Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix user methods requiring a session in Panache REST Data with Reactive #34542

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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();
}
Expand All @@ -132,15 +130,13 @@ 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();
}

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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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"));
}
}
Original file line number Diff line number Diff line change
@@ -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<Collection, String> {
@GET
@Path("/name/{name}")
default Uni<Collection> findByName(@PathParam("name") String name) {
return Collection.find("name = :name", Collections.singletonMap("name", name)).singleResult();
}

@POST
@Path("/name/{name}")
default Uni<Collection> addByName(@PathParam("name") String name) {
Collection collection = new Collection();
collection.id = name;
collection.name = name;
return Collection.persist(collection).onItem().transform(res -> collection);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -18,10 +19,20 @@ public class InjectionResource {
@Inject
ItemsResource itemsResource;

@Inject
CollectionsResource collectionsResource;

@GET
@Path("/items")
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<Item>> items() {
return itemsResource.list(new Page(5), Sort.by("id"));
}

@GET
@Path("/collectionByName/{name}")
@Produces(MediaType.APPLICATION_JSON)
public Uni<Collection> collectionByName(@PathParam("name") String name) {
return collectionsResource.findByName(name);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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"));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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"));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -10,4 +17,19 @@ public interface CollectionsResource extends PanacheRepositoryResource<Collectio

@MethodProperties(rolesAllowed = "admin")
Uni<Boolean> delete(String name);

@GET
@Path("/name/{name}")
default Uni<Collection> findByName(@PathParam("name") String name) {
return Collection.find("name = :name", Collections.singletonMap("name", name)).singleResult();
}

@POST
@Path("/name/{name}")
default Uni<Collection> addByName(@PathParam("name") String name) {
Collection collection = new Collection();
collection.id = name;
collection.name = name;
return Collection.persist(collection).onItem().transform(res -> collection);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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"));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<MethodImplementor> methodImplementors;

Expand Down Expand Up @@ -107,6 +108,9 @@ private void implementClassAnnotations(ClassCreator classCreator, ResourceMetada
classCreator.addAnnotation(classAnnotation);
}
}
if (capabilities.isPresent(Capability.HIBERNATE_REACTIVE)) {
mkouba marked this conversation as resolved.
Show resolved Hide resolved
classCreator.addAnnotation(WITH_SESSION_ON_DEMAND_ANNOTATION);
}
}

private FieldDescriptor implementResourceField(ClassCreator classCreator, ResourceMetadata resourceMetadata) {
Expand Down