From 9595bd98febc70592cbab1335bb3c1e3f204b58b Mon Sep 17 00:00:00 2001 From: Christian Gendreau Date: Fri, 7 Feb 2025 11:32:45 -0500 Subject: [PATCH 1/2] 35687 Change DinaRepositoryV2 create to use JsonApiDocument Changed create method, added customizer + improved checks in set relationships method --- .../dina/repository/DinaRepositoryV2.java | 36 ++++++++++++++----- .../aafc/dina/jsonapi/DinaRepositoryV2IT.java | 13 ++++--- .../dina/repository/DinaRepositoryV2IT.java | 6 +++- .../aafc/dina/jsonapi/JsonApiDocuments.java | 33 +++++++++++++++-- 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java b/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java index f5becea7e..a8d5bd990 100644 --- a/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java +++ b/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java @@ -46,6 +46,7 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.function.Consumer; import javax.persistence.criteria.Predicate; import javax.servlet.http.HttpServletRequest; import lombok.NonNull; @@ -507,15 +508,24 @@ private static int toSafePageLimit(Integer pageLimit) { /** * Create a new resource. - * Relationships are not supported at the moment. - * @param dto + * @param docToCreate + * @param dtoCustomizer used to customize the dto before being transformed to entity. + * Example, setting the authenticated user as createdBy. Can be null. * @return the uuid assigned or used */ - public UUID create(D dto) { + public UUID create(JsonApiDocument docToCreate, Consumer dtoCustomizer) { + + D dto = objMapper.convertValue(docToCreate.getAttributes(), resourceClass); + if(dtoCustomizer != null) { + dtoCustomizer.accept(dto); + } + E entity = dinaMapper.toEntity(dto, registry.getAttributesPerClass().get(resourceClass), null); + updateRelationships(entity, docToCreate.getRelationships()); + authorizationService.authorizeCreate(entity); E created = dinaService.create(entity); return created.getUuid(); @@ -583,15 +593,25 @@ private void updateRelationships(E entity, Map relationshipsReferences = new ArrayList<>(); for (Object el : relObject.getDataAsCollection()) { var resourceIdentifier = toResourceIdentifier(el); - relationshipsReferences.add( - dinaService.getReferenceByNaturalId(relation.getEntityType(), - resourceIdentifier.getId())); + if (resourceIdentifier != null) { + relationshipsReferences.add( + dinaService.getReferenceByNaturalId(relation.getEntityType(), + resourceIdentifier.getId())); + } else { + log.warn("Can't convert to ResourceIdentifier list element, ignoring"); + return; + } } relationshipsReference = relationshipsReferences; } else { // to-one var resourceIdentifier = toResourceIdentifier(relObject.getData()); - relationshipsReference = dinaService.getReferenceByNaturalId(relation.getEntityType(), - resourceIdentifier.getId()); + if (resourceIdentifier != null) { + relationshipsReference = dinaService.getReferenceByNaturalId(relation.getEntityType(), + resourceIdentifier.getId()); + } else { + log.warn("Can't convert to ResourceIdentifier, ignoring"); + return; + } } } else { // remove relationship diff --git a/dina-base-api/src/test/java/ca/gc/aafc/dina/jsonapi/DinaRepositoryV2IT.java b/dina-base-api/src/test/java/ca/gc/aafc/dina/jsonapi/DinaRepositoryV2IT.java index 343681857..938d86d13 100644 --- a/dina-base-api/src/test/java/ca/gc/aafc/dina/jsonapi/DinaRepositoryV2IT.java +++ b/dina-base-api/src/test/java/ca/gc/aafc/dina/jsonapi/DinaRepositoryV2IT.java @@ -8,7 +8,6 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.RepresentationModel; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; @@ -50,7 +49,7 @@ properties = {"dev-user.enabled: true", "keycloak.enabled: false"}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(initializers = { PostgresTestContainerInitializer.class }) -@Import({DinaRepositoryV2IT.TestDynaBeanRepo.class, DinaRepositoryV2IT.RepoV2TestConfig.class}) +@Import({DinaRepositoryV2IT.TestDinaRepositoryV2.class, DinaRepositoryV2IT.RepoV2TestConfig.class}) public class DinaRepositoryV2IT extends BaseRestAssuredTest { private static final String PATH = "repo2"; @@ -120,7 +119,7 @@ public void onPatchToManyRelationship() { */ @RestController @RequestMapping(produces = JSON_API_VALUE) - static class TestDynaBeanRepo { + static class TestDinaRepositoryV2 { @Getter private Integer level; @@ -133,15 +132,15 @@ static class TestDynaBeanRepo { @PostMapping(PATH + "/" + TaskDTO.RESOURCE_TYPE) @Transactional - public ResponseEntity> handlePostTask(@RequestBody EntityModel taskDTO) { - taskRepo.create(taskDTO.getContent()); + public ResponseEntity> handlePostTask(@RequestBody JsonApiDocument doc) { + taskRepo.create(doc, (dto) -> dto.setUuid(doc.getId())); return ResponseEntity.created(URI.create("/")).build(); } @PostMapping(PATH + "/" + ProjectDTO.RESOURCE_TYPE) @Transactional - public ResponseEntity> handlePostProject(@RequestBody EntityModel projectDTO) { - projectRepo.create(projectDTO.getContent()); + public ResponseEntity> handlePostProject(@RequestBody JsonApiDocument doc) { + projectRepo.create(doc, (dto) -> dto.setUuid(doc.getId())); return ResponseEntity.created(URI.create("/")).build(); } diff --git a/dina-base-api/src/test/java/ca/gc/aafc/dina/repository/DinaRepositoryV2IT.java b/dina-base-api/src/test/java/ca/gc/aafc/dina/repository/DinaRepositoryV2IT.java index d00ce41ca..9861c2e71 100644 --- a/dina-base-api/src/test/java/ca/gc/aafc/dina/repository/DinaRepositoryV2IT.java +++ b/dina-base-api/src/test/java/ca/gc/aafc/dina/repository/DinaRepositoryV2IT.java @@ -17,10 +17,12 @@ import ca.gc.aafc.dina.exception.ResourceNotFoundException; import ca.gc.aafc.dina.filter.QueryComponent; import ca.gc.aafc.dina.jsonapi.JsonApiDocument; +import ca.gc.aafc.dina.jsonapi.JsonApiDocuments; import ca.gc.aafc.dina.mapper.PersonMapper; import ca.gc.aafc.dina.security.auth.AllowAllAuthorizationService; import ca.gc.aafc.dina.service.DinaService; import ca.gc.aafc.dina.testsupport.PostgresTestContainerInitializer; +import ca.gc.aafc.dina.testsupport.jsonapi.JsonAPITestHelper; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -128,7 +130,9 @@ public void onCreateUpdateDelete_noException() throws ResourceNotFoundException .name("Bob") .build(); - UUID assignedId = repositoryV2.create(personDto); + JsonApiDocument doc = JsonApiDocuments.createJsonApiDocument(null, PersonDTO.TYPE_NAME, + JsonAPITestHelper.toAttributeMap(personDto)); + UUID assignedId = repositoryV2.create(doc, null); Map attributes = new HashMap<>(); diff --git a/dina-json/src/main/java/ca/gc/aafc/dina/jsonapi/JsonApiDocuments.java b/dina-json/src/main/java/ca/gc/aafc/dina/jsonapi/JsonApiDocuments.java index c7af4fba4..df7af93e5 100644 --- a/dina-json/src/main/java/ca/gc/aafc/dina/jsonapi/JsonApiDocuments.java +++ b/dina-json/src/main/java/ca/gc/aafc/dina/jsonapi/JsonApiDocuments.java @@ -1,6 +1,7 @@ package ca.gc.aafc.dina.jsonapi; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -23,7 +24,6 @@ private JsonApiDocuments() { */ public static JsonApiDocument createJsonApiDocument(UUID uuid, String type, Map attributes) { - Objects.requireNonNull(uuid); Objects.requireNonNull(type); return JsonApiDocument.builder() @@ -36,6 +36,34 @@ public static JsonApiDocument createJsonApiDocument(UUID uuid, String type, ).build(); } + /** + * Creates a {@link JsonApiDocument} with to-one relationships for provided parameters. + * @param uuid + * @param type + * @param attributes + * @param relationships + * @return + */ + public static JsonApiDocument createJsonApiDocumentWithRelToOne(UUID uuid, String type, + Map attributes, + Map relationships) { + return createJsonApiDocument(uuid, type, attributes, relationships); + } + + /** + * Creates a {@link JsonApiDocument} with to-many relationships for provided parameters. + * @param uuid + * @param type + * @param attributes + * @param relationships + * @return + */ + public static JsonApiDocument createJsonApiDocumentWithRelToMany(UUID uuid, String type, + Map attributes, + Map> relationships) { + return createJsonApiDocument(uuid, type, attributes, relationships); + } + /** * Creates a {@link JsonApiDocument} with relationships for provided parameters * @param uuid @@ -46,8 +74,7 @@ public static JsonApiDocument createJsonApiDocument(UUID uuid, String type, */ public static JsonApiDocument createJsonApiDocument(UUID uuid, String type, Map attributes, - Map relationships) { - Objects.requireNonNull(uuid); + Map relationships) { Objects.requireNonNull(type); Objects.requireNonNull(relationships); From cadea0b528fcedb9392e8edfae4f6e4a2b9ad624 Mon Sep 17 00:00:00 2001 From: Christian Gendreau Date: Fri, 7 Feb 2025 14:49:11 -0500 Subject: [PATCH 2/2] Fixed Checkstyle issue --- .../main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java b/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java index a8d5bd990..79a21c622 100644 --- a/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java +++ b/dina-base-api/src/main/java/ca/gc/aafc/dina/repository/DinaRepositoryV2.java @@ -516,7 +516,7 @@ private static int toSafePageLimit(Integer pageLimit) { public UUID create(JsonApiDocument docToCreate, Consumer dtoCustomizer) { D dto = objMapper.convertValue(docToCreate.getAttributes(), resourceClass); - if(dtoCustomizer != null) { + if (dtoCustomizer != null) { dtoCustomizer.accept(dto); }