playframework/play-ws

Play-ws is blocking while consuming a Reactive WebFlux SpringBoot app

patpatpat123 opened this issue · 4 comments

Are you looking for help?

Yes

Play WS Version (2.4.3)

API (Java)

Operating System (MacOS 10.13)

JDK (Oracle 1.8.0_144-b01)

Library Dependencies

?

Expected Behavior

Able to consume the reactive Web service, in a non blocking way, (IE, in this example, to see the stream)

Please describe the expected behavior of the issue, starting from the first action.
As of now, it is blocking. Even if Micro service A is sending the response in a non blocking reactive way, play-ws blocks. It returns the entire payload only after micro service a finishes the compute.

Actual Behavior

Micro service A is a reactive Spring WebFlux, written in Java 8, SpringBoot 2.1.4, it is exposing this API:

@Autowired private ReactiveCustomerRepository customerRepository;

@GetMapping("/customers")
public Flux<Customer> getAllCustomers() {
    Flux<Customer> c = customerRepository.findAll().delayElements(Duration.ofMillis(5000));
    return c;
}

I am expecting play-ws to consume this, in a reactive way. Per say, when invoking WSClient from the controller SomeController extends Controller, it is currently blocking (waiting for the N multiply by 5000ms before getting the entire block of response).

Why play-ws is not getting the response in a reactive way, seeing each row per 5000ms interval?

To provide some more info, a micro service C can successfully consume micro service A using Spring WebClient. still in the non blocking and reactive way. (Able to get each of the customers per interval.)

However, WSRequest request = ws.url("localhost:8080/customers”); request.get(); Either with Promise or CompletionStage blocks until all the customers are retrieved.

You should getBodyAsSource to read data as it's available:

        CompletionStage<WSResponse> wsResponseCompletionStage = ws
            .url("http://someurl.com")
            .get();
        CompletionStage<? extends Source<ByteString, ?>> sourceCompletionStage = wsResponseCompletionStage
            .thenApply(WSResponse::getBodyAsSource);

I will close this issue since it's not a bug.

Hello ignasi35, why such a quick close on something that might be an issue?
Using your example, it is still not reactive at all.
Your first statement is CompletionStage<WSResponse> wsResponseCompletionStage = ws.url("http://someurl.com").get();
Can you elaborate why are you using a get()? A stream() might be more appropriate?

In your second statement, how do you go from CompletionStage<? extends Source<ByteString, ?>> to a CompletionStage<Result>, being able to use in a controller?
As of now, with your combination, it is still blocking. There might be an issue here

Hi @patpatpat123, if you want to get a better understanding of how to reactively consume a stream I think we can move the discussion to https://discuss.lightbend.com/c/play.

If you think there is a bug, it'd be great if you can share some code reproducing the error. I noticed you mentioned "Play WS (2.4.3)" but that version doesn't exist so I'm guessing you meant "Play 2.4.3". If you meant "Play 2.4.3", then I'd suggest you upgrade to a newer version of Play first since Play 2.4.3 is long EOL and we no longer accept fixes for that version.

Regards,