I am integrating Hystrix into SilverWare microservices platform and I want to use hystrix-javanica annotations. These annotations are meant to be applied on the actual implementation of the methods that need to be executed using Hystrix. The problem is that I need to implement a generic solution where you only have a service interface. It has to be done this way in order to let developers use annotated references to other microservices (when they implement their own service) without any need to deal with the implementation of those services.
I came up with a solution where you annotate your microservice reference with something like this:
#Inject
#MicroserviceReference
#HystrixConfiguration(MyServiceHystrix.class)
private MyService myService;
And then you implement (or extend) the service interface and put Hystrix annotations on its methods:
public interface HystrixedMyService extends MyService {
#HystrixCommand
doSomething();
}
When there is #HystrixConfiguration annotation on a field in your microservice referencing another service, SilverWare will scan the class given as a parameter of this annotation and prepare a Hystrix command for every method of the service. The command will also receive a callable with an actual method invocation which will be executed in its run() method.
My question is: Is it possible to reuse some (internal) parts of hystrix-javanica so I do not need to scan all the annotations and create those Hystrix commands myself? I can see that most of the classes are designed to be used only with AOP.
Related
In a spring boot app, using annotations only, i want to implement security
I have added an #EnableGlobalMethodSecurity(jsr360Enabled=true) to a configuration class. the class also has an #EnableSecurity anntation
Now, when i add a #RolesAllowed to any #RestController class, be it on method level or level, the startup logs don't list the class at all. instead , there is line:
'Rejected bean name (rest controller class): no URL paths identified'.
Does anyone have an idea what might be causing this?
After #M.Deinum set me on the path, i did some reading and have an explanation. If anyone can elaborate more or correct me on the more technical details, feel very welcome.
Spring proxies classes to wire beans together.
Classes that don't implement an interface are proxied by using CGLib to make a subclass with additional functionality
classes that do implement an interface, spring uses dynamic proxy to access the functionality of the class, but doing so it can only proxy interface methods.
in my case, my controller implements an interface with non-endpoint related methods, so spring ignored all handling methods and the RequestMappingHandlerMapping did not find any methods to bind, because if only 'saw' the interface methods on the class
using #EnableGlobalMethodSecurity(proxyTargetClass=true) forces the use of CGLib, so the full methods are recognised by our mapper.
I am developing one task scheduler which triggers the tasks in parallel using executor service. I want to make my task scheduler as generic and no code change/less code change in scheduler code base whenever any new type of task is added.
My tasks (mostly client package) can be of any type which basically just accepts particular request and execute the tasks.
To do this I am exposing interface (say ITask) which must be implemented by tasks (which will be on some other app/package) and that will be having one implementation method say example
doTask(IRequest request);
So the use case is if any clients who wants to trigger their job using my scheduler framework/API, just need to add my package in their dependency and rest (those are, getting the list of task classes which implements ITask > schedule it using executor service > retry failed tasks > finally provide the entire tasks status) should be taken care by my schedular API.
What is the optimal way to do this. I am thinking of solution how Junit gets its #Test methods (based on annotation) of client whoever adds Junit dependency in his package, similarly I want get classes based on interface.
You have tagged this question with Spring, but you don't mention anywhere in the question that you are using the Spring framework. This answer makes a few assumptions:
You are using Spring Framework
The implementations of your desired interface have been configured as Spring Beans
If you get access to the ApplicationContext (see the interface ApplicationContextAware), you can use it to look up Spring beans of a certain type. It would look something like this:
Map<String, ITask> beans = appContext.getBeansOfType(ITask.class);
This method returns a map with the key being the bean identifier and the value being the instance of the bean itself. From there, you could loop through the values and add them to your job scheduler.
Alternatively
If you do not want the requirement of having to configure each ITask implementation as a Spring bean, you could use Spring's ClassPathScanningCandidateComponentProvider (a mouthful, I know).
This is a nifty tool that allows you to scan base packages to find bean "candidates". However, in your case, you could use it to find ITask candidates. Clients to your library could configure the base scan packages which you would use to scan:
private String configuredListOfBasePackages;
public void someMethod () {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AssignableTypeFilter(ITask.class));
Set<BeanDefinition> iTaskCandidates = scanner.findCandidateComponents(configuredListOfBasePackages);
// do stuff with the bean definitions
}
This method is obviously a bit more dangerous as it require you to be able to construct a new instance of every candidate you find. As such, this is not the ideal solution.
I'm currently converting a piece of code from plain Java code to OSGi Declarative Services.
Original plain Java code
new AggregateServiceImpl(
new ChildServiceImpl1(),
new ChildServiceImpl2(),
new ChildServiceImpl3()
);
The classes are declared as so:
class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service
So all classes implement Service, but the Aggregate implementation is capable of deferring to child Services when called upon.
AggregateServiceImpl itself does not know of the other implementations' existence. Its constructor is originally declared as:
public class AggregateServiceImpl(Service... children)
Clarification: the interface name 'Service' is intended generically and is not meant to represent an OSGi DS or Service concept.
Converting to OSGi
First I move each implementation into its own bundle. Then I declare my components (service implementations). I happen to be using bnd, so I use service annotations. For example:
#Component
class ChildServiceImpl1 implements Service
In the client class, we can look up the Service using the low level OSGi API or use DS in that bundle to create the object for us.
Problem
What's the best way of looking up a 'Service'? I want the AggregateServiceImpl but I might receive one of the ChildServiceImpls.
Is it best to use a separate service type or add a property to one of the components (e.g. "isRootService") to use as a filter when looking up ServiceReferences?
The best way is to use service registration properties
#Component
#Service
#Property(name = "service.id", value = "<some service unique ID")
class ChildServiceImpl1 implements Service{...}
When you look for some specific services you can use service filter:
bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");
or if you like to use it in DS component as service reference:
#Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;
If the AggregateServiceImpl is the only Service being used by other bundles, then it should be the only one you register.
From the code you have currently shown, we cannot tell if the AggregateServiceImpl class has dependencies on Service or the actual implementations.
If it has dependencies directly on other implementations, not the Service interface (as you have currently described it) the aggregate bundle should create the other implementation classes it requires directly and then register the AggregateServiceImpl as a Service.
If the other implementations need to be used elsewhere as well, then you should use properties (as you suggested) so consumers can distinguish between them. In this case, you still cannot use DS to construct your aggregate, since it doesn't have a dependencies on Service
I'va a ServiceImpl with is annotated with #Service stereotype of Spring and have two methods in it each one is annotated with custom annotations which are intercepted by Spring.
#Service
public class ServiceImpl implements Service{
#CustomAnnotation
public void method1(){
...
}
#AnotherCustomAnnotation
public void method2(){
this.method1();
...
}
}
}
Now Spring uses proxy based AOP approach and hence as I'm using this.method1() interceptor for #CustomAnnotation will not able to intercept this call, We used to inject this service in another FactoryClass and in that way we were able to get the proxy instance like -
#AnotherCustomAnnotation
public void method2(){
someFactory.getService().method1();
...
}
I'm now using Spring 3.0.x, which is the best way to get the proxy instance?
The other alternative is to use AspectJ and #Configurable.
Spring seems to be going towards these days (favoring).
I would look into it if you are using Spring 3 as it is faster (performance) and more flexible than proxy based aop.
Both methods are inside the same proxy, whereas the AOP functionality just enriches calls from the outside (see Understanding AOP Proxies). There are three ways for you to deal with that restriction:
Change your design (that's what I would recommend)
Change proxy type from JDK-proxy to proxy-target-class (CGLib-based subclassing) Nope, that doesn't help, see #axtavt's comment, it would have to be static AspectJ compilation.
Use ((Service)AopContext.currentProxy()).method1() (Works, but is an awful violation of AOP, see the end of Understanding AOP Proxies)
You could make your ServiceImpl class implement the BeanFactoryAware interface, and lookup itself thanks to the provided bean factory. But this is not dependency injection anymore.
The best solution is to put method1 in another service bean, which would be injected in your existing service bean and to which your existing service bean would delegate.
I had the following set-up which worked perfectly fine:
#Service
public class MyService {
}
public class Test {
#Autowired
MyService service;
}
I changed MyService to implement a new interface, like this
#Service
public class MyService implements NewInterface {
}
There's nothing special in this interface, it's just a normal Java interface without any annotation and 2 very simple methods.
Now, Spring is not able to autowire this bean anymore, it gives a NoSuchBeanDefinitionException. I also tried to define it explicitly in the XML but it gave the same exception.
In case it's relevant, I'm using Spring 2.5 and build with Maven, the class Test is a unit test class. When I try to run the real application, it's using applicationContext.getBean() to get this service, and it gives the following exception: java.lang.ClassCastException: $Proxy81 cannot be cast to MyService.
What am I missing and what should I do?
When you see a class with a name like $Proxy81, it's telling you that Spring has auto-generated a proxy object for one of your beans, in this case a proxy object for the MyService bean. This uses java.lang.reflect.Proxy to generate the proxy object. This proxy object will implement the same interfaces as the class that's being proxied, but it will not be type-compatible with the target class itself.
Now, if the target class doesn't implement any interfaces, then Spring will instead use CGLIB to generate the proxy. This proxy will be a subclass of the target class, so the proxy object can be safely cast to the original type of the target object.
Now, when using the lower-level proxy-generation stuff in Spring, you can often override this behaviour, and tell it to always use CGLIB proxies, but I'm assuming that since you're using #Service, then you're also using <context:component-scan>, in which case I think you have to stick with the default behaviour.
It's not bad thing, though. This encourages you to not couple your classes together, but instead to program to interfaces. Any interaction with MyService should be expressible via interfaces, although this concept can get a little fuzzy when talking about unit testing.
It looks like you're autowiring by interface instead of autowiring by class name.
I'd simply code my test against the Interface:
public class Test {
#Autowired
NewInterface service;
}
Also, check this bug, it might be relevant to you since it appears like your class is being proxied.