My [basic] Spring Boot application accepts a request from the browser, sent via jQuery.get()
and is supposed to immediately receive a response - such as "your request has been queued". To accomplish this, I wrote a controller:
@Controller
public class DoSomeWorkController {
@Autowired
private final DoWorkService workService;
@RequestMapping("/doSomeWork")
@ResponseBody
public String doSomeWork() {
workService.doWork(); // time consuming operation
return "Your request has been queued.";
}
}
The DoWorkServiceImpl
class implements a DoWorkService
interface and is really simple. It has a single method to perform a time consuming task. I don't need anything returned from this service call, as an email will be delivered at the end of the work, both for failure or success scenarios. So it would effectively look like:
@Service
public class DoWorkServiceImpl implements DoWorkService {
@Async("workExecutor")
@Override
public void doWork() {
try {
Thread.sleep(10 * 1000);
System.out.println("completed work, sent email");
}
catch (InterruptedException ie) {
System.err.println(ie.getMessage());
}
}
}
I thought this would work, but the browser's Ajax request waited for 10 seconds before returning the response. So the controller mapped method is calling the internal method annotated with @Async
synchronously, it would seem. In a traditional Spring application, I typically add this to the XML configuration:
<task:annotation-driven />
<task:executor id="workExecutor" pool-size="1" queue-capacity="0" rejection-policy="DISCARD" />
So I thought writing the equivalent of this in the main application class would help:
@SpringBootApplication
@EnableAsync
public class Application {
@Value("${pool.size:1}")
private int poolSize;;
@Value("${queue.capacity:0}")
private int queueCapacity;
@Bean(name="workExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(poolSize);
taskExecutor.setQueueCapacity(queueCapacity);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
This did not change the behavior. The Ajax response still arrives after 10 seconds of sending the request. What am I missing?
The Spring Boot application can be downloaded here. With Maven installed, the project can be run with the simple command:
mvn clean spring-boot:run
Note The issue was resolved thanks to the answer provided by @Dave Syer below, who pointed out that I was missing @EnableAsync
in my application, even though I had the line in the code snippet above.
See Question&Answers more detail:
os