From 0fd9456bb4d564072a7ef543e771b017b84d15a4 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 21 Dec 2022 11:10:18 +0100 Subject: [PATCH] Fix AbstractMethodError when injecting generated resource Fix https://github.com/quarkusio/quarkus/issues/29885 Plus, this pull request also resolves an ambiguous bean resolution when injecting these resources. --- .../deployment/DataAccessImplementor.java | 19 +++++++++++++ .../EntityDataAccessImplementor.java | 23 ++++++++++++++++ .../RepositoryDataAccessImplementor.java | 23 ++++++++++++++++ .../deployment/ResourceImplementor.java | 21 +++++++++++++++ .../AbstractInjectResourcesMethodTest.java | 17 ++++++++++++ .../deployment/entity/InjectionResource.java | 26 ++++++++++++++++++ ...tityResourceInjectResourcesMethodTest.java | 19 +++++++++++++ .../deployment/DataAccessImplementor.java | 19 +++++++++++++ .../EntityDataAccessImplementor.java | 23 ++++++++++++++++ .../RepositoryDataAccessImplementor.java | 23 ++++++++++++++++ .../deployment/ResourceImplementor.java | 23 +++++++++++++++- .../AbstractInjectResourcesMethodTest.java | 17 ++++++++++++ .../deployment/entity/InjectionResource.java | 27 +++++++++++++++++++ ...tityResourceInjectResourcesMethodTest.java | 19 +++++++++++++ .../src/test/resources/application.properties | 2 +- .../deployment/JaxRsResourceImplementor.java | 8 ++++++ 16 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/InjectionResource.java create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/InjectionResource.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java index 6e42b89c706fd..b944fb334f02a 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java @@ -17,6 +17,25 @@ public interface DataAccessImplementor { */ ResultHandle findById(BytecodeCreator creator, ResultHandle id); + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page); + + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @param sort Sort instance that should be used in a query. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort); + /** * Find all entities. * diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java index 029513c3ed92d..ef1e2375ba6e8 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java @@ -34,6 +34,29 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { id); } + /** + * Implements Entity.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeStaticMethod(ofMethod(entityClassName, "findAll", PanacheQuery.class)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + + /** + * Implements Entity.findAll(sort).page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { + ResultHandle query = creator.invokeStaticMethod( + ofMethod(entityClassName, "findAll", PanacheQuery.class, Sort.class), sort); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + /** * Implements Entity.find(query, params).page(page).list() */ diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java index f91f1a776508a..d8ff8b7bf81f3 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java @@ -39,6 +39,29 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { getRepositoryInstance(creator), id); } + /** + * Implements repository.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheRepositoryBase.class, "findAll", PanacheQuery.class), getRepositoryInstance(creator)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + + /** + * Implements repository.findAll(sort).page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheRepositoryBase.class, "findAll", PanacheQuery.class, Sort.class), + getRepositoryInstance(creator), sort); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + /** * Implements repository.find(query, params).page(page).list() */ 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 0d69dd8bacbbf..c7dbaaa8835ea 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 @@ -5,7 +5,9 @@ import java.util.List; import java.util.Map; +import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Alternative; import javax.transaction.Transactional; import org.jboss.jandex.ClassInfo; @@ -55,11 +57,16 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem .build(); classCreator.addAnnotation(ApplicationScoped.class); + // The same resource is generated as part of the JaxRsResourceImplementor, so we need to avoid ambiguous resolution + // when injecting the resource in user beans: + classCreator.addAnnotation(Alternative.class); + classCreator.addAnnotation(Priority.class).add("value", Integer.MAX_VALUE); ResourceMethodListenerImplementor listenerImplementor = new ResourceMethodListenerImplementor(classCreator, resourceMethodListeners, false); implementList(classCreator, dataAccessImplementor); + implementListWithQuery(classCreator, dataAccessImplementor); implementListPageCount(classCreator, dataAccessImplementor); implementCount(classCreator, dataAccessImplementor); implementGet(classCreator, dataAccessImplementor); @@ -73,6 +80,20 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem } private void implementList(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { + MethodCreator methodCreator = classCreator.getMethodCreator("list", List.class, Page.class, Sort.class); + ResultHandle page = methodCreator.getMethodParam(0); + ResultHandle sort = methodCreator.getMethodParam(1); + ResultHandle columns = methodCreator.invokeVirtualMethod(ofMethod(Sort.class, "getColumns", List.class), sort); + ResultHandle isEmptySort = methodCreator.invokeInterfaceMethod(ofMethod(List.class, "isEmpty", boolean.class), columns); + + BranchResult isEmptySortBranch = methodCreator.ifTrue(isEmptySort); + isEmptySortBranch.trueBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.trueBranch(), page)); + isEmptySortBranch.falseBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.falseBranch(), page, sort)); + + methodCreator.close(); + } + + private void implementListWithQuery(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("list", List.class, Page.class, Sort.class, String.class, Map.class); ResultHandle page = methodCreator.getMethodParam(0); diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java new file mode 100644 index 0000000000000..b17e82af5ccb3 --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java @@ -0,0 +1,17 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.contains; + +import org.junit.jupiter.api.Test; + +public abstract class AbstractInjectResourcesMethodTest { + + @Test + void shouldGetListOfItems() { + given().accept("application/json") + .when().get("/call/resource/items") + .then().statusCode(200) + .and().body("id", contains(1, 2)); + } +} diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/InjectionResource.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/InjectionResource.java new file mode 100644 index 0000000000000..19f2e6e1e90fb --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/InjectionResource.java @@ -0,0 +1,26 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; + +import java.util.List; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import io.quarkus.panache.common.Page; +import io.quarkus.panache.common.Sort; + +@Path("/call/resource") +public class InjectionResource { + + @Inject + ItemsResource itemsResource; + + @GET + @Path("/items") + @Produces(MediaType.APPLICATION_JSON) + public List items() { + return itemsResource.list(new Page(5), Sort.by("id")); + } +} diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java new file mode 100644 index 0000000000000..7a70f6c533636 --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java @@ -0,0 +1,19 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; + +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import io.quarkus.hibernate.orm.panache.PanacheEntityBase; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.AbstractInjectResourcesMethodTest; +import io.quarkus.test.QuarkusUnitTest; + +class PanacheEntityResourceInjectResourcesMethodTest extends AbstractInjectResourcesMethodTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(PanacheEntityBase.class, PanacheEntity.class, Collection.class, CollectionsResource.class, + AbstractEntity.class, AbstractItem.class, Item.class, ItemsResource.class, InjectionResource.class) + .addAsResource("application.properties") + .addAsResource("import.sql")); +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/DataAccessImplementor.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/DataAccessImplementor.java index 6d88361491536..9d3fec3a0b40a 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/DataAccessImplementor.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/DataAccessImplementor.java @@ -17,6 +17,25 @@ public interface DataAccessImplementor { */ ResultHandle findById(BytecodeCreator creator, ResultHandle id); + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page); + + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @param sort Sort instance that should be used in a query. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort); + /** * Find all entities. * diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/EntityDataAccessImplementor.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/EntityDataAccessImplementor.java index 95c5192b84525..ca0d84fbe5cff 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/EntityDataAccessImplementor.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/EntityDataAccessImplementor.java @@ -34,6 +34,29 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { id); } + /** + * Implements Entity.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeStaticMethod(ofMethod(entityClassName, "findAll", PanacheQuery.class)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", Uni.class), query); + } + + /** + * Implements Entity.findAll(sort).page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { + ResultHandle query = creator.invokeStaticMethod( + ofMethod(entityClassName, "findAll", PanacheQuery.class, Sort.class), sort); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", Uni.class), query); + } + /** * Implements Entity.findAll(query, params).page(page).list() */ diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/RepositoryDataAccessImplementor.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/RepositoryDataAccessImplementor.java index 6382f63a11f9f..603ce94caec84 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/RepositoryDataAccessImplementor.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/RepositoryDataAccessImplementor.java @@ -39,6 +39,29 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { getRepositoryInstance(creator), id); } + /** + * Implements repository.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheRepositoryBase.class, "findAll", PanacheQuery.class), getRepositoryInstance(creator)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", Uni.class), query); + } + + /** + * Implements repository.findAll(sort).page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheRepositoryBase.class, "findAll", PanacheQuery.class, Sort.class), + getRepositoryInstance(creator), sort); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", Uni.class), query); + } + /** * Implements repository.find(query, params).page(page).list() */ 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 448a741b85413..157a570140815 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 @@ -5,7 +5,9 @@ import java.util.List; import java.util.Map; +import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Alternative; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.FieldInfo; @@ -56,13 +58,18 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem .build(); classCreator.addAnnotation(ApplicationScoped.class); + // The same resource is generated as part of the JaxRsResourceImplementor, so we need to avoid ambiguous resolution + // when injecting the resource in user beans: + classCreator.addAnnotation(Alternative.class); + classCreator.addAnnotation(Priority.class).add("value", Integer.MAX_VALUE); ResourceMethodListenerImplementor resourceMethodListenerImplementor = new ResourceMethodListenerImplementor( classCreator, resourceMethodListeners, true); implementList(classCreator, dataAccessImplementor); - implementCount(classCreator, dataAccessImplementor); + implementListWithQuery(classCreator, dataAccessImplementor); implementListPageCount(classCreator, dataAccessImplementor); + implementCount(classCreator, dataAccessImplementor); implementGet(classCreator, dataAccessImplementor); implementAdd(classCreator, dataAccessImplementor, resourceMethodListenerImplementor); implementUpdate(classCreator, dataAccessImplementor, entityType, resourceMethodListenerImplementor); @@ -74,6 +81,20 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem } private void implementList(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { + MethodCreator methodCreator = classCreator.getMethodCreator("list", Uni.class, Page.class, Sort.class); + ResultHandle page = methodCreator.getMethodParam(0); + ResultHandle sort = methodCreator.getMethodParam(1); + ResultHandle columns = methodCreator.invokeVirtualMethod(ofMethod(Sort.class, "getColumns", List.class), sort); + ResultHandle isEmptySort = methodCreator.invokeInterfaceMethod(ofMethod(List.class, "isEmpty", boolean.class), columns); + + BranchResult isEmptySortBranch = methodCreator.ifTrue(isEmptySort); + isEmptySortBranch.trueBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.trueBranch(), page)); + isEmptySortBranch.falseBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.falseBranch(), page, sort)); + + methodCreator.close(); + } + + private void implementListWithQuery(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("list", Uni.class, Page.class, Sort.class, String.class, Map.class); ResultHandle page = methodCreator.getMethodParam(0); diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java new file mode 100644 index 0000000000000..522d322d01d8b --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractInjectResourcesMethodTest.java @@ -0,0 +1,17 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.contains; + +import org.junit.jupiter.api.Test; + +public abstract class AbstractInjectResourcesMethodTest { + + @Test + void shouldGetListOfItems() { + given().accept("application/json") + .when().get("/call/resource/items") + .then().statusCode(200) + .and().body("id", contains(1, 2)); + } +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/InjectionResource.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/InjectionResource.java new file mode 100644 index 0000000000000..19596484519c3 --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/InjectionResource.java @@ -0,0 +1,27 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; + +import java.util.List; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import io.quarkus.panache.common.Page; +import io.quarkus.panache.common.Sort; +import io.smallrye.mutiny.Uni; + +@Path("/call/resource") +public class InjectionResource { + + @Inject + ItemsResource itemsResource; + + @GET + @Path("/items") + @Produces(MediaType.APPLICATION_JSON) + public Uni> items() { + return itemsResource.list(new Page(5), Sort.by("id")); + } +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java new file mode 100644 index 0000000000000..63615ecadc300 --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceInjectResourcesMethodTest.java @@ -0,0 +1,19 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; + +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.reactive.panache.PanacheEntity; +import io.quarkus.hibernate.reactive.panache.PanacheEntityBase; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.AbstractInjectResourcesMethodTest; +import io.quarkus.test.QuarkusUnitTest; + +class PanacheEntityResourceInjectResourcesMethodTest extends AbstractInjectResourcesMethodTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(PanacheEntityBase.class, PanacheEntity.class, Collection.class, CollectionsResource.class, + AbstractEntity.class, AbstractItem.class, Item.class, ItemsResource.class, InjectionResource.class) + .addAsResource("application.properties") + .addAsResource("import.sql")); +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/resources/application.properties b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/resources/application.properties index ce8f669b3ab75..c58689900bbea 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/resources/application.properties +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/resources/application.properties @@ -2,6 +2,6 @@ quarkus.datasource.db-kind=postgresql quarkus.datasource.username=hibernate_orm_test quarkus.datasource.password=hibernate_orm_test quarkus.datasource.reactive=true -quarkus.datasource.reactive.url=${postgres.reactive.url} +quarkus.datasource.reactive.url=vertx-reactive:postgresql://localhost:5431/hibernate_orm_test quarkus.hibernate-orm.database.generation=drop-and-create 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 bbaa04cb04bc3..26662b646e1c2 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 @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.List; +import javax.annotation.Priority; +import javax.enterprise.inject.Alternative; import javax.inject.Inject; import javax.ws.rs.Path; @@ -78,6 +80,12 @@ void implement(ClassOutput classOutput, ResourceMetadata resourceMetadata, Resou } ClassCreator classCreator = classCreatorBuilder.build(); + // The same resource is generated as part of the ResourceImplementor, so we need to avoid ambiguous resolution + // when injecting the resource in user beans: + if (resourceMetadata.getResourceInterface() != null) { + classCreator.addAnnotation(Alternative.class); + classCreator.addAnnotation(Priority.class).add("value", Integer.MIN_VALUE); + } implementClassAnnotations(classCreator, resourceMetadata, resourceProperties, capabilities); FieldDescriptor resourceField = implementResourceField(classCreator, resourceMetadata);