From ea91fbed88b30738d76ebb9a131a60f3bdcb7bb8 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Wed, 9 Nov 2022 14:10:37 +0100 Subject: [PATCH] Include interfaces as bean types of RR resources --- .../deployment/ResteasyReactiveProcessor.java | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java index 6bb15d1a20b61..26f6c576fe68c 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java @@ -16,6 +16,7 @@ import java.util.Deque; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -733,7 +734,8 @@ private FilterClassIntrospector createFilterClassIntrospector() { public void transformEndpoints( ResourceScanningResultBuildItem resourceScanningResultBuildItem, ResourceInterceptorsBuildItem resourceInterceptorsBuildItem, - BuildProducer annotationsTransformer) { + BuildProducer annotationsTransformer, + BeanArchiveIndexBuildItem beanArchiveIndexBuildItem) { // all found resources and sub-resources Set allResources = new HashSet<>(); @@ -774,7 +776,7 @@ public void transform(TransformationContext context) { // check if the class is one of resources/sub-resources if (allResources.contains(clazz.name()) && clazz.declaredAnnotation(ResteasyReactiveDotNames.TYPED) == null) { - context.transform().add(createTypedAnnotationInstance(clazz)).done(); + context.transform().add(createTypedAnnotationInstance(clazz, beanArchiveIndexBuildItem)).done(); return; } // check if the class is one of providers, either explicitly declaring the annotation @@ -783,17 +785,52 @@ public void transform(TransformationContext context) { || filtersAndInterceptors.contains(clazz.name().toString())) && clazz.declaredAnnotation(ResteasyReactiveDotNames.TYPED) == null) { // Add @Typed(MyResource.class) - context.transform().add(createTypedAnnotationInstance(clazz)).done(); + context.transform().add(createTypedAnnotationInstance(clazz, beanArchiveIndexBuildItem)).done(); } } })); } - private AnnotationInstance createTypedAnnotationInstance(ClassInfo clazz) { + private AnnotationInstance createTypedAnnotationInstance(ClassInfo clazz, + BeanArchiveIndexBuildItem beanArchiveIndexBuildItem) { + Set interfaceNames = new HashSet<>(); + ClassInfo currentClazz = clazz; + while (!ResteasyReactiveDotNames.OBJECT.equals(currentClazz.name())) { + currentClazz.interfaceNames().forEach(iface -> interfaceNames.add(iface)); + // inspect super class + currentClazz = beanArchiveIndexBuildItem.getIndex().getClassByName(currentClazz.superName()); + } + Set allInterfaces = new HashSet<>(); + recursiveInterfaceSearch(interfaceNames, allInterfaces, beanArchiveIndexBuildItem); + AnnotationValue[] annotationValues = new AnnotationValue[allInterfaces.size() + 1]; + // always add the bean impl class + annotationValues[0] = AnnotationValue.createClassValue("value", + Type.create(clazz.name(), Type.Kind.CLASS)); + Iterator iterator = allInterfaces.iterator(); + for (int i = 1; i < annotationValues.length; i++) { + annotationValues[i] = AnnotationValue.createClassValue("value", + Type.create(iterator.next(), Type.Kind.CLASS)); + } return AnnotationInstance.create(ResteasyReactiveDotNames.TYPED, clazz, new AnnotationValue[] { AnnotationValue.createArrayValue("value", - new AnnotationValue[] { AnnotationValue.createClassValue("value", - Type.create(clazz.name(), Type.Kind.CLASS)) }) }); + annotationValues) }); + } + + private void recursiveInterfaceSearch(Set interfacesToProcess, Set allDiscoveredInterfaces, + BeanArchiveIndexBuildItem beanArchiveIndexBuildItem) { + allDiscoveredInterfaces.addAll(interfacesToProcess); + Set additionalInterfacesToProcess = new HashSet<>(); + for (DotName name : interfacesToProcess) { + ClassInfo clazz = beanArchiveIndexBuildItem.getIndex().getClassByName(name); + if (clazz != null) { + // get all interface that this interface extends + additionalInterfacesToProcess.addAll(clazz.interfaceNames()); + } + } + if (!additionalInterfacesToProcess.isEmpty()) { + // recursively process newly found interfaces + recursiveInterfaceSearch(additionalInterfacesToProcess, allDiscoveredInterfaces, beanArchiveIndexBuildItem); + } } private Collection additionalContextTypes(List contextTypeBuildItems) {