I have a BE service A which is sending Rest JSON message to microservice B using Feign client:
@FeignClient(name = "mail-service")
@LoadBalancerClient(name = "mail-service", configuration = LoadBalancerConfiguration.class)
public interface EmailClient {
@RequestMapping(method = RequestMethod.POST, value = "/engine/emails/register")
void setUserRegistration(CreateUserDTO createUserDTO);
}
Endpoint:
@RestController
@RequestMapping("/emails")
public class EmailController {
@RequestMapping(method = RequestMethod.POST, value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> register(@Valid @RequestBody CreateUserDTO createUserDTO) {
emailRestService.processCreateUserMessage(createUserDTO);
// Implementation of service to send mail to AWS SES
return new ResponseEntity<>(HttpStatus.OK);
}
}
Rest Endpoint is sending mail to AWS Ses mail or other mail provider.
The issue is that the fist call from Feign can take 5 seconds and more. I need to make it Async in order FE client not to wait for the mail to be send.
How I can make the Rest call made from Feign Async to there is no wait time for the http response OK to be expected? Is there some better solution to implement this?
AFAIK, Feign does not allow for non-blocking IO, it is a work in progress.
But you can implement your EmailRestService
async. Consider the following code (I do no know if processCreateUserMessage
is responsible for sending the email as well, but the solution proposed should be extensible to that functionally if necessary):
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
//...
@Service
public class EmailRestServiceImpl implements EmailRestService {
//...
@Async
public void processCreateUserMessage(CreateUserDTO createUserDTO) {
// Implementation of service to send mail to AWS SES
// ...
}
}
Please, note the @Async
annotation definition.
To enable Spring asynchronous processing, you need to define the @EnableAsync
annotation, in your main configuration or in a specific one:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfiguration {
}
There is no need to change your Controller
, although you can return a more convenient HTTP status code if you prefer to:
@RestController
@RequestMapping("/emails")
public class EmailController {
@RequestMapping(method = RequestMethod.POST, value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> register(@Valid @RequestBody CreateUserDTO createUserDTO) {
// Will be executed asynchronously and return immediately
emailRestService.processCreateUserMessage(createUserDTO);
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
}