Skip to content

Commit

Permalink
Register resource classes for reflection when ContainerResponseFilter…
Browse files Browse the repository at this point in the history
… exists

This is needed because those filters can call
setEntityStream which then forces the use of the
slow path for calling writers

Closes: quarkusio#42537
  • Loading branch information
geoand authored and danielsoro committed Sep 20, 2024
1 parent 5ff82a1 commit 7ad4769
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,7 @@ public void additionalReflection(BeanArchiveIndexBuildItem beanArchiveIndexBuild
SetupEndpointsResultBuildItem setupEndpointsResult,
List<MessageBodyReaderBuildItem> messageBodyReaderBuildItems,
List<MessageBodyWriterBuildItem> messageBodyWriterBuildItems,
ResourceInterceptorsBuildItem resourceInterceptorsBuildItem,
BuildProducer<ReflectiveClassBuildItem> producer) {
List<ResourceClass> resourceClasses = setupEndpointsResult.getResourceClasses();
IndexView index = beanArchiveIndexBuildItem.getIndex();
Expand Down Expand Up @@ -1185,6 +1186,13 @@ public void additionalReflection(BeanArchiveIndexBuildItem beanArchiveIndexBuild
}
}
}

// when a ContainerResponseFilter exists, it can potentially do responseContext.setEntityStream()
// which then forces the use of the slow path for calling writers
if (!resourceInterceptorsBuildItem.getResourceInterceptors().getContainerResponseFilters().isEmpty()) {
serializersRequireResourceReflection = true;
}

if (serializersRequireResourceReflection) {
producer.produce(ReflectiveClassBuildItem
.builder(resourceClasses.stream().map(ResourceClass::getClassName).toArray(String[]::new))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public void sort() {
Collections.sort(nameResourceInterceptors);
}

public boolean isEmpty() {
return globalResourceInterceptors.isEmpty() && nameResourceInterceptors.isEmpty();
}

public ResourceInterceptor<T> create() {
return new ResourceInterceptor<>();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.it.resteasy.reactive.kotlin

import jakarta.ws.rs.container.ContainerRequestContext
import jakarta.ws.rs.container.ContainerResponseContext
import jakarta.ws.rs.container.ContainerResponseFilter
import jakarta.ws.rs.ext.Provider
import java.io.ByteArrayInputStream
import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveContainerRequestContext

@Provider
class EntityStreamSettingContainerResponseFilter : ContainerResponseFilter {
override fun filter(
requestContext: ContainerRequestContext?,
responseContext: ContainerResponseContext?
) {
if (requestContext is ResteasyReactiveContainerRequestContext) {
if (
"hello".equals(
requestContext.serverRequestContext.resteasyReactiveResourceInfo.name
)
) {
responseContext?.setEntity(
ByteArrayInputStream("Hello Quarkus REST".toByteArray(Charsets.UTF_8))
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ReactiveGreetingResource @Inject constructor(val req: RequestScopedKotlinC
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/{name}")
suspend fun hello(name: String): String {
suspend fun namedHello(name: String): String {
delay(50)
return "Hello $name"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class ReactiveGreetingResourceTest {
When { get("/hello-resteasy-reactive/") } Then
{
statusCode(200)
body(`is`("Hello RestEASY Reactive"))
body(
`is`("Hello Quarkus REST")
) // the result comes from EntityStreamSettingContainerResponseFilter
}
}

Expand Down

0 comments on commit 7ad4769

Please sign in to comment.