From a59e2e46fcb6c9d2fe74a28f48d1778e883616a6 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 16 Nov 2022 11:02:24 +0100 Subject: [PATCH] Separate resourceClass into resourceName and resourceInterface The changes in https://github.com/quarkusio/quarkus/pull/29212 introduced a bug that was reproduced by the Quarkus Quickstart (see https://github.com/quarkusio/quarkus-quickstarts/actions/runs/3475885826). The problem is that in REST DATA with Panache, we use the REST interface to declare the resource properties and the generated resource extends to this REST interface. However, in Spring Data Rest, we use the repository to gather the resource properties and hence the generated resource extends to this repository and as we have two beans for the repository (the right one and the generated resource), it fails. The fix is to separate the resourceInterface into resourceName (where the resource properties can be set) and the good resourceInterface (the one we'll use to extend the generated resource - in Spring Data REST, this is null because we don't have resource interfaces). --- .../deployment/JaxRsResourceImplementor.java | 18 +++++++++------ .../panache/deployment/ResourceMetadata.java | 15 +++++++++++++ .../panache/deployment/RestDataProcessor.java | 4 ++-- .../ResourcePropertiesProvider.java | 22 +++++++++---------- .../deployment/SpringDataRestProcessor.java | 10 ++++----- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/JaxRsResourceImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/JaxRsResourceImplementor.java index 5b09b5094be8b..bbaa04cb04bc3 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/JaxRsResourceImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/JaxRsResourceImplementor.java @@ -67,13 +67,17 @@ class JaxRsResourceImplementor { */ void implement(ClassOutput classOutput, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, Capabilities capabilities) { - String controllerClassName = resourceMetadata.getResourceInterface() + "JaxRs_" + - HashUtil.sha1(resourceMetadata.getResourceInterface()); + String controllerClassName = resourceMetadata.getResourceName() + "JaxRs_" + + HashUtil.sha1(resourceMetadata.getResourceName()); LOGGER.tracef("Starting generation of '%s'", controllerClassName); - ClassCreator classCreator = ClassCreator.builder() - .classOutput(classOutput).className(controllerClassName) - .interfaces(resourceMetadata.getResourceInterface()) - .build(); + ClassCreator.Builder classCreatorBuilder = ClassCreator.builder() + .classOutput(classOutput).className(controllerClassName); + + if (resourceMetadata.getResourceInterface() != null) { + classCreatorBuilder.interfaces(resourceMetadata.getResourceInterface()); + } + + ClassCreator classCreator = classCreatorBuilder.build(); implementClassAnnotations(classCreator, resourceMetadata, resourceProperties, capabilities); FieldDescriptor resourceField = implementResourceField(classCreator, resourceMetadata); @@ -87,7 +91,7 @@ private void implementClassAnnotations(ClassCreator classCreator, ResourceMetada ResourceProperties resourceProperties, Capabilities capabilities) { classCreator.addAnnotation(Path.class).addValue("value", resourceProperties.getPath()); if (capabilities.isPresent(Capability.SMALLRYE_OPENAPI)) { - String className = StringUtils.substringAfterLast(resourceMetadata.getResourceInterface(), "."); + String className = StringUtils.substringAfterLast(resourceMetadata.getResourceName(), "."); classCreator.addAnnotation(OPENAPI_TAG_ANNOTATION).add("name", className); } if (resourceProperties.getClassAnnotations() != null) { diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/ResourceMetadata.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/ResourceMetadata.java index 66c0be18e37a5..330ce21b81765 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/ResourceMetadata.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/ResourceMetadata.java @@ -11,6 +11,11 @@ public class ResourceMetadata { */ private final String resourceClass; + /** + * Name that is used to generate the new resource. + */ + private final String resourceName; + /** * Application interface that extends RestDataResource interface. */ @@ -33,7 +38,13 @@ public class ResourceMetadata { public ResourceMetadata(String resourceClass, String resourceInterface, String entityType, String idType, Map fields) { + this(resourceClass, resourceInterface, resourceInterface, entityType, idType, fields); + } + + public ResourceMetadata(String resourceClass, String resourceName, String resourceInterface, String entityType, + String idType, Map fields) { this.resourceClass = resourceClass; + this.resourceName = resourceName; this.resourceInterface = resourceInterface; this.entityType = entityType; this.idType = idType; @@ -44,6 +55,10 @@ public String getResourceClass() { return resourceClass; } + public String getResourceName() { + return resourceName; + } + public String getResourceInterface() { return resourceInterface; } diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/RestDataProcessor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/RestDataProcessor.java index ccd7a5c667596..69bac5fd7f7ea 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/RestDataProcessor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/RestDataProcessor.java @@ -92,11 +92,11 @@ private ResourceProperties getResourceProperties(ResourcePropertiesProvider reso ResourceMetadata resourceMetadata, List resourcePropertiesBuildItems) { for (ResourcePropertiesBuildItem resourcePropertiesBuildItem : resourcePropertiesBuildItems) { if (resourcePropertiesBuildItem.getResourceType().equals(resourceMetadata.getResourceClass()) - || resourcePropertiesBuildItem.getResourceType().equals(resourceMetadata.getResourceInterface())) { + || resourcePropertiesBuildItem.getResourceType().equals(resourceMetadata.getResourceName())) { return resourcePropertiesBuildItem.getResourcePropertiesInfo(); } } - return resourcePropertiesProvider.getForInterface(resourceMetadata.getResourceInterface()); + return resourcePropertiesProvider.getFromClass(resourceMetadata.getResourceName()); } private boolean hasAnyJsonCapabilityForResteasyClassic(Capabilities capabilities) { diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/properties/ResourcePropertiesProvider.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/properties/ResourcePropertiesProvider.java index feb4b4976bdb4..7925f16932eb4 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/properties/ResourcePropertiesProvider.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/properties/ResourcePropertiesProvider.java @@ -37,18 +37,18 @@ public ResourcePropertiesProvider(IndexView index) { * Find resource and method properties annotations used by a given interface * and build {@link ResourceProperties} instance. */ - public ResourceProperties getForInterface(String resourceInterface) { - DotName resourceInterfaceName = DotName.createSimple(resourceInterface); - AnnotationInstance annotation = findResourcePropertiesAnnotation(resourceInterfaceName); + public ResourceProperties getFromClass(String resourceClass) { + DotName resourceClassName = DotName.createSimple(resourceClass); + AnnotationInstance annotation = findResourcePropertiesAnnotation(resourceClassName); return new ResourceProperties( isExposed(annotation), - getPath(annotation, resourceInterface), + getPath(annotation, resourceClass), isPaged(annotation), isHal(annotation), - getHalCollectionName(annotation, resourceInterface), + getHalCollectionName(annotation, resourceClass), getRolesAllowed(annotation), - collectAnnotationsToCopy(resourceInterfaceName), - collectMethodProperties(resourceInterfaceName)); + collectAnnotationsToCopy(resourceClassName), + collectMethodProperties(resourceClassName)); } private Collection collectAnnotationsToCopy(DotName className) { @@ -142,18 +142,18 @@ private String getPath(AnnotationInstance annotation) { return ""; } - private String getPath(AnnotationInstance annotation, String resourceInterface) { + private String getPath(AnnotationInstance annotation, String resourceClass) { if (annotation != null && annotation.value("path") != null) { return annotation.value("path").asString(); } - return ResourceName.fromClass(resourceInterface); + return ResourceName.fromClass(resourceClass); } - private String getHalCollectionName(AnnotationInstance annotation, String resourceInterface) { + private String getHalCollectionName(AnnotationInstance annotation, String resourceClass) { if (annotation != null && annotation.value("halCollectionName") != null) { return annotation.value("halCollectionName").asString(); } - return ResourceName.fromClass(resourceInterface); + return ResourceName.fromClass(resourceClass); } private String[] getRolesAllowed(AnnotationInstance annotation) { diff --git a/extensions/spring-data-rest/deployment/src/main/java/io/quarkus/spring/data/rest/deployment/SpringDataRestProcessor.java b/extensions/spring-data-rest/deployment/src/main/java/io/quarkus/spring/data/rest/deployment/SpringDataRestProcessor.java index 2cab60a9e7c46..a2433afe36d77 100644 --- a/extensions/spring-data-rest/deployment/src/main/java/io/quarkus/spring/data/rest/deployment/SpringDataRestProcessor.java +++ b/extensions/spring-data-rest/deployment/src/main/java/io/quarkus/spring/data/rest/deployment/SpringDataRestProcessor.java @@ -120,22 +120,22 @@ private void implementResources(Capabilities capabilities, ResourceImplementor resourceImplementor = new ResourceImplementor(methodsImplementor); for (ClassInfo classInfo : repositoriesToImplement) { List generics = getGenericTypes(classInfo); - String repositoryInterface = classInfo.name().toString(); + String repositoryName = classInfo.name().toString(); String entityType = generics.get(0).toString(); String idType = generics.get(1).toString(); - String resourceClass = resourceImplementor.implement(classOutput, repositoryInterface, entityType); + String resourceClass = resourceImplementor.implement(classOutput, repositoryName, entityType); // Register resource metadata so that a JAX-RS resource could be generated by the rest-data-panache restDataResourceProducer.produce(new RestDataResourceBuildItem( - new ResourceMetadata(resourceClass, repositoryInterface, entityType, idType, Collections.emptyMap()))); + new ResourceMetadata(resourceClass, repositoryName, null, entityType, idType, Collections.emptyMap()))); // Spring Data repositories use different annotations for configuration and we translate them for // the rest-data-panache here. - ResourceProperties resourceProperties = propertiesProvider.getResourceProperties(repositoryInterface); + ResourceProperties resourceProperties = propertiesProvider.getResourceProperties(repositoryName); resourcePropertiesProducer.produce(new ResourcePropertiesBuildItem(resourceClass, resourceProperties)); // Make sure that repository bean is not removed and will be injected to the generated resource unremovableBeansProducer.produce(new UnremovableBeanBuildItem( - new UnremovableBeanBuildItem.BeanTypeExclusion(DotName.createSimple(repositoryInterface)))); + new UnremovableBeanBuildItem.BeanTypeExclusion(DotName.createSimple(repositoryName)))); } }