From b65c4e7f0300c49a229352fe88f334f34d983eff Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 4 Sep 2024 15:08:31 +0530 Subject: [PATCH] avniproject/avni-webapp#1314 - maintain bundle error message separately. ReactAdminUtil to use only user message. --- .../avni/server/builder/BuilderException.java | 20 ++++++++++++++ .../server/builder/FormElementBuilder.java | 2 +- .../builder/FormElementGroupBuilder.java | 2 +- .../avni/server/builder/LocationBuilder.java | 2 +- .../batch/csv/writer/BulkLocationCreator.java | 3 +-- .../batch/zip/BundleZipFileImporter.java | 5 ++-- .../avni/server/service/CatchmentService.java | 4 +-- .../avni/server/service/ConceptService.java | 2 +- .../avni/server/service/LocationService.java | 13 ++++----- .../org/avni/server/util/ReactAdminUtil.java | 7 ++++- .../avni/server/web/LocationController.java | 2 +- .../server/builder/BuilderExceptionTest.java | 27 +++++++++++++++++++ 12 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 avni-server-api/src/test/java/org/avni/server/builder/BuilderExceptionTest.java diff --git a/avni-server-api/src/main/java/org/avni/server/builder/BuilderException.java b/avni-server-api/src/main/java/org/avni/server/builder/BuilderException.java index 885c3f4cc..98337194d 100644 --- a/avni-server-api/src/main/java/org/avni/server/builder/BuilderException.java +++ b/avni-server-api/src/main/java/org/avni/server/builder/BuilderException.java @@ -1,7 +1,27 @@ package org.avni.server.builder; public class BuilderException extends RuntimeException { + private final String bundleSpecificMessage; + public BuilderException(String message) { super(message); + bundleSpecificMessage = null; + } + + public BuilderException(String message, String bundleMessage) { + super(message); + this.bundleSpecificMessage = bundleMessage; + } + + public String getUserMessage() { + return super.getMessage(); + } + + @Override + public String getMessage() { + if (bundleSpecificMessage == null) { + return super.getMessage(); + } + return String.format("%s (%s)", super.getMessage(), bundleSpecificMessage); } } diff --git a/avni-server-api/src/main/java/org/avni/server/builder/FormElementBuilder.java b/avni-server-api/src/main/java/org/avni/server/builder/FormElementBuilder.java index 406fa54cf..bf29129d9 100644 --- a/avni-server-api/src/main/java/org/avni/server/builder/FormElementBuilder.java +++ b/avni-server-api/src/main/java/org/avni/server/builder/FormElementBuilder.java @@ -20,7 +20,7 @@ public FormElementBuilder(FormElementGroup formElementGroup, FormElement existin } public FormElementBuilder withName(String name) { - if(StringUtils.hasLength(name) && name.length() > 255) { + if (StringUtils.hasLength(name) && name.length() > 255) { throw new BuilderException(format("FormElement name \"%s\" exceeds allowed length of 255 characters", name)); } this.set("Name", name, String.class); diff --git a/avni-server-api/src/main/java/org/avni/server/builder/FormElementGroupBuilder.java b/avni-server-api/src/main/java/org/avni/server/builder/FormElementGroupBuilder.java index 7d1eb917a..3ddd42c30 100644 --- a/avni-server-api/src/main/java/org/avni/server/builder/FormElementGroupBuilder.java +++ b/avni-server-api/src/main/java/org/avni/server/builder/FormElementGroupBuilder.java @@ -34,7 +34,7 @@ public FormElementGroupBuilder(Form form, FormElementGroup existingFormElementGr } public FormElementGroupBuilder withName(String name) { - if(StringUtils.hasLength(name) && name.length() > 255) { + if (StringUtils.hasLength(name) && name.length() > 255) { throw new BuilderException(format("FormElementGroup name \"%s\" exceeds allowed length of 255 characters", name)); } this.set("Name", name, String.class); diff --git a/avni-server-api/src/main/java/org/avni/server/builder/LocationBuilder.java b/avni-server-api/src/main/java/org/avni/server/builder/LocationBuilder.java index 2ad7cfd19..5f856d3ea 100644 --- a/avni-server-api/src/main/java/org/avni/server/builder/LocationBuilder.java +++ b/avni-server-api/src/main/java/org/avni/server/builder/LocationBuilder.java @@ -21,7 +21,7 @@ public LocationBuilder(AddressLevel existingEntity, AddressLevelType type) { locationRepository = ApplicationContextProvider.getContext().getBean(LocationRepository.class); } - public LocationBuilder copy(LocationContract locationRequest) throws BuilderException { + public LocationBuilder copy(LocationContract locationRequest) { get().setUuid(locationRequest.getUuid() == null ? UUID.randomUUID().toString() : locationRequest.getUuid()); get().setTitle(locationRequest.getName()); get().setType(type); diff --git a/avni-server-api/src/main/java/org/avni/server/importer/batch/csv/writer/BulkLocationCreator.java b/avni-server-api/src/main/java/org/avni/server/importer/batch/csv/writer/BulkLocationCreator.java index e505e241f..838c6230e 100644 --- a/avni-server-api/src/main/java/org/avni/server/importer/batch/csv/writer/BulkLocationCreator.java +++ b/avni-server-api/src/main/java/org/avni/server/importer/batch/csv/writer/BulkLocationCreator.java @@ -2,7 +2,6 @@ import com.google.common.collect.Sets; import org.avni.server.application.FormElement; -import org.avni.server.builder.BuilderException; import org.avni.server.dao.AddressLevelTypeRepository; import org.avni.server.dao.LocationRepository; import org.avni.server.domain.AddressLevel; @@ -104,7 +103,7 @@ private void checkIfHeaderRowHasUnknownHeaders(List additionalHeaders, L } } - private AddressLevel createAddressLevel(Row row, AddressLevel parent, String header, List locationTypeNames) throws BuilderException { + private AddressLevel createAddressLevel(Row row, AddressLevel parent, String header, List locationTypeNames) { AddressLevel location; location = locationRepository.findChildLocation(parent, row.get(header)); if (location == null) { diff --git a/avni-server-api/src/main/java/org/avni/server/importer/batch/zip/BundleZipFileImporter.java b/avni-server-api/src/main/java/org/avni/server/importer/batch/zip/BundleZipFileImporter.java index 42772c6e2..81473b89b 100644 --- a/avni-server-api/src/main/java/org/avni/server/importer/batch/zip/BundleZipFileImporter.java +++ b/avni-server-api/src/main/java/org/avni/server/importer/batch/zip/BundleZipFileImporter.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.avni.messaging.contract.MessageRuleContract; import org.avni.messaging.service.MessagingService; -import org.avni.server.builder.BuilderException; import org.avni.server.builder.FormBuilderException; import org.avni.server.dao.CardRepository; import org.avni.server.dao.SubjectTypeRepository; @@ -249,7 +248,7 @@ private void deployFolder(BundleFolder bundleFolder, List } } - private void deployFile(String fileName, String fileData, List bundleFiles) throws IOException, FormBuilderException, BuilderException, ValidationException { + private void deployFile(String fileName, String fileData, List bundleFiles) throws IOException { logger.info("processing file {}", fileName); Organisation organisation = UserContextHolder.getUserContext().getOrganisation(); switch (fileName) { @@ -376,7 +375,7 @@ private void deployFile(String fileName, String fileData, List fileData, List bundleFiles) throws IOException, FormBuilderException, BuilderException { + private void deployFile(BundleFolder bundleFolder, Map.Entry fileData, List bundleFiles) throws IOException, FormBuilderException { logger.info("processing folder {} file {}", bundleFolder.getModifiedFileName(), fileData.getKey()); Organisation organisation = UserContextHolder.getUserContext().getOrganisation(); switch (bundleFolder) { diff --git a/avni-server-api/src/main/java/org/avni/server/service/CatchmentService.java b/avni-server-api/src/main/java/org/avni/server/service/CatchmentService.java index 89fa44a71..8753c61a6 100644 --- a/avni-server-api/src/main/java/org/avni/server/service/CatchmentService.java +++ b/avni-server-api/src/main/java/org/avni/server/service/CatchmentService.java @@ -53,7 +53,7 @@ public Catchment createOrUpdate(String catchmentName, AddressLevel location) { return catchmentRepository.save(catchment); } - public List saveAllCatchments(CatchmentsContract catchmentsContract, Organisation organisation) throws BuilderException { + public List saveAllCatchments(CatchmentsContract catchmentsContract, Organisation organisation) { List catchments = new ArrayList<>(); for (CatchmentContract catchmentRequest : catchmentsContract.getCatchments()) { logger.info(String.format("Processing catchment request: %s", catchmentRequest.toString())); @@ -79,7 +79,7 @@ public List saveAllCatchments(CatchmentsContract catchmentsContract, return catchments; } - private void addAddressLevels(CatchmentContract catchmentRequest, Catchment catchment) throws BuilderException { + private void addAddressLevels(CatchmentContract catchmentRequest, Catchment catchment) { List locations = catchmentRequest.getLocations(); if(isNull(locations) || locations.isEmpty()) { logger.warn(String.format("Locations not defined in Catchment {uuid='%s',locations=undefined,...}", catchment.getUuid())); diff --git a/avni-server-api/src/main/java/org/avni/server/service/ConceptService.java b/avni-server-api/src/main/java/org/avni/server/service/ConceptService.java index 3fd28fdfb..2b93bf17c 100644 --- a/avni-server-api/src/main/java/org/avni/server/service/ConceptService.java +++ b/avni-server-api/src/main/java/org/avni/server/service/ConceptService.java @@ -178,7 +178,7 @@ private Concept saveOrUpdate(ConceptContract conceptRequest) throws AnswerConcep if (conceptExistsWithSameNameAndDifferentUUID(conceptRequest)) { throw new BadRequestError(String.format("Concept with name \'%s\' already exists", conceptRequest.getName())); } - logger.info(String.format("Creating concept: %s", conceptRequest.toString())); + logger.info(String.format("Creating concept: %s", conceptRequest)); addToMigrationIfRequired(conceptRequest); Concept concept = map(conceptRequest); diff --git a/avni-server-api/src/main/java/org/avni/server/service/LocationService.java b/avni-server-api/src/main/java/org/avni/server/service/LocationService.java index 1e31dd0ea..93b239ea0 100644 --- a/avni-server-api/src/main/java/org/avni/server/service/LocationService.java +++ b/avni-server-api/src/main/java/org/avni/server/service/LocationService.java @@ -54,7 +54,7 @@ public LocationService(LocationRepository locationRepository, AddressLevelTypeRe this.logger = LoggerFactory.getLogger(this.getClass()); } - public List saveAll(List locationContracts) throws BuilderException { + public List saveAll(List locationContracts) { List saved = new ArrayList<>(); for (LocationContract contract : locationContracts) { saved.add(save(contract)); @@ -62,7 +62,7 @@ public List saveAll(List locationContracts) thro return saved; } - public AddressLevel save(LocationContract locationContract) throws BuilderException { + public AddressLevel save(LocationContract locationContract) { logger.info(String.format("Processing location request: %s", locationContract.toString())); AddressLevelType type = getTypeByUuidOrName(locationContract); if (type == null) { @@ -98,7 +98,7 @@ private AddressLevelType createType(LocationContract locationContract) { return addressLevelType; } - private AddressLevel saveLocation(LocationContract contract, AddressLevelType type) throws BuilderException { + private AddressLevel saveLocation(LocationContract contract, AddressLevelType type) { LocationBuilder locationBuilder = new LocationBuilder(locationRepository.findByUuid(contract.getUuid()), type); locationBuilder.copy(contract); AddressLevel location = locationBuilder.build(); @@ -106,20 +106,21 @@ private AddressLevel saveLocation(LocationContract contract, AddressLevelType ty // Validate location title/name is unique only if new AddressLevel if (location.getId() == null && !titleIsValid(location, contract.getName().trim(), type)) - throw new BuilderException(String.format("Location with same name '%s' and type '%s' exists at this level. (%s)", contract.getName(), type.getName(), contract)); + throw new BuilderException(String.format("Location with same name '%s' and type '%s' exists at this level.", contract.getName(), type.getName()), + contract.toString()); try { locationRepository.save(location); } catch (Exception e) { logger.error(e.getMessage(), e); - throw new BuilderException(String.format("Unable to create Location{name='%s',level='%s',orgUUID='%s',..}: '%s' (%s)", contract.getName(), contract.getLevel(), contract.getOrganisationUUID(), e.getMessage(), contract)); + throw new BuilderException(String.format("Unable to create Location{name='%s',level='%s',orgUUID='%s',..}: '%s'", contract.getName(), contract.getLevel(), contract.getOrganisationUUID(), e.getMessage()), contract.toString()); } try { location.calculateLineage(); locationRepository.save(location); } catch (Exception e) { logger.error(e.getMessage(), e); - throw new BuilderException(String.format("Unable to update lineage for location with Id %s - %s. (%s)", location.getId(), e.getMessage(), contract)); + throw new BuilderException(String.format("Unable to update lineage for location with Id %s - %s.", location.getId(), e.getMessage()), contract.toString()); } return location; } diff --git a/avni-server-api/src/main/java/org/avni/server/util/ReactAdminUtil.java b/avni-server-api/src/main/java/org/avni/server/util/ReactAdminUtil.java index 333d6c4c6..9cd568eb9 100644 --- a/avni-server-api/src/main/java/org/avni/server/util/ReactAdminUtil.java +++ b/avni-server-api/src/main/java/org/avni/server/util/ReactAdminUtil.java @@ -1,9 +1,15 @@ package org.avni.server.util; +import org.avni.server.builder.BuilderException; + import java.util.HashMap; import java.util.Map; public class ReactAdminUtil { + public static Map generateJsonError(BuilderException builderException) { + return generateJsonError(builderException.getUserMessage()); + } + public static Map generateJsonError(String errorMsg) { Map errorMap = new HashMap<>(); errorMap.put("message", errorMsg); @@ -13,5 +19,4 @@ public static Map generateJsonError(String errorMsg) { public static String getVoidedName(String name, Long id) { return String.format("%s (voided~%d)", name, id); } - } diff --git a/avni-server-api/src/main/java/org/avni/server/web/LocationController.java b/avni-server-api/src/main/java/org/avni/server/web/LocationController.java index d3f3b4253..20a1dd821 100644 --- a/avni-server-api/src/main/java/org/avni/server/web/LocationController.java +++ b/avni-server-api/src/main/java/org/avni/server/web/LocationController.java @@ -73,7 +73,7 @@ public ResponseEntity save(@RequestBody List locationContra } } catch (BuilderException e) { logger.error(e.getMessage(), e); - return ResponseEntity.badRequest().body(ReactAdminUtil.generateJsonError(e.getMessage())); + return ResponseEntity.badRequest().body(ReactAdminUtil.generateJsonError(e)); } return ResponseEntity.ok(null); } diff --git a/avni-server-api/src/test/java/org/avni/server/builder/BuilderExceptionTest.java b/avni-server-api/src/test/java/org/avni/server/builder/BuilderExceptionTest.java new file mode 100644 index 000000000..51c43ca31 --- /dev/null +++ b/avni-server-api/src/test/java/org/avni/server/builder/BuilderExceptionTest.java @@ -0,0 +1,27 @@ +package org.avni.server.builder; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class BuilderExceptionTest { + @Test + public void hasBundleSpecificMessage() { + try { + throw new BuilderException("userMessage", "bundleSpecificMessage"); + } catch (BuilderException be) { + assertEquals("userMessage (bundleSpecificMessage)", be.getMessage()); + assertEquals("userMessage", be.getUserMessage()); + } + } + + @Test + public void doesntHaveBundleSpecificMessage() { + try { + throw new BuilderException("userMessage"); + } catch (BuilderException be) { + assertEquals("userMessage", be.getMessage()); + assertEquals("userMessage", be.getUserMessage()); + } + } +}