jakartaee / rest

Jakarta RESTful Web Services
Other
368 stars 121 forks source link

Add ReactiveStream/JDK 9 Flow Support #1281

Open hantsy opened 3 months ago

hantsy commented 3 months ago

Besides asynchronous context support in Rest, add ReactiveStreams Publisher and JDK 9 Flow.Publisher as a generic return type, or parameter type in Response.

Quarkus/Resteasy has implemented reactive versions.

The following is an example of Quarkus/Resteasy Reactive, check: https://github.com/hantsy/quarkus-sandbox/blob/master/resteasy-reactive-hibernate/src/main/java/com/example/PostResource.java

@Path("/posts")
@RequestScoped
public class PostResource {
    private final static Logger LOGGER = Logger.getLogger(PostResource.class.getName());

    private final PostRepository posts;

    @Inject
    public PostResource(PostRepository posts) {
        this.posts = posts;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<List<Post>> getAllPosts() {
        return this.posts.findAll();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Uni<Response> savePost(@Valid Post post) {
        return this.posts.save(post)
                .map(id -> created(URI.create("/posts/" + id)).build());
    }

    @Path("{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> getPostById(@PathParam("id") final String id) {
        return this.posts.findById(UUID.fromString(id))
                .map(data -> {
                    if (data == null) {
                        return null;
                    }
                    return ok(data).build();
                })
        //        .onItem().ifNull().continueWith(status(Status.NOT_FOUND).build());
        .onFailure(PostNotFoundException.class).recoverWithItem(status(Status.NOT_FOUND).build());
    }

    @Path("{id}")
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public Uni<Response> updatePost(@PathParam("id") final String id, @Valid Post post) {
        return this.posts.update(UUID.fromString(id), post)
                .map(updated -> updated > 0 ? Status.NO_CONTENT : Status.NOT_FOUND)
                .map(status -> status(status).build());
    }

    @DELETE
    @Path("{id}")
    public Uni<Response> delete(@PathParam("id") String id) {
        return this.posts.delete(UUID.fromString(id))
                .map(deleted -> deleted > 0 ? Status.NO_CONTENT : Status.NOT_FOUND)
                .map(status -> status(status).build());
    }
}

Besides general Reactive Streams support, the Server Sent Event is a good match for Reactive Streams.

MP Rest Client has supported ReactiveStreams for a while.

mkarg commented 3 months ago

In fact I was about to propose that very same feature, too! 👍

jamezp commented 2 months ago

I'm a +1 for this. I think it makes sense.