diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java index d9e45149276ac..64896442d2aad 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java @@ -67,7 +67,7 @@ public MaybeRestClientInterface createClientProxy(ClassInfo classInfo, } clazz.setPath(path); } - List methods = createEndpoints(classInfo, classInfo, new HashSet<>(), + List methods = createEndpoints(classInfo, classInfo, new HashSet<>(), new HashSet<>(), clazz.getPathParameters(), clazz.getPath(), false); clazz.getMethods().addAll(methods); @@ -99,7 +99,8 @@ protected void handleClientSubResource(ResourceMethod resourceMethod, MethodInfo throw new IllegalStateException("Subresource method returns an invalid type: " + method.returnType().name()); } - List endpoints = createEndpoints(subResourceClass, subResourceClass, new HashSet<>(), new HashSet<>(), + List endpoints = createEndpoints(subResourceClass, subResourceClass, + new HashSet<>(), new HashSet<>(), new HashSet<>(), "", false); resourceMethod.setSubResourceMethods(endpoints); } diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index 9f9fdc15a1eda..7d24c2046a693 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -281,7 +281,7 @@ public Optional createEndpoints(ClassInfo classInfo, boolean cons if (classLevelExceptionMappers != null) { clazz.setClassLevelExceptionMappers(classLevelExceptionMappers); } - List methods = createEndpoints(classInfo, classInfo, new HashSet<>(), + List methods = createEndpoints(classInfo, classInfo, new HashSet<>(), new HashSet<>(), clazz.getPathParameters(), clazz.getPath(), considerApplication); clazz.getMethods().addAll(methods); @@ -349,7 +349,7 @@ protected abstract METHOD createResourceMethod(MethodInfo info, ClassInfo actual Map methodContext); protected List createEndpoints(ClassInfo currentClassInfo, - ClassInfo actualEndpointInfo, Set seenMethods, + ClassInfo actualEndpointInfo, Set seenMethods, Set existingClassNameBindings, Set pathParameters, String resourceClassPath, boolean considerApplication) { if (considerApplication && applicationScanningResult != null && !applicationScanningResult.keepClass(actualEndpointInfo.name().toString())) { @@ -371,6 +371,9 @@ protected List createEndpoints(ClassInfo currentClassInfo, classConsumes, pathParameters, classStreamElementType); Set classNameBindings = NameBindingUtil.nameBindingNames(index, currentClassInfo); + if (classNameBindings.isEmpty()) { + classNameBindings = existingClassNameBindings; + } for (DotName httpMethod : httpAnnotationToMethod.keySet()) { List methods = currentClassInfo.methods(); @@ -436,7 +439,7 @@ protected List createEndpoints(ClassInfo currentClassInfo, if (superClassName != null && !superClassName.equals(OBJECT)) { ClassInfo superClass = index.getClassByName(superClassName); if (superClass != null) { - ret.addAll(createEndpoints(superClass, actualEndpointInfo, seenMethods, + ret.addAll(createEndpoints(superClass, actualEndpointInfo, seenMethods, classNameBindings, pathParameters, resourceClassPath, considerApplication)); } } @@ -444,7 +447,7 @@ protected List createEndpoints(ClassInfo currentClassInfo, for (DotName i : interfaces) { ClassInfo superClass = index.getClassByName(i); if (superClass != null) { - ret.addAll(createEndpoints(superClass, actualEndpointInfo, seenMethods, + ret.addAll(createEndpoints(superClass, actualEndpointInfo, seenMethods, classNameBindings, pathParameters, resourceClassPath, considerApplication)); } } diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/NameBindingWithInterfaceTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/NameBindingWithInterfaceTest.java new file mode 100644 index 0000000000000..a239b55335cdf --- /dev/null +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/NameBindingWithInterfaceTest.java @@ -0,0 +1,101 @@ +package org.jboss.resteasy.reactive.server.vertx.test.simple; + +import static io.restassured.RestAssured.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import io.smallrye.mutiny.Uni; +import java.io.IOException; +import java.lang.annotation.Retention; +import javax.ws.rs.GET; +import javax.ws.rs.NameBinding; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.Provider; +import org.hamcrest.Matchers; +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 NameBindingWithInterfaceTest { + + @RegisterExtension + static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(BlockingHelloResource.class, ReactiveHelloResource.class, BlockingHelloApi.class, + ReactiveHelloApi.class, AddTestHeaderContainerRequestFilter.class)); + + @Test + public void blockingHello() { + get("/blocking-hello") + .then() + .statusCode(200) + .body(Matchers.equalTo("hello")) + .header("test", "some-value"); + } + + @Test + public void reactiveHello() { + get("/reactive-hello") + .then() + .statusCode(200) + .body(Matchers.equalTo("hello")) + .header("test", "some-value"); + } + + @SomeFilter + public static class BlockingHelloResource implements BlockingHelloApi { + + @Override + public String sayHello() { + return "hello"; + } + } + + @SomeFilter + public static class ReactiveHelloResource implements ReactiveHelloApi { + + @Override + public Uni sayHello() { + return Uni.createFrom().item("hello"); + } + } + + @Path("blocking-hello") + public interface BlockingHelloApi { + + @GET + @Produces(MediaType.TEXT_PLAIN) + String sayHello(); + } + + @Path("reactive-hello") + public interface ReactiveHelloApi { + + @GET + @Produces(MediaType.TEXT_PLAIN) + Uni sayHello(); + } + + @NameBinding + @Retention(RUNTIME) + @interface SomeFilter { + } + + @Provider + @SomeFilter + public static class AddTestHeaderContainerRequestFilter implements ContainerResponseFilter { + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + responseContext.getHeaders().putSingle("test", "some-value"); + + } + } +}