I have a spring boot(version 2.1.8.RELEASE) rest application that contain the following mail functionality from the controller:
@PostMapping(value = "/sendMail1")
public @ResponseBody EmailResponse sendMail1( @RequestBody EmailRequestDto emailRequestDto) {
if (checkAllEmailAddValid(emailRequestDto)) {
sendMailService.sendEmail(emailRequestDto);
//return new ResponseEntity<>("Mail has been sent successfully", HttpStatus.OK);
return new EmailResponse(HttpStatus.OK, "Mail has been sent successfully");
} else {
LOG.error("Email addresse provided is invalid");
//return new ResponseEntity<>("Email address provided is invalid", HttpStatus.BAD_REQUEST);
return new EmailResponse(HttpStatus.BAD_REQUEST, "Email address provided is invalid");
}
}
An method to send mail for the service class is :
@Override
@Async("threadPoolExecutor")
public void sendEmail(EmailRequestDto emailRequestDto) {
LOG.debug("calling method sendMail");
...
}
I have deployed the above rest service on my machine and accessible with the url(http://localhost:9090/email-service/email/sendMail1). However when I use Spring WebClient to call the web service the following error is displayed and the web service is not called at all:
java.lang.IllegalStateException: The underlying HTTP client completed without emitting a response
Please find below my integration test to call the web service:
@Test
public void test() {
EmailRequestDto emailRequestDto = new EmailRequestDto();
emailRequestDto.setMailTo((Arrays.asList("[email protected]")));
emailRequestDto.setEmailContent("Dear Sir");
emailRequestDto.setMailFrom("[email protected]");
emailRequestDto.setSubject("Sending Email subject - 17102019-0905");
emailRequestDto.setFileHtml(true);
WebClient webClient = WebClient
.builder()
.baseUrl("http://localhost:9090/email-service/email")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
Mono <EmailResponse> rs = webClient.post().uri("/sendMail1").body(Mono.just(emailRequestDto), EmailRequestDto.class).retrieve().bodyToMono(EmailResponse.class);
System.out.println(rs);
}
When I execute the same functionality with Postman client plugin the web service is called successfully.
Any idea what i am missing here please?
When debugging with WebClient, logRequest and logResponse is very helpful. Most likely, a non-2xx status code is returned from email server.
public static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(response -> {
logStatus(response);
logHeaders(response);
return logBody(response);
});
}
both logStatus and logHeader are straightforward, because one can easily get that information from response. logBody is tricky one:
private static Mono<ClientResponse> logBody(ClientResponse response) {
if ((response.statusCode().is4xxClientError() || response.statusCode().is5xxServerError())) {
return response.bodyToMono(String.class)
.defaultIfEmpty(response.statusCode().getReasonPhrase()) response"
.flatMap(body -> {
log.info("Body is {}", body);
return Mono.just(response);
});
} else {
return Mono.just(response);
}
}
In above code, defaultIfEmpty is needed for responses that do not have a body, this is common when response code is non-2xx. and otherwise you will get an error like IllegalStateException The underlying HTTP client completed without emitting a response. The reason is probably as stated in
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With