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 6fc0fb62e719d..2dcc24a7a3a41 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 @@ -20,7 +20,7 @@ import io.quarkus.gizmo.MethodCreator; import io.quarkus.gizmo.MethodDescriptor; import io.quarkus.gizmo.ResultHandle; -import io.quarkus.hibernate.reactive.panache.common.WithSession; +import io.quarkus.hibernate.reactive.panache.common.WithSessionOnDemand; import io.quarkus.hibernate.reactive.panache.common.WithTransaction; import io.quarkus.panache.common.Page; import io.quarkus.panache.common.Sort; @@ -62,6 +62,7 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem // when injecting the resource in user beans: classCreator.addAnnotation(Alternative.class); classCreator.addAnnotation(Priority.class).add("value", Integer.MAX_VALUE); + classCreator.addAnnotation(WithSessionOnDemand.class); HibernateReactiveResourceMethodListenerImplementor resourceMethodListenerImplementor = new HibernateReactiveResourceMethodListenerImplementor( classCreator, resourceMethodListeners); @@ -82,7 +83,6 @@ String implement(ClassOutput classOutput, DataAccessImplementor dataAccessImplem private void implementList(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("list", Uni.class, Page.class, Sort.class); - methodCreator.addAnnotation(WithSession.class); ResultHandle page = methodCreator.getMethodParam(0); ResultHandle sort = methodCreator.getMethodParam(1); ResultHandle columns = methodCreator.invokeVirtualMethod(ofMethod(Sort.class, "getColumns", List.class), sort); @@ -98,7 +98,6 @@ private void implementList(ClassCreator classCreator, DataAccessImplementor data private void implementListWithQuery(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("list", Uni.class, Page.class, Sort.class, String.class, Map.class); - methodCreator.addAnnotation(WithSession.class); ResultHandle page = methodCreator.getMethodParam(0); ResultHandle sort = methodCreator.getMethodParam(1); ResultHandle query = methodCreator.getMethodParam(2); @@ -120,7 +119,6 @@ private void implementListWithQuery(ClassCreator classCreator, DataAccessImpleme */ private void implementCount(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("count", Uni.class); - methodCreator.addAnnotation(WithSession.class); methodCreator.returnValue(dataAccessImplementor.count(methodCreator)); methodCreator.close(); } @@ -132,7 +130,6 @@ private void implementCount(ClassCreator classCreator, DataAccessImplementor dat private void implementListPageCount(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator(Constants.PAGE_COUNT_METHOD_PREFIX + "list", Uni.class, Page.class); - methodCreator.addAnnotation(WithSession.class); ResultHandle page = methodCreator.getMethodParam(0); methodCreator.returnValue(dataAccessImplementor.pageCount(methodCreator, page)); methodCreator.close(); @@ -140,7 +137,6 @@ private void implementListPageCount(ClassCreator classCreator, DataAccessImpleme private void implementGet(ClassCreator classCreator, DataAccessImplementor dataAccessImplementor) { MethodCreator methodCreator = classCreator.getMethodCreator("get", Uni.class, Object.class); - methodCreator.addAnnotation(WithSession.class); ResultHandle id = methodCreator.getMethodParam(0); methodCreator.returnValue(dataAccessImplementor.findById(methodCreator, id)); methodCreator.close(); 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 index 522d322d01d8b..0a1b32680ab70 100644 --- 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 @@ -2,6 +2,7 @@ import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; import org.junit.jupiter.api.Test; @@ -14,4 +15,13 @@ void shouldGetListOfItems() { .then().statusCode(200) .and().body("id", contains(1, 2)); } + + @Test + void shouldCollectionByName() { + given().accept("application/json") + .when().get("/call/resource/collectionByName/full collection") + .then().statusCode(200) + .and().body("id", is("full")) + .and().body("name", is("full collection")); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/CollectionsResource.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/CollectionsResource.java index bcf2595d487a9..8b2db9ab78106 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/CollectionsResource.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/CollectionsResource.java @@ -1,8 +1,30 @@ package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; +import java.util.Collections; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + import io.quarkus.hibernate.reactive.rest.data.panache.PanacheEntityResource; import io.quarkus.rest.data.panache.ResourceProperties; +import io.smallrye.mutiny.Uni; @ResourceProperties(hal = true, paged = false, halCollectionName = "item-collections") public interface CollectionsResource extends PanacheEntityResource { + @GET + @Path("/name/{name}") + default Uni findByName(@PathParam("name") String name) { + return Collection.find("name = :name", Collections.singletonMap("name", name)).singleResult(); + } + + @POST + @Path("/name/{name}") + default Uni addByName(@PathParam("name") String name) { + Collection collection = new Collection(); + collection.id = name; + collection.name = name; + return Collection.persist(collection).onItem().transform(res -> collection); + } } 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 index ef961bbd2922f..1addf66232756 100644 --- 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 @@ -5,6 +5,7 @@ import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; @@ -18,10 +19,20 @@ public class InjectionResource { @Inject ItemsResource itemsResource; + @Inject + CollectionsResource collectionsResource; + @GET @Path("/items") @Produces(MediaType.APPLICATION_JSON) public Uni> items() { return itemsResource.list(new Page(5), Sort.by("id")); } + + @GET + @Path("/collectionByName/{name}") + @Produces(MediaType.APPLICATION_JSON) + public Uni collectionByName(@PathParam("name") String name) { + return collectionsResource.findByName(name); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceGetMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceGetMethodTest.java index 536d893409eeb..6290512bb78d2 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceGetMethodTest.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceGetMethodTest.java @@ -1,5 +1,9 @@ package io.quarkus.hibernate.reactive.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.reactive.rest.data.panache.deployment.AbstractGetMethodTest; @@ -15,4 +19,13 @@ class PanacheEntityResourceGetMethodTest extends AbstractGetMethodTest { EmptyListItem.class, EmptyListItemsResource.class) .addAsResource("application.properties") .addAsResource("import.sql")); + + @Test + void shouldCopyAdditionalMethodsAsResources() { + given().accept("application/json") + .when().get("/collections/name/full collection") + .then().statusCode(200) + .and().body("id", is("full")) + .and().body("name", is("full collection")); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java index fea432427db38..d575e9c557c6d 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourcePostMethodTest.java @@ -1,5 +1,9 @@ package io.quarkus.hibernate.reactive.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.reactive.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 shouldCopyAdditionalMethodsAsResources() { + 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/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/CollectionsResource.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/CollectionsResource.java index e24f791173789..137642ce48a84 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/CollectionsResource.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/CollectionsResource.java @@ -1,5 +1,12 @@ package io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository; +import java.util.Collections; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + import io.quarkus.hibernate.reactive.rest.data.panache.PanacheRepositoryResource; import io.quarkus.rest.data.panache.MethodProperties; import io.quarkus.rest.data.panache.ResourceProperties; @@ -10,4 +17,19 @@ public interface CollectionsResource extends PanacheRepositoryResource delete(String name); + + @GET + @Path("/name/{name}") + default Uni findByName(@PathParam("name") String name) { + return Collection.find("name = :name", Collections.singletonMap("name", name)).singleResult(); + } + + @POST + @Path("/name/{name}") + default Uni addByName(@PathParam("name") String name) { + Collection collection = new Collection(); + collection.id = name; + collection.name = name; + return Collection.persist(collection).onItem().transform(res -> collection); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourceGetMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourceGetMethodTest.java index 1554e52727a68..90932cfc7216a 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourceGetMethodTest.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourceGetMethodTest.java @@ -1,5 +1,9 @@ package io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository; +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.reactive.rest.data.panache.deployment.AbstractGetMethodTest; @@ -16,4 +20,13 @@ class PanacheRepositoryResourceGetMethodTest extends AbstractGetMethodTest { EmptyListItemsResource.class) .addAsResource("application.properties") .addAsResource("import.sql")); + + @Test + void shouldCopyAdditionalMethodsAsResources() { + given().accept("application/json") + .when().get("/collections/name/full collection") + .then().statusCode(200) + .and().body("id", is("full")) + .and().body("name", is("full collection")); + } } diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourcePostMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourcePostMethodTest.java index 4835a1080e3cc..a4e39ce66abc3 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourcePostMethodTest.java +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/PanacheRepositoryResourcePostMethodTest.java @@ -1,5 +1,9 @@ package io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository; +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.reactive.rest.data.panache.deployment.AbstractPostMethodTest; @@ -15,4 +19,13 @@ class PanacheRepositoryResourcePostMethodTest extends AbstractPostMethodTest { ItemsRepository.class) .addAsResource("application.properties") .addAsResource("import.sql")); + + @Test + void shouldCopyAdditionalMethodsAsResources() { + 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/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 2a94eb832dabb..eb31ccdaccef8 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 @@ -37,6 +37,7 @@ class JaxRsResourceImplementor { private static final Logger LOGGER = Logger.getLogger(JaxRsResourceImplementor.class); private static final String OPENAPI_TAG_ANNOTATION = "org.eclipse.microprofile.openapi.annotations.tags.Tag"; + private static final String WITH_SESSION_ON_DEMAND_ANNOTATION = "io.quarkus.hibernate.reactive.panache.common.WithSessionOnDemand"; private final List methodImplementors; @@ -107,6 +108,9 @@ private void implementClassAnnotations(ClassCreator classCreator, ResourceMetada classCreator.addAnnotation(classAnnotation); } } + if (capabilities.isPresent(Capability.HIBERNATE_REACTIVE)) { + classCreator.addAnnotation(WITH_SESSION_ON_DEMAND_ANNOTATION); + } } private FieldDescriptor implementResourceField(ClassCreator classCreator, ResourceMetadata resourceMetadata) {