From efe7b412719a3094a02d1df36b1a6cf6595bff49 Mon Sep 17 00:00:00 2001 From: Jose Date: Tue, 1 Aug 2023 09:59:59 +0200 Subject: [PATCH] Support user methods with @Transactional in REST Data with Panache ORM Since the annotation `@Transactional` is ignored when used in default methods, we need to copy the default method from the interface into the generated resource. After these changes, we can now use the `@Transacational` annotation. Note that this solution is based on what REST Client also does. Fix https://github.com/quarkusio/quarkus/issues/35107 --- .../HibernateOrmPanacheRestProcessor.java | 15 +++-- .../deployment/ResourceImplementor.java | 3 +- .../entity/CollectionsResource.java | 13 ++++ .../PanacheEntityResourcePostMethodTest.java | 13 ++++ ...HibernateReactivePanacheRestProcessor.java | 14 ++--- .../deployment/ResourceImplementor.java | 3 +- .../deployment/MongoPanacheRestProcessor.java | 14 ++--- .../deployment/ResourceImplementor.java | 4 +- .../deployment/JaxRsResourceImplementor.java | 4 +- .../panache/deployment/ResourceMetadata.java | 11 ++-- .../panache/deployment/RestDataProcessor.java | 2 +- ...erMethodsWithTransactionalImplementor.java | 62 +++++++++++++++++++ 12 files changed, 124 insertions(+), 34 deletions(-) create mode 100644 extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UserMethodsWithTransactionalImplementor.java diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/HibernateOrmPanacheRestProcessor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/HibernateOrmPanacheRestProcessor.java index 135872bc97aec..3cdfc87dd48a8 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/HibernateOrmPanacheRestProcessor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/HibernateOrmPanacheRestProcessor.java @@ -88,11 +88,11 @@ void findEntityResources(CombinedIndexBuildItem index, ResourceImplementor resourceImplementor = new ResourceImplementor(new EntityClassHelper(index.getComputingIndex())); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getComputingIndex().getKnownDirectImplementors(PANACHE_ENTITY_RESOURCE_INTERFACE)) { - validateResource(index.getComputingIndex(), classInfo); + for (ClassInfo resourceInterface : index.getComputingIndex() + .getKnownDirectImplementors(PANACHE_ENTITY_RESOURCE_INTERFACE)) { + validateResource(index.getComputingIndex(), resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String entityType = generics.get(0).name().toString(); String idType = generics.get(1).name().toString(); @@ -120,12 +120,11 @@ void findRepositoryResources(CombinedIndexBuildItem index, ResourceImplementor resourceImplementor = new ResourceImplementor(new EntityClassHelper(index.getComputingIndex())); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getComputingIndex() + for (ClassInfo resourceInterface : index.getComputingIndex() .getKnownDirectImplementors(PANACHE_REPOSITORY_RESOURCE_INTERFACE)) { - validateResource(index.getComputingIndex(), classInfo); + validateResource(index.getComputingIndex(), resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String repositoryClassName = generics.get(0).name().toString(); String entityType = generics.get(1).name().toString(); String idType = generics.get(2).name().toString(); diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java index b5725d3af8227..25b964f53591e 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java @@ -45,8 +45,9 @@ class ResourceImplementor { * Implements {@link io.quarkus.rest.data.panache.RestDataResource} interfaces defined in a user application. * Instances of this class are registered as beans and are later used in the generated JAX-RS controllers. */ - String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, String resourceType, + String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, ClassInfo resourceInterface, String entityType, List resourceMethodListeners) { + String resourceType = resourceInterface.name().toString(); String className = resourceType + "Impl_" + HashUtil.sha1(resourceType); LOGGER.tracef("Starting generation of '%s'", className); ClassCreator classCreator = ClassCreator.builder() diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/CollectionsResource.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/CollectionsResource.java index 714b6c1c88c59..ea551e7f4bef3 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/CollectionsResource.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/CollectionsResource.java @@ -3,7 +3,9 @@ import java.util.Collections; import java.util.List; +import jakarta.transaction.Transactional; import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; @@ -22,4 +24,15 @@ default Collection findByName(@PathParam("name") String name) { return collections.get(0); } + + @Transactional + @POST + @Path("/name/{name}") + default Collection addByName(@PathParam("name") String name) { + Collection collection = new Collection(); + collection.id = name; + collection.name = name; + Collection.persist(collection); + return collection; + } } diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java index 1742569b65ff3..44ed1024f7ddd 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java @@ -1,5 +1,9 @@ package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import io.quarkus.hibernate.orm.rest.data.panache.deployment.AbstractPostMethodTest; @@ -14,4 +18,13 @@ class PanacheEntityResourcePostMethodTest extends AbstractPostMethodTest { Item.class, ItemsResource.class) .addAsResource("application.properties") .addAsResource("import.sql")); + + @Test + void shouldCopyUserMethodsAnnotatedWithTransactional() { + given().accept("application/json") + .when().post("/collections/name/mycollection") + .then().statusCode(200) + .and().body("id", is("mycollection")) + .and().body("name", is("mycollection")); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/HibernateReactivePanacheRestProcessor.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/HibernateReactivePanacheRestProcessor.java index c416808fa807e..96ebed274b87f 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/HibernateReactivePanacheRestProcessor.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/HibernateReactivePanacheRestProcessor.java @@ -73,11 +73,10 @@ void findEntityResources(CombinedIndexBuildItem indexBuildItem, ResourceImplementor resourceImplementor = new ResourceImplementor(new EntityClassHelper(index)); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getKnownDirectImplementors(PANACHE_ENTITY_RESOURCE_INTERFACE)) { - validateResource(index, classInfo); + for (ClassInfo resourceInterface : index.getKnownDirectImplementors(PANACHE_ENTITY_RESOURCE_INTERFACE)) { + validateResource(index, resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String entityType = generics.get(0).name().toString(); String idType = generics.get(1).name().toString(); @@ -105,11 +104,10 @@ void findRepositoryResources(CombinedIndexBuildItem indexBuildItem, ResourceImplementor resourceImplementor = new ResourceImplementor(new EntityClassHelper(index)); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getKnownDirectImplementors(PANACHE_REPOSITORY_RESOURCE_INTERFACE)) { - validateResource(index, classInfo); + for (ClassInfo resourceInterface : index.getKnownDirectImplementors(PANACHE_REPOSITORY_RESOURCE_INTERFACE)) { + validateResource(index, resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String repositoryClassName = generics.get(0).name().toString(); String entityType = generics.get(1).name().toString(); String idType = generics.get(2).name().toString(); diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/ResourceImplementor.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/ResourceImplementor.java index 2dcc24a7a3a41..17d2aab4f6759 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/ResourceImplementor.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/ResourceImplementor.java @@ -47,8 +47,9 @@ class ResourceImplementor { * Implements {@link io.quarkus.rest.data.panache.ReactiveRestDataResource} interfaces defined in a user application. * Instances of this class are registered as beans and are later used in the generated JAX-RS controllers. */ - String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, String resourceType, + String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, ClassInfo resourceInterface, String entityType, List resourceMethodListeners) { + String resourceType = resourceInterface.name().toString(); String className = resourceType + "Impl_" + HashUtil.sha1(resourceType); LOGGER.tracef("Starting generation of '%s'", className); ClassCreator classCreator = ClassCreator.builder() diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java index 37551efedcfea..37446fc58745a 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java @@ -76,12 +76,11 @@ void findEntityResources(CombinedIndexBuildItem index, Capabilities capabilities ResourceImplementor resourceImplementor = new ResourceImplementor(entityClassHelper); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getComputingIndex() + for (ClassInfo resourceInterface : index.getComputingIndex() .getKnownDirectImplementors(PANACHE_MONGO_ENTITY_RESOURCE_INTERFACE)) { - validateResource(index.getComputingIndex(), classInfo); + validateResource(index.getComputingIndex(), resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String entityType = generics.get(0).toString(); String idType = generics.get(1).toString(); @@ -109,12 +108,11 @@ void findRepositoryResources(CombinedIndexBuildItem index, Capabilities capabili ResourceImplementor resourceImplementor = new ResourceImplementor(entityClassHelper); ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(implementationsProducer); - for (ClassInfo classInfo : index.getComputingIndex() + for (ClassInfo resourceInterface : index.getComputingIndex() .getKnownDirectImplementors(PANACHE_MONGO_REPOSITORY_RESOURCE_INTERFACE)) { - validateResource(index.getComputingIndex(), classInfo); + validateResource(index.getComputingIndex(), resourceInterface); - List generics = getGenericTypes(classInfo); - String resourceInterface = classInfo.name().toString(); + List generics = getGenericTypes(resourceInterface); String repositoryClassName = generics.get(0).toString(); String entityType = generics.get(1).toString(); String idType = generics.get(2).toString(); diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java index 57782d23f21b2..8f7dd2f527fe6 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java @@ -7,6 +7,7 @@ import jakarta.enterprise.context.ApplicationScoped; +import org.jboss.jandex.ClassInfo; import org.jboss.jandex.FieldInfo; import org.jboss.logging.Logger; @@ -37,8 +38,9 @@ class ResourceImplementor { this.entityClassHelper = entityClassHelper; } - String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, String resourceType, + String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplementor, ClassInfo resourceInterface, String entityType) { + String resourceType = resourceInterface.name().toString(); String className = resourceType + "Impl_" + HashUtil.sha1(resourceType); LOGGER.tracef("Starting generation of '%s'", className); ClassCreator classCreator = ClassCreator.builder() 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 eb31ccdaccef8..ecbce04af98a6 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 @@ -26,6 +26,7 @@ import io.quarkus.rest.data.panache.deployment.methods.ListMethodImplementor; import io.quarkus.rest.data.panache.deployment.methods.MethodImplementor; import io.quarkus.rest.data.panache.deployment.methods.UpdateMethodImplementor; +import io.quarkus.rest.data.panache.deployment.methods.UserMethodsWithTransactionalImplementor; import io.quarkus.rest.data.panache.deployment.methods.hal.ListHalMethodImplementor; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; import io.quarkus.runtime.util.HashUtil; @@ -48,6 +49,7 @@ class JaxRsResourceImplementor { new AddMethodImplementor(capabilities), new UpdateMethodImplementor(capabilities), new DeleteMethodImplementor(capabilities), + new UserMethodsWithTransactionalImplementor(capabilities), // The list hal endpoint needs to be added for both resteasy classic and resteasy reactive // because the pagination links are programmatically added. new ListHalMethodImplementor(capabilities)); @@ -77,7 +79,7 @@ void implement(ClassOutput classOutput, ResourceMetadata resourceMetadata, Resou .classOutput(classOutput).className(controllerClassName); if (resourceMetadata.getResourceInterface() != null) { - classCreatorBuilder.interfaces(resourceMetadata.getResourceInterface()); + classCreatorBuilder.interfaces(resourceMetadata.getResourceInterface().name().toString()); } ClassCreator classCreator = classCreatorBuilder.build(); 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 330ce21b81765..0406541131f90 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 @@ -2,6 +2,7 @@ import java.util.Map; +import org.jboss.jandex.ClassInfo; import org.jboss.jandex.Type; public class ResourceMetadata { @@ -19,7 +20,7 @@ public class ResourceMetadata { /** * Application interface that extends RestDataResource interface. */ - private final String resourceInterface; + private final ClassInfo resourceInterface; /** * Entity class that is used by the resource. @@ -36,12 +37,12 @@ public class ResourceMetadata { */ private final Map fields; - public ResourceMetadata(String resourceClass, String resourceInterface, String entityType, String idType, + public ResourceMetadata(String resourceClass, ClassInfo resourceInterface, String entityType, String idType, Map fields) { - this(resourceClass, resourceInterface, resourceInterface, entityType, idType, fields); + this(resourceClass, resourceInterface.name().toString(), resourceInterface, entityType, idType, fields); } - public ResourceMetadata(String resourceClass, String resourceName, String resourceInterface, String entityType, + public ResourceMetadata(String resourceClass, String resourceName, ClassInfo resourceInterface, String entityType, String idType, Map fields) { this.resourceClass = resourceClass; this.resourceName = resourceName; @@ -59,7 +60,7 @@ public String getResourceName() { return resourceName; } - public String getResourceInterface() { + public ClassInfo 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 1c2b5e6607aa0..d59c37a52728c 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 @@ -78,7 +78,7 @@ void implementResources(CombinedIndexBuildItem index, ResourcePropertiesProvider resourcePropertiesProvider = new ResourcePropertiesProvider(index.getIndex()); for (RestDataResourceBuildItem resourceBuildItem : resourceBuildItems) { - if (!excludedClasses.contains(resourceBuildItem.getResourceMetadata().getResourceInterface())) { + if (!excludedClasses.contains(resourceBuildItem.getResourceMetadata().getResourceName())) { ResourceMetadata resourceMetadata = resourceBuildItem.getResourceMetadata(); ResourceProperties resourceProperties = getResourceProperties(resourcePropertiesProvider, resourceMetadata, resourcePropertiesBuildItems); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UserMethodsWithTransactionalImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UserMethodsWithTransactionalImplementor.java new file mode 100644 index 0000000000000..e1992090435e7 --- /dev/null +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UserMethodsWithTransactionalImplementor.java @@ -0,0 +1,62 @@ +package io.quarkus.rest.data.panache.deployment.methods; + +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.DotName; + +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.Capability; +import io.quarkus.gizmo.ClassCreator; +import io.quarkus.gizmo.FieldDescriptor; +import io.quarkus.gizmo.MethodCreator; +import io.quarkus.gizmo.MethodDescriptor; +import io.quarkus.gizmo.ResultHandle; +import io.quarkus.rest.data.panache.deployment.ResourceMetadata; +import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; + +/** + * Propagate the user methods annotated with `@Transactional`. + * This implementor is only used if Hibernate ORM is present. + */ +public final class UserMethodsWithTransactionalImplementor implements MethodImplementor { + + public static final DotName TRANSACTIONAL = DotName.createSimple("jakarta.transaction.Transactional"); + + private final Capabilities capabilities; + + public UserMethodsWithTransactionalImplementor(Capabilities capabilities) { + this.capabilities = capabilities; + } + + @Override + public void implement(ClassCreator classCreator, ResourceMetadata resourceMetadata, + ResourceProperties resourceProperties, FieldDescriptor resourceField) { + if (capabilities.isPresent(Capability.HIBERNATE_ORM) && resourceMetadata.getResourceInterface() != null) { + for (var methodInfo : resourceMetadata.getResourceInterface().methods()) { + // we only need to propagate the user methods annotated with `@Transactional` + if (methodInfo.hasAnnotation(TRANSACTIONAL)) { + MethodCreator methodCreator = classCreator.getMethodCreator(MethodDescriptor.of(methodInfo)); + methodCreator.setSignature(methodInfo.genericSignatureIfRequired()); + for (var annotation : methodInfo.annotations()) { + if (annotation.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER) { + short position = annotation.target().asMethodParameter().position(); + methodCreator.getParameterAnnotations(position).addAnnotation(annotation); + } + + if (annotation.target().kind() == AnnotationTarget.Kind.METHOD) { + methodCreator.addAnnotation(annotation); + } + } + + ResultHandle[] params = new ResultHandle[methodInfo.parametersCount()]; + for (int paramIdx = 0; paramIdx < methodInfo.parametersCount(); paramIdx++) { + params[paramIdx] = methodCreator.getMethodParam(paramIdx); + } + + methodCreator.returnValue( + methodCreator.invokeSpecialInterfaceMethod(methodInfo, methodCreator.getThis(), params)); + methodCreator.close(); + } + } + } + } +}