From 599400162b1fa8a97d9cf5257533633641617192 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 7 Feb 2023 12:41:53 +0200 Subject: [PATCH 1/2] Add support for JAX-RS StreamingOutput Closes: #28385 --- .../server/core/ServerSerialisers.java | 4 ++ .../StreamingOutputMessageBodyWriter.java | 51 +++++++++++++++++ .../providers/StreamingOutputTestCase.java | 55 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/StreamingOutputMessageBodyWriter.java create mode 100644 independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/providers/StreamingOutputTestCase.java diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/ServerSerialisers.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/ServerSerialisers.java index bd093f5c242fd..fc482e22001fd 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/ServerSerialisers.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/ServerSerialisers.java @@ -27,6 +27,7 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.StreamingOutput; import jakarta.ws.rs.core.Variant; import jakarta.ws.rs.ext.MessageBodyReader; import jakarta.ws.rs.ext.MessageBodyWriter; @@ -63,6 +64,7 @@ import org.jboss.resteasy.reactive.server.providers.serialisers.ServerPathPartBodyHandler; import org.jboss.resteasy.reactive.server.providers.serialisers.ServerReaderBodyHandler; import org.jboss.resteasy.reactive.server.providers.serialisers.ServerStringMessageBodyHandler; +import org.jboss.resteasy.reactive.server.providers.serialisers.StreamingOutputMessageBodyWriter; import org.jboss.resteasy.reactive.server.spi.ServerHttpRequest; import org.jboss.resteasy.reactive.server.spi.ServerHttpResponse; import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter; @@ -130,6 +132,8 @@ public void accept(ResteasyReactiveRequestContext context) { MediaType.APPLICATION_FORM_URLENCODED), new Serialisers.BuiltinWriter(InputStream.class, ServerInputStreamMessageBodyHandler.class, MediaType.WILDCARD), + new Serialisers.BuiltinWriter(StreamingOutput.class, StreamingOutputMessageBodyWriter.class, + MediaType.WILDCARD), new Serialisers.BuiltinWriter(Reader.class, ServerReaderBodyHandler.class, MediaType.WILDCARD), new Serialisers.BuiltinWriter(File.class, ServerFileBodyHandler.class, diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/StreamingOutputMessageBodyWriter.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/StreamingOutputMessageBodyWriter.java new file mode 100644 index 0000000000000..9fa833eccaf5d --- /dev/null +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/StreamingOutputMessageBodyWriter.java @@ -0,0 +1,51 @@ +package org.jboss.resteasy.reactive.server.providers.serialisers; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.StreamingOutput; + +import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo; +import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter; +import org.jboss.resteasy.reactive.server.spi.ServerRequestContext; + +public class StreamingOutputMessageBodyWriter implements ServerMessageBodyWriter { + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return doIsWriteable(type); + } + + @Override + public boolean isWriteable(Class type, Type genericType, ResteasyReactiveResourceInfo target, + MediaType mediaType) { + return doIsWriteable(type); + } + + private static boolean doIsWriteable(Class type) { + return StreamingOutput.class.isAssignableFrom(type); + } + + @Override + public long getSize(StreamingOutput streamingOutput, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return -1; + } + + @Override + public void writeTo(StreamingOutput streamingOutput, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + streamingOutput.write(entityStream); + } + + @Override + public void writeResponse(StreamingOutput o, Type genericType, ServerRequestContext context) + throws WebApplicationException, IOException { + o.write(context.getOrCreateOutputStream()); + } +} diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/providers/StreamingOutputTestCase.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/providers/StreamingOutputTestCase.java new file mode 100644 index 0000000000000..0aa8818ec21f7 --- /dev/null +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/providers/StreamingOutputTestCase.java @@ -0,0 +1,55 @@ +package org.jboss.resteasy.reactive.server.vertx.test.providers; + +import static io.restassured.RestAssured.get; +import static org.hamcrest.CoreMatchers.equalTo; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.function.Supplier; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.StreamingOutput; + +import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class StreamingOutputTestCase { + + @RegisterExtension + static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest() + .setArchiveProducer(new Supplier<>() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(TestResource.class); + } + }); + + @Test + public void testWith() { + get("/test") + .then() + .statusCode(200) + .body(equalTo("hello world")); + } + + @Path("test") + public static class TestResource { + + @GET + public StreamingOutput with() { + return new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + output.write("hello world".getBytes(StandardCharsets.UTF_8)); + } + }; + } + } +} From bbbd2da2d01129d08377eeb5a856bd39e6b3e2e7 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 7 Feb 2023 12:59:48 +0200 Subject: [PATCH 2/2] Update revision of RR TCK This revision includes enabled StreamingOutput tests --- tcks/resteasy-reactive/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcks/resteasy-reactive/pom.xml b/tcks/resteasy-reactive/pom.xml index 53c51f2e962a0..189bc8a29f828 100644 --- a/tcks/resteasy-reactive/pom.xml +++ b/tcks/resteasy-reactive/pom.xml @@ -17,7 +17,7 @@ - 34795c1d2159c420298916d640df239f249f4935 + 8937bc59acc21658d1c9acf59dc3e8960fd98869 ${skipTests} ${exec.skip}