When implementing an Interceptor, is there a way to get the name of the actual (concrete) class being intercepted using the InvocationContext ?
Unless I am wrong, calling ic.getMethod().getDeclaringClass().getName() will return the (extdended) interface / base abstract class?
Is the #Intercepted annotation the only way of getting the actual implementation being intercepted?
In the past, I have used the following to get the name of the intercepted class:
public Object audit(InvocationContext invocation) throws Exception
{
final String name = invocation.getTarget().getClass().getName();
...
The "target" in this context is the class that is being intercepted.
Related
I have a class called
ServiceImpl
which implents the interface
Service
I have a method in another jar which I want to call but it takes
Service
as input. Here is the method:
public void setService(Service service) {
context.setService(service);
}
I tried to use reflection to call this method
final ServiceImpl myService = new ServiceImpl(param1, param2);
method = beanClass.getMethod("setService",Service.class);
method.invoke("setService", myService);
However I get the error:
Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
It is saying that it expects a Service class but I am passing in an object of type ServiceImpl. But why should that be a problem, since ServiceImpl has implemented Service? How can I work around this?
You're trying to call setService on a string object, "setService". Method#invoke's first parameter is the object to call the method on, not the name of the method (it already knows who it is).
You wanted:
method.invoke(bean, myService);
...where bean is an instance of the class whose Class object beanClass refers to.
It is not the Service parameter that the reflection is complaining about, it is the first parameter. Effectively, your code attempts to do this:
"setService".setService(myService);
which does not work for obvious reasons.
Pass the object on which you want to set the service as the first parameter to fix this problem:
method.invoke(instanceOfBeanClass, myService);
I have multiple modules with service interfaces binding to their corresponding types and I am able to get an instance by using
injector.getInstance(MyServiceInterface.class)
I would like to retrieve the instance using
injector.getInstance("MyServiceInterface")
i.e. a string literal instead of the class type
How can I achieve this ?
To elaborate my question further - I can retrieve the Class object from the string literal using a Class.forName(literal) call and then use it to retrieve the instance with a injector.getInstance(clsInstance) .
After retrieving the instance which I receive in my base service type interface I need to use reflection to invoke the method of the service object.
so Service serv = injector.getInstance(MyCustomService.class)
Now I need to invoke myCustomMethod() present in MyCustomService through reflection since this invoker is generic and is intended to work with multiple services without being aware of their actual type.
I will also need the Method interceptors configured on the service interfaces to be invoked transparently when I invoke the method on this instance reflectively.
While I'm not certain if there's functionality for that built into Guice itself, you could try getting the relevant Class<?> object yourself.
Something along the lines of:
Class<?> myServiceInterfaceClass = Class.forName("path.to.MyServiceInterface");
injector.getInstance(myServiceInterfaceClass);
This does however require that the current Classloader can access that specific class, etc.
This can't be done within Guice... because it can't be done, period! Think about it, let's say you have two of the same class name in different packages. Which class would you instantiate?
So at the very least the String would have to have the fully qualified class name, e.g. instead of Integer, it would have java.lang.Integer.
However, if you know which classes you want to support in advance, you can use a MapBinder.
Tweaking their example to match your use case:
public class ServiceModule extends AbstractModule {
protected void configure() {
MapBinder<String, MyServiceInterface> mapbinder
= MapBinder.newMapBinder(binder(), String.class, MyServiceInterface.class);
mapbinder.addBinding("MyServiceInterface").to(MyServiceImpl.class);
bind(MyServiceInterface.class).to(MyServiceImpl.class);
}
}
Now you can inject like this:
class ServiceManager {
#Inject
public ServiceManager(Map<String, MyServiceInterface> services) {
MyServiceInterface service = stacks.get("MyServiceInterface");
// etc.
}
}
Please note when you call inj.getInstance() you do have to know the return type of the Object you're trying to create, unless you are planning on doing:
Object foo = inj.getInstance(myString);
Actually , what i want to invoke is a service method, so some people are saying that with regular reflection , how can one load autowired elements? I am new to spring framework. I am working on web application designed using Spring-hibernate framework.
So in one case i saved class name and method name in DB. And now i want to invoke method via reflection:
Class cls = Class.forName("com.xyz.pqr.Invest");
Object obj = cls.newInstance();
//call the printIt method
Method method = cls.getDeclaredMethod("exec", noparams);
method.invoke(obj, null);
by fetching class name and method name from DB. But its not fulfilling my purpose. Kindly tell how to invoke method via reflection using spring . I googled it out and something like to implement ApplicationContextAware i found. But not clear idea.
Actually , what i want to invoke is a service method, so some people are saying that with regular reflection , how can one load autowired elements?
Invest is a service class , in that we have api exec to process some data
public void exex(int a, int b, String c){**}
thanks
What you need to do is make your caller ApplicationContextAware and use the getBean() method to get the instance of the Invest class instead of cls.newInstance().
Something like below;
public TheCaller implements org.springframework.context.ApplicationContextAware {
/** The spring application context */
#Autowired
private org.springframework.context.ApplicationContext springContext;
public void callService(String serviceName, String theClass, String methodName) {
Class cls = Class.forName(theClass);
Object obj = applicationContext.getBean(serviceName); // Or use applicationContext.getBeansOfType(cls)
Method method = cls.getDeclaredMethod(methodName, noparams);
method.invoke(obj, null);
}
}
The serviceName is the name of the bean configured in spring.
My issue is quite simple, I hava a generic parent class with the following JAXRS definition
#POST
#Restricted(permissions = {"*_create"})
public Response save(T entity) throws Exception {
And I created a specific child class with generic parameter T becoming Access type, which have the following declaration:
#POST
#Restricted(permissions = {"*_create"})
#Consumes({"application/x-www-form-urlencoded", "application/json", "application/xml"})
public Response save(final Access newAccess, #HeaderParam("Authorization") String token, #Context HttpServletRequest request) throws Exception {
My issue is that Resteasy has apparently a random behavior that is set on war launch that it will keep for application lifetime. Some time it associates the incomming POST request to the parent save method, sometime to the child one. I aim to get the child one being systematically used, but I want to avoid to change my parent class as lot's of resource defining classes in my project rely on it with no issue (and do not override the save method for instance). Is there an easy (like in resteasy) way to fiw this issue ?
As for now the solution I found was to override the parent method signature public Response save(T entity) throws Exception in the child class, without any annotation but the #Override. The method definition contains a throw new UnsupportedOperationException();.
#Override
public Response save(Access entity) throws Exception {
throw new UnsupportedOperationException();
}
This make the other save declaration with jaxrs annotation in this child class to be chosen without ambiguity.
I am interested in getting the class being proxied from spring, rather than the proxy.
ie:
public class FooImpl<KittyKat> {
#Transactional
public void doStuff() {
getBar();
// java.lang.ClassCastException: $Proxy26 cannot be cast to
// com.my.foo.Bar
}
}
public abstract class AbstractFoo<T extends AbstractBar> {
public String barBeanName;
protected T getBar() {
// java.lang.ClassCastException: $Proxy26 cannot be cast to
// com.my.foo.Bar
return (T)appContext.getBean(barBeanName);
}
}
public class KittyCat extends AbstractBar {
...
}
public abstract class AbstractBar {
...
}
Are you trying to get the proxied bean only because of the ClassCastException? If you could cast to Bar, would you happy with that?
When Spring creates a proxy, it checks to see if the bean class implements any interfaces. If it does, then the generated proxy will also implement those interfaces, but it will not extend the target bean's class. It does this using a standard java.lang.reflect.Proxy. This seems to be the case in your example.
If the target bean's class does not implement any interfaces, then Spring will use CGLIB to generate a proxy class which is a subclass of the target bean's class. This is sort of a stop-gap measure for proxying non-interface beans.
You can force Spring to always proxy the target class, but how you do that depends on how you created the Bar proxy to begin with, and you haven't told us that.
The generally preferred solution is to refer to your proxied beans by their interfaces, and everything works nicely. If your Bar class implement interfaces, could your Foo not refer to that interface?