Reputation: 183
I'm looking at using Spring's @Sync annotation, and I'm running into some quirky behavior. I've put together a very simple test case, which just doesn't work (my asynchronous method does not get called). Tweaking the test case in certain ways does induce the method to be called, but it's hard to understand why. Anyway, here are the details. I'm using annotation-based configuration and autowiring.
I've tested with Spring 3.1.1 and 3.2.3.
a) Spring context file:
<context:annotation-config />
<context:component-scan base-package="sample" />
<task:annotation-driven />
b) Class containing asynchronous method:
package sample;
@Component
public class SomeServiceImpl {
@Async
public void asynchMethod(String in) {
logger.debug("Starting asynchMethod");
logger.debug("Ending asynchMethod");
}
public void doNothing() {
}
}
c) Unit Test (in class TestSomeService):
@Test
public void testAsynch() throws InterruptedException {
logger.debug("Starting testAsynch");
service.asynchMethod("hello asynch");
logger.debug("Ending testAsynch");
}
Here is the unit test result:
[DEBUG] [2013-06-13 09:18:10,350] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:18:10,353] [sample.TestSomeService] - Ending testAsynch
No output from the asynchronous method - so that's problem #1. The example is so simple, I'm not seeing why it's not working.
NEXT - if I modify the test by adding a call to the synchronous method "doNothing()":
@Test
public void testAsynch() throws InterruptedException {
logger.debug("Starting testAsynch");
service.doNothing();
service.asynchMethod("hello asynch");
logger.debug("Ending testAsynch");
}
The async method DOES get executed:
[DEBUG] [2013-06-13 09:20:59,493] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.TestSomeService] - Ending testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Ending asynchMethod
I can't fathom why first calling a synchronous method would make the async method call work.
NEXT - still more puzzling: if I put my unit test to sleep for a second after calling the async method - the async method does execute.
@Test
public void testAsynch() throws InterruptedException {
logger.debug("Starting testAsynch");
service.asynchMethod("hello asynch");
Thread.sleep(1000);
logger.debug("Ending testAsynch");
}
[DEBUG] [2013-06-13 09:22:21,187] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Ending asynchMethod
[DEBUG] [2013-06-13 09:22:22,190] [sample.TestSomeService] - Ending testAsynch
I'm baffled as to why the simple case does not work, and why the other two modifications do work. Can anyone see what I'm missing?
Upvotes: 0
Views: 2504
Reputation: 4663
The Junit run ends (JVM halts) before the thread executing the async call has a chance to run, hence the sleeps helps.
Upvotes: 2