From 170aa5e4625fac3a6eaf1edbcd7d0bd7629de5ba Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sat, 27 Jan 2024 16:07:01 +0100 Subject: [PATCH] amend HsOfficePartnerController and test to new data structure --- .../errors/ReferenceNotFoundException.java | 21 ++++++++++++ .../RestResponseEntityExceptionHandler.java | 18 ++++++++--- .../partner/HsOfficePartnerController.java | 22 ++++++++++--- ...OfficePartnerControllerAcceptanceTest.java | 32 ++++++++++--------- 4 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/errors/ReferenceNotFoundException.java diff --git a/src/main/java/net/hostsharing/hsadminng/errors/ReferenceNotFoundException.java b/src/main/java/net/hostsharing/hsadminng/errors/ReferenceNotFoundException.java new file mode 100644 index 00000000..5703064c --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/errors/ReferenceNotFoundException.java @@ -0,0 +1,21 @@ +package net.hostsharing.hsadminng.errors; + +import net.hostsharing.hsadminng.hs.office.migration.HasUuid; + +import java.util.UUID; + +public class ReferenceNotFoundException extends RuntimeException { + + private final Class entityClass; + private final UUID uuid; + public ReferenceNotFoundException(final Class entityClass, final UUID uuid, final Throwable exc) { + super(exc); + this.entityClass = entityClass; + this.uuid = uuid; + } + + @Override + public String getMessage() { + return "Cannot resolve " + entityClass.getSimpleName() +" with uuid " + uuid; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java index 536cbf16..6c36dfb8 100644 --- a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java +++ b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java @@ -45,7 +45,7 @@ public class RestResponseEntityExceptionHandler protected ResponseEntity handleJpaExceptions( final RuntimeException exc, final WebRequest request) { final var message = line(NestedExceptionUtils.getMostSpecificCause(exc).getMessage(), 0); - return errorResponse(request, httpStatus(message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); + return errorResponse(request, httpStatus(exc, message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); } @ExceptionHandler(NoSuchElementException.class) @@ -55,6 +55,12 @@ public class RestResponseEntityExceptionHandler return errorResponse(request, HttpStatus.NOT_FOUND, message); } + @ExceptionHandler(ReferenceNotFoundException.class) + protected ResponseEntity handleReferenceNotFoundException( + final ReferenceNotFoundException exc, final WebRequest request) { + return errorResponse(request, HttpStatus.BAD_REQUEST, exc.getMessage()); + } + @ExceptionHandler({ JpaObjectRetrievalFailureException.class, EntityNotFoundException.class }) protected ResponseEntity handleJpaObjectRetrievalFailureException( final RuntimeException exc, final WebRequest request) { @@ -74,8 +80,9 @@ public class RestResponseEntityExceptionHandler @ExceptionHandler(Throwable.class) protected ResponseEntity handleOtherExceptions( final Throwable exc, final WebRequest request) { - final var message = firstMessageLine(NestedExceptionUtils.getMostSpecificCause(exc)); - return errorResponse(request, httpStatus(message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); + final var causingException = NestedExceptionUtils.getMostSpecificCause(exc); + final var message = firstMessageLine(causingException); + return errorResponse(request, httpStatus(causingException, message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); } @Override @@ -138,7 +145,10 @@ public class RestResponseEntityExceptionHandler } } - private Optional httpStatus(final String message) { + private Optional httpStatus(final Throwable causingException, final String message) { + if ( EntityNotFoundException.class.isInstance(causingException) ) { + return Optional.of(HttpStatus.BAD_REQUEST); + } if (message.startsWith("ERROR: [")) { for (HttpStatus status : HttpStatus.values()) { if (message.startsWith("ERROR: [" + status.value() + "]")) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java index 9a71a622..ebc1065a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java @@ -1,12 +1,14 @@ package net.hostsharing.hsadminng.hs.office.partner; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.errors.ReferenceNotFoundException; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerRoleInsertResource; +import net.hostsharing.hsadminng.hs.office.migration.HasUuid; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType; @@ -129,8 +131,8 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { final var entityToSave = new HsOfficePartnerEntity(); entityToSave.setPartnerNumber(body.getPartnerNumber()); entityToSave.setPartnerRole(persistPartnerRole(body.getPartnerRole())); - entityToSave.setContact(em.find(HsOfficeContactEntity.class, body.getContactUuid())); - entityToSave.setPerson(em.find(HsOfficePersonEntity.class, body.getPersonUuid())); + entityToSave.setContact(ref(HsOfficeContactEntity.class, body.getContactUuid())); + entityToSave.setPerson(ref(HsOfficePersonEntity.class, body.getPersonUuid())); entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class)); return entityToSave; } @@ -138,10 +140,20 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { private HsOfficeRelationshipEntity persistPartnerRole(final HsOfficePartnerRoleInsertResource resource) { final var entity = new HsOfficeRelationshipEntity(); entity.setRelType(HsOfficeRelationshipType.PARTNER); - entity.setRelAnchor(em.find(HsOfficePersonEntity.class, resource.getRelAnchorUuid())); - entity.setRelHolder(em.find(HsOfficePersonEntity.class, resource.getRelHolderUuid())); - entity.setContact(em.find(HsOfficeContactEntity.class, resource.getContactUuid())); + entity.setRelAnchor(ref(HsOfficePersonEntity.class, resource.getRelAnchorUuid())); + entity.setRelHolder(ref(HsOfficePersonEntity.class, resource.getRelHolderUuid())); + entity.setContact(ref(HsOfficeContactEntity.class, resource.getContactUuid())); em.persist(entity); return entity; } + + private E ref(final Class entityClass, final UUID uuid) { + try { + final var e = em.getReference(entityClass, uuid); + em.contains(e); + return e; + } catch (final Throwable exc) { + throw new ReferenceNotFoundException(entityClass, uuid, exc); + } + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java index 221c502f..c16d6f39 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java @@ -4,7 +4,9 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; +import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType; @@ -33,7 +35,8 @@ import static org.hamcrest.Matchers.*; ) class HsOfficePartnerControllerAcceptanceTest { - private static final UUID GIVEN_NON_EXISTING_PERSON_UUID = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"); +// private static final UUID GIVEN_NON_EXISTING_UUID = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"); + private static final UUID GIVEN_NON_EXISTING_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000"); @LocalServerPort private Integer port; @@ -145,16 +148,15 @@ class HsOfficePartnerControllerAcceptanceTest { context.define("superuser-alex@hostsharing.net"); final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0); final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0); - final var givenContactUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"); final var location = RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") .contentType(ContentType.JSON) .body(""" - { - "partnerNumber": "12345", - "partnerRole": { + { + "partnerNumber": "12345", + "partnerRole": { "relAnchorUuid": "%s", "relHolderUuid": "%s", "contactUuid": "%s" @@ -164,17 +166,17 @@ class HsOfficePartnerControllerAcceptanceTest { "details": {} } """.formatted( - givenMandantPerson, - givenPerson.getUuid(), - givenContactUuid, - givenPerson.getUuid(), - givenContactUuid)) + givenMandantPerson.getUuid(), + givenPerson.getUuid(), + GIVEN_NON_EXISTING_UUID, + givenPerson.getUuid(), + GIVEN_NON_EXISTING_UUID)) .port(port) .when() .post("http://localhost/api/hs/office/partners") .then().log().all().assertThat() .statusCode(400) - .body("message", is("Unable to find Contact with uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6")); + .body("message", is("Unable to find " + HsOfficeContactEntity.class.getName() + " with id " + GIVEN_NON_EXISTING_UUID)); // @formatter:on } @@ -195,7 +197,7 @@ class HsOfficePartnerControllerAcceptanceTest { "partnerRole": { "relAnchorUuid": "%s", "relHolderUuid": "%s", - "contact": "%s" + "contactUuid": "%s" }, "personUuid": "%s", "contactUuid": "%s", @@ -203,16 +205,16 @@ class HsOfficePartnerControllerAcceptanceTest { } """.formatted( mandantPerson.getUuid(), - GIVEN_NON_EXISTING_PERSON_UUID, + GIVEN_NON_EXISTING_UUID, givenContact.getUuid(), - GIVEN_NON_EXISTING_PERSON_UUID, + GIVEN_NON_EXISTING_UUID, givenContact.getUuid())) .port(port) .when() .post("http://localhost/api/hs/office/partners") .then().log().all().assertThat() .statusCode(400) - .body("message", is("Unable to find Person with uuid " + GIVEN_NON_EXISTING_PERSON_UUID)); + .body("message", is("Unable to find " + HsOfficePersonEntity.class.getName() + " with id " + GIVEN_NON_EXISTING_UUID)); // @formatter:on } }