Is this the correct way to use @Async
in Spring Boot?
@Service
class someServiceImpl {
...
public someResponseDTO getUsers(int userId) {
// Do some logic
...
// Call external API with another service method from another service impl
anotherService.emailUserInTheBackground(userId);
return someResponseDTO;
}
...
}
@Service
public class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
// This might take a while...
...
}
}
Since emailUserInTheBackground()
has @Async
annotation and void
return type, does it block the line return someResponseDTO
at all?
All I wanted is to return the response to the caller without waiting because emailUserInTheBackground()
takes too long to complete and isn't directly tied to the response object.
Yes that is the correct way to run a task in the background, you can mimick the thread blocking behavior by introducing a delay.
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] arg) {
SpringApplication.run(MyApplication.class);
}
}
then you need to mark the emailUserInTheBackground method with @Async
annotation.
@Service
class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("Print from async: "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now add one more logger after a method call, you'll see getUsers(...)
call completing first in a different thread even though the emailService thread is blocked for 10 seconds.
anotherService.emailUserInTheBackground(userId);
System.out.println("Print from service: "+ Thread.currentThread().getName());
you can also use CompletableFuture to run a task in the background.
public someResponseDTO getUsers(int userId) {
// some other task
...
// Call external API with another service method from another service impl
CompletableFuture.runAsync(() -> anotherService.emailUserInTheBackground(userId))
return someResponseDTO;
}