Method with Spring #Async annotation not executed - java

I use spring #Async annotation to execute certain tasks. At some point (maybe because the pool-size was reached) I see in the debugger that the method with #Async is called but the break point in the method is not reached. I do not know it it will be called when another #Async method is finished or it is skipped forever.
I would like to know if it is possible to trigger an exception when there are not free #Async to execute it.
In addition, how can I know how many #Async are currently used at any given time
Thanks
Avi

At some point (maybe because the pool-size was reached) I see in the debugger that the method with #Async is called but the break point in the method is not reached.
Are you sure that the code fragment if not blocked by some conditional? Without a valid code sample, one can only speculate at this point.
I would like to know if it is possible to trigger an exception when there are not free #Async to execute it.
A TimeoutException is usually thrown in this case. You can modify the time out value by adding the following to your Spring config XML.
<mvc:annotation-driven>
<mvc:async-support default-timeout="180"/>
</mvc:annotation-driven>
Alternatively have a look at this answer: Providing a timeout value when using #Async for a method using Spring 3.0
In addition, how can I know how many #Async are currently used at any given time
Usually when you activate logging using e.g. sl4j inside the code executed inside an #Async method, you'll see the following output:
2017-03-10 10:27:41,910 [SimpleAsyncTaskExecutor-1] DEBUG
2017-03-10 10:27:43,282 [SimpleAsyncTaskExecutor-2] DEBUG
Hope that this helps!

Related

Spring aspects across multiple threads

Trying to wrap service class with two aspects to get this call chain:
javanica..HystrixCommandAspect -> MyCustomAroundAspect -> MyService
met two problems:
HystrixCommandAspect does not call joinPoint.proceed(). Instead it calls method directly on target class, which effectively skips any other proxies created after javanica's aspect
Hystrix aspect makes subsequent calls running in deferent thread. It leads to message:
"No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor..."
which is reasonable because this interceptor keeps its stuff in thread local.
Questions:
1. Why is Spring APO implemented this way? Is it conceptually wrong to run different aspects in different threads? Are there workarounds except changing the aspects' order?
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
regards
Disclaimer: I am not a Spring or Hystrix user, just an AOP guy.
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
Actually, you have to ask the Hystrix maintainer. It is a good question, actually. the assumption that Hystrix aspects are the only ones in this universe is certainly a bold one because there actually is an AspectJ or Spring AOP contract for #Around advices:
Either the aspect calls the original method. If it does so, it ought to use proceed(). If it proceeds with the original method arguments or with a modified set, is up to the aspect. Also if it proceeds before, after or in between doing other things.
Or the aspect returns a result (for non-void methods) calculated without proceeding to the original method.
Or the aspect throws an exception, not returning any result.
Having said that, I think it is a design flaw in Hystrix not to pass on the ProceedingJoinPoint and eventually call proceed() on it in case the original method is to be called eventually. If I was a Hystrix user, I would open a bug ticket for that.
Besides, it is in principle no problem to call proceed() asynchronously from another thread in which you inject the joinpoint instance upon creation. Then you can put that thread (or a runnable) into a queue and execute it whenever convenient. Technically you can even call proceed() on the same joinpoint instance multiple times, but if the target method is no pure function without side effects you might want to be careful with that and usually won't do it unless your aspect implements some kind of retry scheme (with or without exponential back-off). So Hystrix could to that too. If they do not then they must be doing something ugly instead, such as use reflection to call the original method. I did not check.

Is it possible to resubmit a task to a Spring #Async method?

I have a Spring method annotated with #Async
#Async
public void doSomething(long id, String text) {
//do something
}
The method invokes a remote service, which occasionally times out. Is there a way to catch the timeout and resubmit the task to the #Async method N seconds later?
I doubt calling the annotated method from inside itself will work because Spring uses a pointcut to intercept invocations.
The only way I can think of is to override AsyncExecutionAspectSupport.handleError to rebuild an instanceof MethodInvocation and then call a copy of
AsyncExecutionInterceptor.invoke that lets me specify a delay.
Is there another way? Perhaps someone has already done it?
An Aside
I can imagine a solution whereby #Async is extended to specify cases for retry, in much the same way that transactions are managed in Spring but this is more fundamental than the theoretical solution described above!
#Async(retryOn=TimeoutException.class, maxRetries=2, delayStrategy=DelayStrategy.DOUBLE)

Asynchronously calling synchronized methods?

