Request is not send with subscribe - java

I'm trying to run this code:
Mono<String> personMono = Mono.just("wfw");
WebClient client = WebClient.create("https://webhook.site");
Mono<Void> result = client.post()
.uri("/a6ad3a35-61c6-4bfc-8d8c-7e5a3e2462aa")
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, String.class)
.exchange()
.flatMap(response -> response.bodyToMono(Void.class));
result.subscribe();
But request is not send. Do you know what I need to add in order to make POST request? I can't find what I'm missing?

Related

Access response status code for successful requests using Spring WebClient

I need to be able to access the status code of a request. The call can be successful in either of two ways 200 or 201. This is obvious when calling via postman but using the web client, so far I haven't been able to determine which has occurred.
webClient.post()
.uri(url)
.header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.AUTHORIZATION, bearerToken)
.bodyValue(bodyMap)
.retrieve()
.onStatus(
HttpStatus.BAD_REQUEST::equals,
response -> response.bodyToMono(String.class).map(Exception::new))
.bodyToMono(Map.class)
I was thinking maybe I could set an integer variable using within the onStatus() lambda function. Is it even possible to access external variables within a lambda function?
int responseStatus;
// post call
.onStatus(
HttpStatus.CREATED::equals,
response -> ... // do something to set responseStatus
You could use .toEntity(Class<T> bodyClass) method to get entity wrapped in response object ResponseEntity<T>
var response = webClient.post()
.uri(uri)
.retrieve()
.toEntity(Map.class)
.map(res -> {
if (res.getStatusCode().equals(HttpStatus.OK)) {
...
}
return res.getBody();
});

How to convert Spring WebClient Response to ResponseEntity?

I'm able to return ResponseEntity using toEntity() method like below:
#GetMapping("/uri")
public Mono<ResponseEntity<Data[]>> methodName() {
return webClient
.get()
.uri("http://localhost:8088/externalService")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.toEntity(Data[].class);
}
But I want to process response headers before returning.
The above code converts WebClient response to ResponseEntity and returns immediately but I want to store it in a ResponseEntity variable, process it, and then return the ResponseEntity back.
I referred this -> Spring WebClient Documentation
WHen I tried to store it in a varibale, I get this error -> "block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3"
You can simply use the Reactor's map operator to modify the headers:
return webClient
.get()
.uri("http://localhost:8088/externalService")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.toEntity(Data[].class)
.map(responseEntity -> responseEntity.getHeaders().add("header", "header-value");
Alternatively, you can use .handle operator in order to provide response processing:
.handle((responseEntity, sink) -> {
if(!isValid(responseEntity)){
sink.error(new InvalidResponseException());
} else if (isOk(responseEntity))
sink.next(responseEntity);
}
else {
//just ignore element
}
})
Spring Starter Web dependency was missing in my pom.xml. Found it and added it back.
Now able to get WebClient response in ResponseEntity format.

Get headers from response with Spring Boot 2 WebClient

I would like to receive the headers (especially the content-type) from the webclient response.
I found this code with flatmap-mono-getHeaders, but it doesn't work.
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'image/tiff' not supported for bodyType=org.company.MyResponse
How can I fix it? Or maybe can someone recommend a simpler solution.
Mono<Object> mono = webClient.get()
.uri(path)
.acceptCharset(StandardCharsets.UTF_8)
.retrieve()
.toEntity(MyResponse.class)
.flatMap(entity -> Mono.justOrEmpty(entity.getHeaders().getFirst("content-type")));
Object rs = mono.block();
public class MyResponse {
Object body;
Integer status;
String contentType;
}
I would like to receive the headers (especially the content-type) from the webclient response
Generally speaking you can access response headers like this:
ResponseEntity<MyResponse> response = webClient.get()
.uri(path)
.acceptCharset(StandardCharsets.UTF_8)
.retrieve()
.toEntity(MyResponse.class)
.block();
HttpHeaders headers = response.getHeaders();
MediaType contentType = headers.getContentType();
But from the error you pasted it appears that you are accessing an image (image/tiff) that obviously cannot be converted to your MyResponse class.

Follow redirection with cookies using WebFlux

I am using WebFlux with netty to make third party calls for my spring boot app. A post request with form parameters is made on client's provided url and client responds with 302 status and a location. The code I have written below is able to follow redirections but doesn't send cookies with it which is causing subsequent redirections to fail.
WebFlux config
#Bean
public WebClient webClient() {
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs((configurer) -> {
configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder());
}).build();
exchangeStrategies.messageWriters().stream()
.filter(LoggingCodecSupport.class::isInstance)
.forEach(writer -> ((LoggingCodecSupport) writer)
.setEnableLoggingRequestDetails(Boolean.TRUE));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient.create()
.followRedirect(true)
.secure()))
.exchangeStrategies(exchangeStrategies)
.build();
}
Post Request
private <T> Mono <String> buildPostRequest(MultiValueMap <String, String> formData, String postUrl) {
return client.post()
.uri(postUrl)
.body(BodyInserters.fromFormData(formData))
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.retrieve()
.bodyToMono(String.class);
}

Spring WebClient filter Null from Json Request

I am using Spring WebClient Api to make a rest api call.
I have an entity object--JobInfo which acts as my POST Request pay-load.
The below Rest API fails because certain attributes of JobInfo are null.
private BatchInfo createBulkUploadJob(JobInfo jobInfo) {
return webClient.post()
.uri(URL.concat("/services/data/v47.0/jobs/ingest/"))
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "OAuth " + TOKEN)
.bodyValue(jobInfo)
.retrieve()
.bodyToMono(BatchInfo.class)
.block();
}
I need to filter out the Null attributes from sending it across the rest call.
I understand this can be easily achieved by including below annotation on JobInfo class.
#JsonInclude(JsonInclude.Include.NON_NULL)
But JobInfo is coming from a third party Jar, so I cannot touch this class.
Is there a way I can configure this in webClient to filter this out or any other option ?
Try with this:
private BatchInfo createBulkUploadJob(JobInfo jobInfo) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
ExchangeStrategies strategies = ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
}).build();
WebClient webClient = WebClient.builder().exchangeStrategies(strategies).build();
return webClient.post()
.uri(URL.concat("/services/data/v47.0/jobs/ingest/"))
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "OAuth " + TOKEN)
.bodyValue(jobInfo)
.retrieve()
.bodyToMono(BatchInfo.class)
.block();
}

Categories

Resources