I am using Spring's AOPContext.currentProxy() in a #service class implementation. However, i am using it in a static method and I do something like
public static void addCustomer() {
//....
((CustomerService) AopContext.currentProxy()).addCustomer();
//...
However, I am getting the error -- "cannot find proxy" set expose-proxy to true.
Is using static method the reason for this kind of error?
Note: "addCustomer" method is also static
Thanks in advance.
Proxy configuration is injected at the time of the instance creation. Suppose Using this proxy created instance you are calling to the method AOP is applicable to that method. Suppose without proxy instance or using class name ( in the case of static ) you are calling to the method it is direct call proxy config is not injected to the instance, So AOP is not applicable to that method call.
I'm not sure what you are trying to do, but you cannot do it this way at all.
Invocations of static methods are resolved at compile time, therefore they cannot be affected by proxy-based AOP. In other words:
AopContext.currentProxy() inside a static method doesn't make sense (unless you want to get a proxy for enclosing call of some instance method), because invocation of static method is not proxied
Calling a static method on an instance returned by AopContext.currentProxy() doesn't make sense, because it's resolved at compile time using a static type of expression, i.e. it compiles into CustomerService.addCustomer().
Does your configuration include something like <aop:config expose-proxy="true" />?
Related
I'm trying to Mock ValidatorService in unit tests of SubscriptionInterceptor.
validator = Mockito.mock(ValidatorService.class);
Mockito.when(validator.validateSubscription(any(), any(), any())).thenReturn("");
interceptor = new SubscriptionInterceptor(validator);
Later, when the interceptor calls the validateSubscription method of the mocked validator, an instance of the actual class is invoked, rather than the mock. Why? How can I get the method call to return an empty String?
Resolved in comments:
Method was declared final.
Mockito works by providing a proxy (subclass) of the class in question, with each of the methods overridden. However, for final classes and methods, Java assumes that it can detect which implementation it needs to call, and skips the dynamic method lookup. Because of this, Mockito cannot override behavior for final methods, static methods, or methods on final classes, and because you're not interacting with the mock Mockito cannot even warn you about it.
This is a very common problem; be sure to check for final fields if Mockito is not working for stubbing/verifying your method.
In order not to remove final, static fields/classes/methods in main java sources you could put mocks initialization after mockito's "when/then" stubs.
It will call a constructor for the mock object with finals after all stubs initialization.
Try:
Mockito.when(validator.validateSubscription(any(), any(), any())).thenReturn("");
validator = Mockito.mock(ValidatorService.class);
interceptor = new SubscriptionInterceptor(validator);
Spring AOP weaving process is done at runtime when the request to that specific method is made then a new proxy object will be created which wraps your current object and the call is intercepted.
Am I correct with my assumption?
Second thing is if this process is runtime then what are static pointcuts? when these pointcuts are evaluated?
Your understanding is wrong. A proxy is created only once at startup of the application not each time a method is called on an object. (Unless you have an AOP Scoped Proxy which is prototype scoped, but that scenario is highly unlikely).
#Aspect
public MyAspect {
#Pointcut("execution(* foo.bar.MyService.foo(..)) and args(x, ..)"
public Object around(ProceedingJoinPoint pop, MyObject x) { ... }
}
Given the aspect above the execution(* foo.bar.MyService.foo(..)) is the static part of the joinpoint, it can be matched regardless of inspection of types. The args(x, ..) however is dynamic as it needs to be determined at runtime if the value for x (the first argument in this case) is of type MyObject.
That part cannot be determined statically but only during the actual invocation. Basically anything that depends on runtime informations is dynamic in nature.
I thought the Spring annotations were supposed to work out of the box in a Grails environment, but I cannot get it to work at all. I also tried the afterProperties method, which did not work either.
Can anyone spot a mistake? Is there some configuration I need to do?
package dashboard
import javax.annotation.PostConstruct
class EmailJobSchedulerService
{
def grailsApplication
#PostConstruct
def init() {
def cronExpression = grailsApplication.config.emailAt8AmTrigger
println(cronExpression)
EmailSubscribersJob.schedule(cronExpression, new HashMap())
}
}
Try changing it to
#PostConstruct
void init() {
(i.e. void instead of def). I'm not sure whether Spring specifically enforces this but the specification of #PostConstruct states that among other things "The return type of the method MUST be void".
Edit: uchamp's comment is correct, I just tried the same test and indeed the #PostConstruct annotated method is called only the first time the service bean is used and, not necessarily immediately at startup. You can add
static lazyInit = false
to the service class to force it to be initialized eagerly at startup. This doesn't appear to be documented in the user guide, I deduced it by reading the code.
Note that "used" in the previous paragraph doesn't necessarily mean you have to call a method on it. The service bean will be initialized the first time it is fetched from the application context, either directly or because it has been autowired into another bean that is being initialized. For example, injecting the service into BootStrap using
def emailJobSchedulerService
would be enough to fire the #PostConstruct method, you don't have to actually call any of the service's methods from the BootStrap.init closure. Similarly, if your service were injected into any controllers then the init would fire the first time one of those controllers handled a request (any request, it doesn't have to be an action that calls the service).
Just adding on the answer from #Ian - For some reason i had:
#PostConstruct
private void init() {
This also failed silently and gave strange behavior. Solution was to remove "private":
#PostConstruct
void init() {
I have created a custom scope in my application that implements org.springframework.beans.factory.config.Scope.
As part of this, i have to implement the method below so that the PreDestroy method gets correctly invoked on my custom scoped beans.
public void registerDestructionCallback(String name, Runnable callback) {
}
The javadocs on the method are not that clear and I seem to be lost about what code i should write in that method.
Can someone please help?
It depends on what your custom scope actually does and if you are using this scope for DisposableBean, beans with destroy-method, and DestructionAwareBeanPostProcessor.
In simplest case you don't need to do anything or just log a warning that callback is not supported.
In more complex case, you need to handle object destruction that is outside of regular custom scope life cycle. Eg. when object is destroyed, based on its expiration or something similar (unlike explicit call to Scope.remove(String name) method).
For example, for session-scoped beans, this callback is hooked up to HttpSessionListener.sessionDestroyed(..) event. See sources for org.springframework.web.context.request.SessionScope class.
I have a class that uses a static block to initialize a static Hashtable. This is done by reading a properties file, parsing the contents of the file, and then setting the appropriate values into the Hashtable.
However, instead of specifying the location of the file, I would like to inject the location instead using Spring, basically to eliminate any hard-coded values in the class. I did see somewhere else that it is in fact possible to inject into a static variable, but that it will involve the use of a non-static setter.
So my question is--will the invocation of the setter happen before the static block is executed, or will the static block execute first before Spring invokes the setter (which will basically cause an exception in my code)?
Thank you!
The static initializer is executed by the classloader as part of loading the class before any code is granted access to the class. Since Spring must instantiate the class--which definitely requires loading the class--before it can call setters on that instance, the static initializer block has already run.