Skip to content

The JDK Flow API

The java.util.concurrent.Flow API packages the Reactive Streams interfaces inside the JDK (Flow.Publisher, Flow.Subscriber, Flow.Subscription, Flow.Processor) and adds a ready-made Flow.Publisher implementation: SubmissionPublisher.

Spring WebFlux provides adapter support for it, so a Flow.Publisher can be a controller return type or parameter.

Flow.Publisher as a return type

The java9 sample returns a Flow.Publisher from a controller and bridges Reactor's Flux with JdkFlowAdapter:

@RestController
@RequestMapping(value = "/posts")
public class PostController {

    @GetMapping
    public Flow.Publisher<Post> all() {
        return JdkFlowAdapter.publisherToFlowPublisher(
                Flux.just(
                        new Post(1L, "post one", "content of post one"),
                        new Post(2L, "post two", "content of post two")
                )
        );
    }
}

Spring accepts the Flow.Publisher and drives it through the reactive request handling stack — the response is streamed exactly as with a Flux return type.

The JDK HttpClient

The JDK ships a reactive java.net.http.HttpClient built on the Flow API. When you need a JDK-native client outside of Spring, it frees you from third-party HTTP client libraries:

HttpClient client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)
        .build();

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:8080/posts"))
        .build();

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body)
        .thenAccept(System.out::println)
        .join();

Inside a Spring application, prefer WebClient with the JDK connector, which wraps the same HttpClient behind the ClientHttpConnector abstraction.

You can explore the complete codes in spring-reactive-sample/java9.