I have a requirement to write Spring Webflux endpoint ( Router function ) to send out mail to list of the mail recipients. UI will select the list of mail recipients and sends out the list to the API that I will be writing. Im looking to imlement the endpoint in such a way as soon I receive the request, I should send out the response to the UI saying the Emails are being sent. After sending the response, I should continue the mail sending work asynchronously. I can't use @async annotation like we use in Spring MVC as it an anti pattern in the reactive world.
Since Im using spring webflux to develop API, how can i send the repsonse.
I have a below strucuture in my code.
Router.java
@Bean
public RouterFunction<ServerResponse> sendEmail() {
return route(POST("/email").and(accept(APPLICATION_JSON)), handler::sendEmail);
}
Handler.java
@Autowired
EmailService emailService;
public Mono<ServerResponse> sendEmail(ServerRequest request) {
Mono<PojoA> pojoAMono = request.bodyToMono(PojoA.class);
return pojoAMono.flatMap(pojoA -> {
return emailService.sendEmail(pojoA).flatMap(mailSent -> {
return ServerResponse
.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body("Mails are being sent", String.class));
});
});
}
You could just directly return the response to the caller and after that stream completes run the email sending as a side effect. This can be done with doFinally
that is executed after the stream completes.
So your code could look like this:
public Mono<ServerResponse> sendEmail(ServerRequest request) {
return request.bodyToMono(PojoA.class)
.map(this::sendEmailSideEffect)
.flatMap(pojoA -> ServerResponse
.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body("Mails are being sent", String.class));
}
private Mono<PojoA> sendEmailSideEffect(PojoA pojoA) {
return Mono.just(pojoA)
.doFinally(signalType -> emailService.sendEmails(pojoA));
}
You should build the response and then process the data (send email).
Something like this:
@Bean
public RouterFunction<ServerResponse> sendEmail() {
return route(POST("/test").and(accept(APPLICATION_JSON)), this::someMethod);
}
Mono<ServerResponse> someMethod(ServerRequest serverRequest) {
return ServerResponse.ok().build()
.doOnNext(r -> Mono.just("data") //doing some process like send email
.delayElement(Duration.ofSeconds(2))
.subscribeOn(Schedulers.parallel())
.log()
.subscribe());
}
For testing purpose, I put a delay to you see the data processing after response sent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.