A lot of Boilerplate Code can be avoided.
AND: it is reactive, non-blocking.
Example (really, an example) – the ‚old way‘:
HttpPost request = new HttpPost("http://www.someurl.de");
request.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
request.setHeader(HttpHeaders.CONTENT_TYPE,
ContentType.APPLICATION_JSON.getMimeType());
String json = someJsonConverter.toJson(someRequestDto);
HttpEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
request.setEntity(stringEntity);
try {
CloseableHttpResponse response2 = httpclient.execute(request);
if (HttpStatus.SC_CREATED != response2.getStatusLine().getStatusCode()) {
//TODO eventually handle http statuus additionally
return returnHandleAndDoNotThrow();
}
SomeResponseDto responseDto = (SomeResponseDto)
someJsonConverter.toDto(EntityUtils.toString(response.getEntity()),
SomerResponseDto.class);
return Optional.ofNullable(responseDto);
} catch (IOException e) {
return Optional.empty();;
}
The new way:
Function<UriBuilder, URI> function = uriBuilder ->
uriBuilder.path("/somePath").build();
return client.post()
.uri(function)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(someDtoInstance), SomeDto.class)
.exchange()
.block()
.bodyToFlux(someResponseDto.class);
//any errors, status codes are handled by a filter which you can define as follows:
Howto:
I am using Spring Boot for this, so I do have a Config class.
import ...
import org.springframework.context.annotation.Bean;
import reactor.core.publisher.Mono;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebClientConfig {
//Create the Bean for Autowiring
@Bean
public WebClient webClient() {
return WebClient.builder().filter(someStatusHandlingFilter()).build();
}
//Handle status codes
public static ExchangeFilterFunction someStatusHandlingFilter() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if ((clientResponse.statusCode().is4xxServerError()
|| clientResponse.statusCode().is5xxClientError())) {
return clientResponse
.bodyToMono(SomeException.class)
.flatMap(errorBody -> {
return Mono.error(someExceptionToLog);
});
} else {
return Mono.just(clientResponse);
}
});
}
}
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
<version>your latest version goes here</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>your latest version goes here</version>
</dependency>