Skip to content

Commit

Permalink
Make subresource handling for interfaces more nuanced
Browse files Browse the repository at this point in the history
We don't want to create subresources for interfaces
that are used by multiple resource classes
for the purpose of reusing resource methods
and JAX-RS annotations

Fixes: quarkusio#34657
  • Loading branch information
geoand committed Jul 20, 2023
1 parent ac078d9 commit 7b997cd
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ public Supplier<Boolean> apply(ClassInfo classInfo) {
}
}
Map<DotName, ClassInfo> possibleSubResources = new HashMap<>();
Set<String> resourceClassNames = null;
while (!toScan.isEmpty()) {
ClassInfo classInfo = toScan.poll();
if (scannedResources.containsKey(classInfo.name()) ||
Expand All @@ -691,6 +692,25 @@ public Supplier<Boolean> apply(ClassInfo classInfo) {
continue;
}
possibleSubResources.put(classInfo.name(), classInfo);

if (classInfo.isInterface()) {
int resourceClassImplCount = 0;
if (resourceClassNames == null) {
resourceClassNames = resourceClasses.stream().map(ResourceClass::getClassName)
.collect(Collectors.toSet());
}
for (ClassInfo impl : index.getAllKnownImplementors(classInfo.name())) {
if (resourceClassNames.contains(impl.name().toString())) {
resourceClassImplCount++;
}
}
if (resourceClassImplCount > 1) {
// this is the case were an interface doesn't denote a subresource, but it's simply used
// to share method and annotations between Resource classes
continue;
}
}

Optional<ResourceClass> endpoints = serverEndpointIndexer.createEndpoints(classInfo, false);
if (endpoints.isPresent()) {
subResourceClasses.add(endpoints.get());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.quarkus.resteasy.reactive.server.test.resource.basic;

import static io.restassured.RestAssured.when;
import static org.hamcrest.CoreMatchers.is;

import java.util.function.Supplier;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.RestPath;
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;

import io.quarkus.test.QuarkusUnitTest;

public class MultipleResourceImplementInterfaceTest {

@RegisterExtension
static QuarkusUnitTest testExtension = new QuarkusUnitTest()
.setArchiveProducer(new Supplier<>() {
@Override
public JavaArchive get() {
JavaArchive war = ShrinkWrap.create(JavaArchive.class);
war.addClass(HelloResource.class);
war.addClass(Hello2Resource.class);
war.addClass(Shared.class);
return war;
}
});

@Test
public void hello() {
when().get("/hello")
.then().statusCode(200).body(is("hello"));

when().get("/hello/shared/1")
.then().statusCode(200).body(is("1"));
}

@Test
public void hello2() {
when().get("/hello2")
.then().statusCode(200).body(is("hello2"));

when().get("/hello2/shared/h2")
.then().statusCode(200).body(is("h2"));
}

@Path("/hello")
public static class HelloResource implements Shared {

@GET
public String hello() {
return "hello";
}

}

@Path("/hello2")
public static class Hello2Resource implements Shared {

@GET
public String hello() {
return "hello2";
}

}

public interface Shared {

@GET
@Path("/shared/{id}")
default String version(@RestPath String id) {
return id;
}
}
}

0 comments on commit 7b997cd

Please sign in to comment.