From c13bbbae4e21b665ab733c0b3ed0beeafb4ffadf Mon Sep 17 00:00:00 2001 From: Jose Date: Thu, 3 Aug 2023 09:10:09 +0200 Subject: [PATCH] REST Data with Panache should not produce links when hal is disabled This is related to https://github.com/quarkusio/quarkus/issues/35167. Even though HAL is disabled by default, it's still used to generate unexpected links and to set the location. --- .../PanacheEntityResourceHalDisabledTest.java | 49 +++++++++++++++++++ .../panache/deployment/entity/Project.java | 12 +++++ .../deployment/entity/ProjectResource.java | 11 +++++ .../PanacheEntityResourceHalDisabledTest.java | 45 +++++++++++++++++ .../panache/deployment/entity/Project.java | 12 +++++ .../deployment/entity/ProjectResource.java | 11 +++++ .../methods/AddMethodImplementor.java | 6 +-- .../methods/CountMethodImplementor.java | 2 +- .../methods/DeleteMethodImplementor.java | 2 +- .../methods/GetMethodImplementor.java | 2 +- .../methods/ListMethodImplementor.java | 4 +- .../methods/StandardMethodImplementor.java | 29 ++++++----- .../methods/UpdateMethodImplementor.java | 20 ++++---- .../deployment/utils/ResponseImplementor.java | 28 +++++++---- 14 files changed, 193 insertions(+), 40 deletions(-) create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Project.java create mode 100644 extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/ProjectResource.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Project.java create mode 100644 extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/ProjectResource.java diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java new file mode 100644 index 00000000000000..8acc37ef4cd0c0 --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java @@ -0,0 +1,49 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.equalTo; +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.AbstractPutMethodTest; +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.response.Response; + +class PanacheEntityResourceHalDisabledTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Project.class, ProjectResource.class) + .addAsResource("application.properties")); + + @Test + void shouldHalNotBeSupported() { + given().accept("application/hal+json") + .when().get("/group/projects/1") + .then().statusCode(406); + } + + @Test + void shouldNotContainLocationAndLinks() { + Response response = given().accept("application/json") + .and().contentType("application/json") + .and().body("{\"name\": \"projectname\"}") + .when().post("/group/projects") + .thenReturn(); + assertThat(response.statusCode()).isEqualTo(201); + assertThat(response.header("Location")).isBlank(); + assertThat(response.getHeaders().getList("Link")).isEmpty(); + + response = given().accept("application/json") + .when().get("/group/projects/projectname") + .thenReturn(); + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.header("Location")).isBlank(); + assertThat(response.getHeaders().getList("Link")).isEmpty(); + } +} diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Project.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Project.java new file mode 100644 index 00000000000000..e8f050921bdab1 --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Project.java @@ -0,0 +1,12 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; + +import io.quarkus.hibernate.orm.panache.PanacheEntityBase; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class Project extends PanacheEntityBase { + + @Id + public String name; +} diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/ProjectResource.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/ProjectResource.java new file mode 100644 index 00000000000000..1a939ff3ce66f8 --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/ProjectResource.java @@ -0,0 +1,11 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity; + +import io.quarkus.hibernate.orm.rest.data.panache.PanacheEntityResource; +import io.quarkus.rest.data.panache.ResourceProperties; + +/** + * Having a path param in the path reproduces the issue of having HAL enabled spites it should be disabled by default. + */ +@ResourceProperties(path = "/{group}/projects") +public interface ProjectResource extends PanacheEntityResource { +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java new file mode 100644 index 00000000000000..aad658564a479b --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/PanacheEntityResourceHalDisabledTest.java @@ -0,0 +1,45 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.response.Response; + +class PanacheEntityResourceHalDisabledTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Project.class, ProjectResource.class) + .addAsResource("application.properties")); + + @Test + void shouldHalNotBeSupported() { + given().accept("application/hal+json") + .when().get("/group/projects/1") + .then().statusCode(406); + } + + @Test + void shouldNotContainLocationAndLinks() { + Response response = given().accept("application/json") + .and().contentType("application/json") + .and().body("{\"name\": \"projectname\"}") + .when().post("/group/projects") + .thenReturn(); + assertThat(response.statusCode()).isEqualTo(201); + assertThat(response.header("Location")).isBlank(); + assertThat(response.getHeaders().getList("Link")).isEmpty(); + + response = given().accept("application/json") + .when().get("/group/projects/projectname") + .thenReturn(); + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.header("Location")).isBlank(); + assertThat(response.getHeaders().getList("Link")).isEmpty(); + } +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Project.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Project.java new file mode 100644 index 00000000000000..2833438775e2ee --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Project.java @@ -0,0 +1,12 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; + +import io.quarkus.hibernate.reactive.panache.PanacheEntityBase; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class Project extends PanacheEntityBase { + + @Id + public String name; +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/ProjectResource.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/ProjectResource.java new file mode 100644 index 00000000000000..c22a85d8899a34 --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/ProjectResource.java @@ -0,0 +1,11 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity; + +import io.quarkus.hibernate.reactive.rest.data.panache.PanacheEntityResource; +import io.quarkus.rest.data.panache.ResourceProperties; + +/** + * Having a path param in the path reproduces the issue of having HAL enabled spites it should be disabled by default. + */ +@ResourceProperties(path = "/{group}/projects") +public interface ProjectResource extends PanacheEntityResource { +} diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java index f3f719f7669483..eb862c9601d9ff 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java @@ -114,7 +114,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res addContextAnnotation(methodCreator.getParameterAnnotations(1)); addConsumesAnnotation(methodCreator, APPLICATION_JSON); addProducesJsonAnnotation(methodCreator, resourceProperties); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); addOpenApiResponseAnnotation(methodCreator, Response.Status.CREATED, resourceMetadata.getEntityType()); addSecurityAnnotations(methodCreator, resourceProperties); // Add parameter annotations @@ -130,7 +130,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res ResultHandle entity = tryBlock.invokeVirtualMethod( ofMethod(resourceMetadata.getResourceClass(), RESOURCE_METHOD_NAME, Object.class, Object.class), resource, entityToSave); - tryBlock.returnValue(responseImplementor.created(tryBlock, entity)); + tryBlock.returnValue(responseImplementor.created(tryBlock, entity, resourceProperties)); tryBlock.close(); } else { ResultHandle uniEntity = methodCreator.invokeVirtualMethod( @@ -138,7 +138,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res resource, entityToSave); methodCreator.returnValue(UniImplementor.map(methodCreator, uniEntity, EXCEPTION_MESSAGE, - (body, item) -> body.returnValue(responseImplementor.created(body, item)))); + (body, item) -> body.returnValue(responseImplementor.created(body, item, resourceProperties)))); } methodCreator.close(); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java index 334875ce9f402d..a77e466b742c84 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java @@ -87,7 +87,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res if (!isResteasyClassic()) { // We only add the Links annotation in Resteasy Reactive because Resteasy Classic ignores the REL parameter: // it always uses "list" for GET methods, so it interferes with the list implementation. - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); } ResultHandle resource = methodCreator.readInstanceField(resourceField, methodCreator.getThis()); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java index 6cb73e874a5b93..0734705ec18698 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java @@ -91,7 +91,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res addPathAnnotation(methodCreator, appendToPath(resourceProperties.getPath(RESOURCE_METHOD_NAME), "{id}")); addDeleteAnnotation(methodCreator); addPathParamAnnotation(methodCreator.getParameterAnnotations(0), "id"); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); addMethodAnnotations(methodCreator, resourceProperties.getMethodAnnotations(RESOURCE_METHOD_NAME)); addOpenApiResponseAnnotation(methodCreator, Response.Status.NO_CONTENT); addSecurityAnnotations(methodCreator, resourceProperties); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java index 5f59df6fe30a0f..098fa9d3049d64 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java @@ -98,7 +98,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res addSecurityAnnotations(methodCreator, resourceProperties); addPathParamAnnotation(methodCreator.getParameterAnnotations(0), "id"); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); ResultHandle resource = methodCreator.readInstanceField(resourceField, methodCreator.getThis()); ResultHandle id = methodCreator.getMethodParam(0); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java index 2c46c6172868f7..1b8ec8077590f6 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java @@ -193,7 +193,7 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource addGetAnnotation(methodCreator); addPathAnnotation(methodCreator, resourceProperties.getPath(RESOURCE_METHOD_NAME)); addProducesJsonAnnotation(methodCreator, resourceProperties); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); addMethodAnnotations(methodCreator, resourceProperties.getMethodAnnotations(RESOURCE_METHOD_NAME)); addOpenApiResponseAnnotation(methodCreator, Response.Status.OK, resourceMetadata.getEntityType(), true); addSecurityAnnotations(methodCreator, resourceProperties); @@ -280,7 +280,7 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou addGetAnnotation(methodCreator); addPathAnnotation(methodCreator, resourceProperties.getPath(RESOURCE_METHOD_NAME)); addProducesJsonAnnotation(methodCreator, resourceProperties); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); addMethodAnnotations(methodCreator, resourceProperties.getMethodAnnotations(RESOURCE_METHOD_NAME)); addOpenApiResponseAnnotation(methodCreator, Response.Status.OK, resourceMetadata.getEntityType(), true); addSecurityAnnotations(methodCreator, resourceProperties); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java index d12d3a9eb279e5..449cfc39e42709 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java @@ -100,20 +100,23 @@ protected void addDeleteAnnotation(AnnotatedElement element) { element.addAnnotation(DELETE.class); } - protected void addLinksAnnotation(AnnotatedElement element, String entityClassName, String rel) { - if (isResteasyClassic()) { - AnnotationCreator linkResource = element.addAnnotation("org.jboss.resteasy.links.LinkResource"); - linkResource.addValue("entityClassName", entityClassName); - linkResource.addValue("rel", rel); - } else { - AnnotationCreator linkResource = element.addAnnotation("io.quarkus.resteasy.reactive.links.RestLink"); - Class entityClass; - try { - entityClass = Thread.currentThread().getContextClassLoader().loadClass(entityClassName); - linkResource.addValue("entityType", entityClass); + protected void addLinksAnnotation(AnnotatedElement element, ResourceProperties resourceProperties, String entityClassName, + String rel) { + if (resourceProperties.isHal()) { + if (isResteasyClassic()) { + AnnotationCreator linkResource = element.addAnnotation("org.jboss.resteasy.links.LinkResource"); + linkResource.addValue("entityClassName", entityClassName); linkResource.addValue("rel", rel); - } catch (ClassNotFoundException e) { - LOGGER.error("Unable to create links for entity: '" + entityClassName + "'", e); + } else { + AnnotationCreator linkResource = element.addAnnotation("io.quarkus.resteasy.reactive.links.RestLink"); + Class entityClass; + try { + entityClass = Thread.currentThread().getContextClassLoader().loadClass(entityClassName); + linkResource.addValue("entityType", entityClass); + linkResource.addValue("rel", rel); + } catch (ClassNotFoundException e) { + LOGGER.error("Unable to create links for entity: '" + entityClassName + "'", e); + } } } } diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java index baa8f7fa0a87be..2f42be5938390f 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java @@ -148,7 +148,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res addContextAnnotation(methodCreator.getParameterAnnotations(2)); addConsumesAnnotation(methodCreator, APPLICATION_JSON); addProducesJsonAnnotation(methodCreator, resourceProperties); - addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL); + addLinksAnnotation(methodCreator, resourceProperties, resourceMetadata.getEntityType(), REL); addMethodAnnotations(methodCreator, resourceProperties.getMethodAnnotations(RESOURCE_UPDATE_METHOD_NAME)); addOpenApiResponseAnnotation(methodCreator, Response.Status.CREATED, resourceMetadata.getEntityType()); addSecurityAnnotations(methodCreator, resourceProperties); @@ -162,9 +162,9 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res ResultHandle entityToSave = methodCreator.getMethodParam(1); if (isNotReactivePanache()) { - implementClassicVersion(methodCreator, resourceMetadata, resource, id, entityToSave); + implementClassicVersion(methodCreator, resourceMetadata, resourceProperties, resource, id, entityToSave); } else { - implementReactiveVersion(methodCreator, resourceMetadata, resource, id, entityToSave); + implementReactiveVersion(methodCreator, resourceMetadata, resourceProperties, resource, id, entityToSave); } methodCreator.close(); @@ -175,8 +175,8 @@ protected String getResourceMethodName() { return RESOURCE_UPDATE_METHOD_NAME; } - private void implementReactiveVersion(MethodCreator methodCreator, ResourceMetadata resourceMetadata, ResultHandle resource, - ResultHandle id, ResultHandle entityToSave) { + private void implementReactiveVersion(MethodCreator methodCreator, ResourceMetadata resourceMetadata, + ResourceProperties resourceProperties, ResultHandle resource, ResultHandle id, ResultHandle entityToSave) { ResultHandle uniResponse = methodCreator.invokeVirtualMethod( ofMethod(resourceMetadata.getResourceClass(), RESOURCE_GET_METHOD_NAME, Uni.class, Object.class), resource, id); @@ -193,15 +193,16 @@ private void implementReactiveVersion(MethodCreator methodCreator, ResourceMetad (updateBody, itemUpdated) -> { BranchResult ifEntityIsNew = updateBody.ifNull(itemWasFound); ifEntityIsNew.trueBranch() - .returnValue(responseImplementor.created(ifEntityIsNew.trueBranch(), itemUpdated)); + .returnValue(responseImplementor.created(ifEntityIsNew.trueBranch(), itemUpdated, + resourceProperties)); ifEntityIsNew.falseBranch() .returnValue(responseImplementor.noContent(ifEntityIsNew.falseBranch())); })); })); } - private void implementClassicVersion(MethodCreator methodCreator, ResourceMetadata resourceMetadata, ResultHandle resource, - ResultHandle id, ResultHandle entityToSave) { + private void implementClassicVersion(MethodCreator methodCreator, ResourceMetadata resourceMetadata, + ResourceProperties resourceProperties, ResultHandle resource, ResultHandle id, ResultHandle entityToSave) { // Invoke resource methods inside a supplier function which will be given to an update executor. // For ORM, this update executor will have the @Transactional annotation to make // sure that all database operations are executed in a single transaction. @@ -214,7 +215,8 @@ private void implementClassicVersion(MethodCreator methodCreator, ResourceMetada updateExecutor, updateFunction); BranchResult createdNewEntity = tryBlock.ifNotNull(newEntity); - createdNewEntity.trueBranch().returnValue(responseImplementor.created(createdNewEntity.trueBranch(), newEntity)); + createdNewEntity.trueBranch() + .returnValue(responseImplementor.created(createdNewEntity.trueBranch(), newEntity, resourceProperties)); createdNewEntity.falseBranch().returnValue(responseImplementor.noContent(createdNewEntity.falseBranch())); } diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/ResponseImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/ResponseImplementor.java index e2db59b6b95fd2..834ae183d89b56 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/ResponseImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/ResponseImplementor.java @@ -19,6 +19,7 @@ import io.quarkus.gizmo.MethodDescriptor; import io.quarkus.gizmo.ResultHandle; import io.quarkus.hal.HalService; +import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; import io.quarkus.resteasy.links.runtime.hal.ResteasyHalService; import io.quarkus.resteasy.reactive.links.runtime.hal.ResteasyReactiveHalService; @@ -44,17 +45,12 @@ public ResultHandle ok(BytecodeCreator creator, ResultHandle entity, ResultHandl return creator.invokeVirtualMethod(ofMethod(ResponseBuilder.class, "build", Response.class), builder); } - public ResultHandle created(BytecodeCreator creator, ResultHandle entity) { - return created(creator, entity, getEntityUrl(creator, entity)); - } + public ResultHandle created(BytecodeCreator creator, ResultHandle entity, ResourceProperties resourceProperties) { + if (resourceProperties.isHal()) { + return doCreated(creator, entity, getEntityUrl(creator, entity)); + } - public ResultHandle created(BytecodeCreator creator, ResultHandle entity, ResultHandle location) { - ResultHandle builder = getResponseBuilder(creator, Response.Status.CREATED.getStatusCode()); - creator.invokeVirtualMethod( - ofMethod(ResponseBuilder.class, "entity", ResponseBuilder.class, Object.class), builder, entity); - creator.invokeVirtualMethod( - ofMethod(ResponseBuilder.class, "location", ResponseBuilder.class, URI.class), builder, location); - return creator.invokeVirtualMethod(ofMethod(ResponseBuilder.class, "build", Response.class), builder); + return doCreated(creator, entity, null); } public ResultHandle getEntityUrl(BytecodeCreator creator, ResultHandle entity) { @@ -89,6 +85,18 @@ public ResultHandle notFoundException(BytecodeCreator creator) { creator.load(Response.Status.NOT_FOUND.getStatusCode())); } + private ResultHandle doCreated(BytecodeCreator creator, ResultHandle entity, ResultHandle location) { + ResultHandle builder = getResponseBuilder(creator, Response.Status.CREATED.getStatusCode()); + creator.invokeVirtualMethod( + ofMethod(ResponseBuilder.class, "entity", ResponseBuilder.class, Object.class), builder, entity); + if (location != null) { + creator.invokeVirtualMethod( + ofMethod(ResponseBuilder.class, "location", ResponseBuilder.class, URI.class), builder, location); + } + + return creator.invokeVirtualMethod(ofMethod(ResponseBuilder.class, "build", Response.class), builder); + } + private ResultHandle status(BytecodeCreator creator, int status) { ResultHandle builder = getResponseBuilder(creator, status); return creator.invokeVirtualMethod(ofMethod(ResponseBuilder.class, "build", Response.class), builder);