I want to benefit from asynchronously calling one of my methods. Since I use spring framework, this task is quite trivial, so I just marked the method with #Async annotation.
However my method is using a global variable that is not intended to be used concurrently by multiple threads( you may think of it as javax.jms.Session).
First thing that comes to mind to mark the method with synchronized keyword in order to make sure that method is thread safe.
But on the other hand it will be completely nonsense to use #Async annotation on synchronized method, right?
Is there any benefit to use #Async annotation on method that contains synchronized block ?
The purpose of making something asynchronous is that it will do things in the future, that will take relatively much time, for example file or database operation, and during that time, you can make other useful operations.
In your case, if you do synchronous block inside and async operation, you will lose async functionality making that part of your code block in certain cases. Of course, if you access a shared resource concurrently, you should defend it, the real question here, is that you really need async functionality inside that function? Maybe you can refactor your code to deal with the synchronous resource somewhere else.
Also if you are really into async functionality, and spring, you should check out Spring 5, and what it has to offer, when it's released.
Spring 5.x

Spring async method called from another async method

I'm using Spring 4 and I've noticed an odd behaviour... if I'm calling an async method multiple times from a normal instance method then they are all called in different threads and finish at random times. But if I call multiple times an async method from another async method then they finish in order. I have something like this:
#Async
public void nonAsyncMethod() {
for (int i = 0; i < 30; i++) {
asyncMethod();
}
}
#Async
public void asyncMethod() {
... something here
}
I'm using the default async executor. Should I use a different one? However this executor do not reuse any threads and starts another one every time so it should be fine... Can it be just a coincidence? But I've tried like more than 10 times and if I revert back to non-async for the first method then they finish randomly
What you are describing is a classic pitfall of Spring AOP.
In short, for Spring to be able to provide the async behavior it needs to create a proxy for your class at runtime. The proxy then does whatever it needs to do before and/or after calling your code. But in your case, the proxy mechanism is not being applied for the second method.
When a bean of your class is injected via Spring into some other component, Spring really injects the proxy instead. Therefor the relevant method of the proxy is called. However, when you are calling a method from inside the class, the limitations of Spring AOP mean the proxy never comes into play, but instead the regular method is called - with no extra features.
That is why asyncMethod is always executing on the same thread as the other method in the same class that called it.
Check out this excellent blog post as well as this part of Spring documentation.
There are some ways around the problem (check out this) that don't require you to refactor your code, but if you want async to work on both methods no matter what, the simplest thing to do is refactor the second method into another class.

Poor JUnit test using springframework has fragile Thread.sleep() calls. How to fix?

I have recently joined a group with some severe JUnit testing issues. One problem is an 8 minute long test! The test has several sections; each makes calls to org.springframework.context.ApplicationEventPublisher.publishEvent()
followed by Thread.sleep() of various amounts of time, then tests conditions.
There are several obvious problems with this approach, the timing of the Thread.sleep() calls is fragile:
tests occasionally fail on busy machines; and
tests take far too long when they do not fail.
Is the pool upon which these events are handled accessible for testing and is there a call to see if the event cascade has quiesced?
Worth mentioning is that test code that actually calls external services are integration tests and not unit tests. If you're truly unit testing here you should replace those calls with mocks. That way you can better control the values returned to your business logic and test for specific conditions. Also, as you've seen, this all but eliminates false positives due to external (non-code) situations. Obviously these tests aren't failing, the facility they expect to use is.
You can overwrite the default applicationEventMulticaster by adding this bean id to your application context.
Instead of the default SimpleApplicationEventMulticaster, you could set a TaskExecutor on this bean to perform the event publishing asynchronously in multiple threads.
Or you could implement your own multicaster, which prints out which event listener took so long or was blocking, for how long and on which events. That could help you to track down the real problem of the 8-Minute-Testcase.
Interestingly, the JavaDoc of the SimpleApplicationEventMulticaster, which is used by default by Spring when you are using ApplicationContext, states the following:
By default, all listeners are invoked in the calling thread. This allows the danger of a rogue listener blocking the entire application, but adds minimal overhead. Specify an alternative TaskExecutor to have listeners executed in different threads, for example from a thread pool.
I (intentionally) avoid Spring so I'm not sure I can help with the specifics but just looking at the sleep issue, you can use something like WaitFor in tempus-fugit (shameless plug) to poll for a Condition rather than "sleep and hope". It's not ideal and usually a change in the way you test (as suggested before) is preferable but it does mean you get finer grained "waits" which are more likely to avoid race-conditions / flaky tests and generally speed up the test.
See the project's documentation for details and post back if you find it useful!

Categories

Resources