Skip to content

Commit e3b4bab

Browse files
committed
Set path of client subinterfaces 2+ levels deep
The path of client interfaces, which do not have a Path annotation of their own, needs to be set to the path of its direct parent. Now this also works if a parent interface is inerhited 2 or more levels deep, without another Path annotation on any of the sub interfaces
1 parent 4e23e2c commit e3b4bab

File tree

2 files changed

+78
-9
lines changed

2 files changed

+78
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.quarkus.rest.client.reactive;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.hamcrest.Matchers.is;
5+
6+
import java.util.Map;
7+
import java.util.function.Consumer;
8+
9+
import jakarta.ws.rs.GET;
10+
import jakarta.ws.rs.Path;
11+
12+
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
13+
import org.hamcrest.MatcherAssert;
14+
import org.jboss.jandex.DotName;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.RegisterExtension;
17+
18+
import io.quarkus.builder.BuildChainBuilder;
19+
import io.quarkus.builder.BuildContext;
20+
import io.quarkus.builder.BuildStep;
21+
import io.quarkus.deployment.builditem.FeatureBuildItem;
22+
import io.quarkus.resteasy.reactive.common.deployment.ResourceScanningResultBuildItem;
23+
import io.quarkus.test.QuarkusUnitTest;
24+
25+
public class InterfacePathInheritanceTest {
26+
@RegisterExtension
27+
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
28+
.withApplicationRoot((jar) -> jar
29+
.addClass(Z.class)
30+
.addClass(Y.class)
31+
.addClass(InheritanceTestClient.class))
32+
.addBuildChainCustomizer(new Consumer<BuildChainBuilder>() {
33+
@Override
34+
public void accept(BuildChainBuilder buildChainBuilder) {
35+
buildChainBuilder.addBuildStep(new BuildStep() {
36+
@Override
37+
public void execute(BuildContext context) {
38+
ResourceScanningResultBuildItem consumed = context.consume(ResourceScanningResultBuildItem.class);
39+
context.produce(new FeatureBuildItem("just-here-to-invoke-buildstep"));
40+
41+
Map<DotName, String> clientInterfaces = consumed.getResult().getClientInterfaces();
42+
MatcherAssert.assertThat(clientInterfaces.size(), is(3));
43+
clientInterfaces.forEach((k, v) -> {
44+
MatcherAssert.assertThat("Path of %s needs to match".formatted(k), v, is("hello"));
45+
});
46+
}
47+
}).consumes(ResourceScanningResultBuildItem.class).produces(FeatureBuildItem.class).build();
48+
}
49+
});
50+
51+
@Test
52+
void basicTest() {
53+
// see addBuildChainCustomizer of RegisterExtension for the test logic
54+
}
55+
56+
@Path("hello")
57+
public interface Z {
58+
@GET
59+
@Path("something")
60+
String get();
61+
}
62+
63+
public interface Y extends Z {
64+
65+
}
66+
67+
@RegisterRestClient
68+
public interface InheritanceTestClient extends Y {
69+
70+
}
71+
}

independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/scanning/ResteasyReactiveScanner.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,9 @@ public static ResourceScanningResult scanResources(
302302
}
303303
}
304304

305-
Map<DotName, String> clientInterfaceSubtypes = new HashMap<>();
306-
for (DotName interfaceName : clientInterfaces.keySet()) {
307-
addClientSubInterfaces(interfaceName, index, clientInterfaceSubtypes, clientInterfaces);
305+
for (DotName interfaceName : new ArrayList<>(clientInterfaces.keySet())) {
306+
addClientSubInterfaces(interfaceName, index, clientInterfaces);
308307
}
309-
clientInterfaces.putAll(clientInterfaceSubtypes);
310308

311309
for (Map.Entry<DotName, String> i : pathInterfaces.entrySet()) {
312310
for (ClassInfo clazz : index.getAllKnownImplementors(i.getKey())) {
@@ -402,13 +400,13 @@ public static ResourceScanningResult scanResources(
402400
}
403401

404402
private static void addClientSubInterfaces(DotName interfaceName, IndexView index,
405-
Map<DotName, String> clientInterfaceSubtypes, Map<DotName, String> clientInterfaces) {
403+
Map<DotName, String> clientInterfaces) {
404+
406405
Collection<ClassInfo> subclasses = index.getKnownDirectImplementors(interfaceName);
407406
for (ClassInfo subclass : subclasses) {
408-
if (!clientInterfaces.containsKey(subclass.name()) && Modifier.isInterface(subclass.flags())
409-
&& !clientInterfaceSubtypes.containsKey(subclass.name())) {
410-
clientInterfaceSubtypes.put(subclass.name(), clientInterfaces.get(interfaceName));
411-
addClientSubInterfaces(subclass.name(), index, clientInterfaceSubtypes, clientInterfaces);
407+
if (!clientInterfaces.containsKey(subclass.name()) && Modifier.isInterface(subclass.flags())) {
408+
clientInterfaces.put(subclass.name(), clientInterfaces.get(interfaceName));
409+
addClientSubInterfaces(subclass.name(), index, clientInterfaces);
412410
}
413411
}
414412

0 commit comments

Comments
 (0)