Reputation: 1040
I have a Springboot application and I'm trying to execute an asynchronous method on a bean class inside a controller method. The problem is that my @Async method is not being executed asynchronously. Execution is halted until the method completes.
Can anyone tell me what I'm missing?
Here is my application class:
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(9000);
connector.setAsyncTimeout(60000);
}
});
return factory;
}
}
Here is my bean class:
public class LongProcess {
@Async
public Future<String> call() {
try {
System.out.println("Sleeping now...");
Thread.sleep(10000);
return new AsyncResult<String>("Hey");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
My configuration class:
@Configuration
@EnableAsync
public class LongProcessConfiguration implements AsyncConfigurer {
@Bean
public LongProcess longProcessBean() {
return new LongProcess();
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(10);
taskExecutor.setThreadNamePrefix("LULExecutor-");
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
My controller method:
@RequestMapping("/utilities/longProcess")
public String longProcess() {
System.out.println("Starting long process...");
CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();
LongProcess process = context.longProcessBean();
Future<String> result = process.call();
System.out.println("Done!");
return "{success: 1}";
}
This request unfortunately does not return immediately (I don't care about the result). The method is called successfully, but not in the background. Any idea what I might be missing?
As a test, if I change the controller method to wait for the result, the wait block is never entered:
@RequestMapping("/utilities/longProcess")
public String longProcess() throws InterruptedException {
System.out.println("Starting long process...");
CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();
LongProcess process = context.longProcessBean();
Future<String> result = process.call();
while (!(result.isDone())) {
Thread.sleep(1); //10-millisecond pause between each check
System.out.println("Waiting for Long Process...");
}
System.out.println("Done!");
return "{success: 1}";
}
Upvotes: 2
Views: 2180
Reputation: 121550
You have a mistake for the CDI usage.
If you manage your object using Spring Container you have to get deal just with ApplicationContext
or its abilities like @Autowired
.
The code
CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();
is wrong.
Since you define your LongProcess
as a @Bean
you can just inject it to your @Controller
:
@Autowired
privete LongProcess process;
and use it as before.
Using objects directly (e.g. new
) loses the dependency injection
features.
Read more Spring Docs, please.
Upvotes: 1