Converting Mono to Pojo without block

17.9k Views Asked by At

Is there a way to convert Mono objects to java Pojo? I have a web client connecting to 3rd party REST service and instead of returning Mono I have to extract that object and interrogate it.

All the examples I have found return Mono<Pojo> but I have to get the Pojo itself. Currently, I am doing it by calling block() on Pojo but is there a better way to avoid block?

The issue with the block is that after few runs it starts throwing some error like block Terminated with error.

 public MyPojo getPojo(){
     return myWebClient.get()
                .uri(generateUrl())
                .headers(createHttpHeaders(headersMap))
                .exchange()
                .flatMap(evaluateResponseStatus())
                .block();
}


private Function<ClientResponse, Mono<? extends MyPojo>> evaluateResponseStatus() {
      return response -> {
            if (response.statusCode() == HttpStatus.OK) {
                return response.bodyToMono(MyPojo.class);
            }
            if (webClientUtils.isError(response.statusCode())) {
                throw myHttpException(response);
                // This invokes my exceptionAdvice
                // but after few runs its ignored and 500 error is returned.
            }
            return Mono.empty();
        };
    }
2

There are 2 best solutions below

5
On

It's not a good idea to block to operate on value in a reactive stream. Project Reactor offers you a selection of operators for you to handle the objects within a stream.

In your case, you can write getPojo() method like:

public Mono<MyPojo> getPojo() {
     return myWebClient.get()
            .uri(generateUrl())
            .headers(createHttpHeaders(headersMap))
            .retrieve()
            .onStatus(status -> webClientUtils.isError(status), 
                      response -> Mono.error(myHttpException(response))
            .bodyToMono(MyPojo.class)
}

Note that using onStatus method, we replaced the whole evaluateResponseStatus method in your example.

You would use this method like the following:

// some method
...
getPojo()
    .map(pojo -> /* do something with the pojo instance */)
...

I strongly advise you to look into Transforming an existing sequence in Project Reactor docs.

0
On

Since Webclient.block() is not recommended, the other way to retrieve the values from incoming httpresponse is to create a POJO in the calling application having the required fields. Then once the Mono is received, use Mono.subscribe(), within subscribe add a lambda function, with input say x, to retrieve the individual fields using the x.getters(). The values could be printed on console or assigned to a local var for further processing. This helps in two ways:-

  1. Avoid the dreaded .block()
  2. Keep the call Asynchronous when pulling large volumes of data. This is one of many other ways to achieve the desired outcome.