3

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();
        };
    }
MuratOzkan
  • 2,599
  • 13
  • 25
No_One
  • 215
  • 2
  • 3
  • 11

2 Answers2

7

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.

MuratOzkan
  • 2,599
  • 13
  • 25
  • thanks MuratOzkan.. will try it.. though I don't want to return Mono it has to be MyPojo so I guess I can use map(pojo ->) before returning? – No_One Jun 03 '18 at 17:32
  • If you can add more details on the context it would be great. But in general, blocking the stream is not a good idea and must be avoided. – MuratOzkan Jun 03 '18 at 18:05
  • yeah, I understand and want to avoid blocking. The context is to fetch the MyPojo and return it instead of returning Mono. one field of MyPojo is further used to throw an exception if value is null. – No_One Jun 06 '18 at 20:26
  • I mean what are you trying to accomplish? Usually you don't need to return an object, you use the reactive operations. Maybe you misunderstood sth. – MuratOzkan Jun 06 '18 at 20:45
  • right... I will try it with those operations. thanks a lot for your help. – No_One Jun 06 '18 at 21:35
0

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.
AwsAnurag
  • 91
  • 7