From 52cb3f0ffb9923b9cfd568340694cab655daeb5e Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Thu, 16 Jan 2025 16:13:16 +1100 Subject: [PATCH 1/7] Exception handling for fail safe --- .../ExtractingPathVersionsException.java | 9 ++++ .../InvalidVersionFormatException.java | 9 ++++ .../service/ArdcVocabServiceImpl.java | 51 ++++++++++++------- .../esindexer/service/VocabServiceImpl.java | 12 +++-- .../esindexer/utils/VocabsIndexUtils.java | 11 ++-- 5 files changed, 67 insertions(+), 25 deletions(-) create mode 100644 ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/ExtractingPathVersionsException.java create mode 100644 ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/InvalidVersionFormatException.java diff --git a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/ExtractingPathVersionsException.java b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/ExtractingPathVersionsException.java new file mode 100644 index 00000000..50d67374 --- /dev/null +++ b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/ExtractingPathVersionsException.java @@ -0,0 +1,9 @@ +package au.org.aodn.ardcvocabs.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class ExtractingPathVersionsException extends RuntimeException { + public ExtractingPathVersionsException(String message) { super(message); }; +} diff --git a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/InvalidVersionFormatException.java b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/InvalidVersionFormatException.java new file mode 100644 index 00000000..6d49abd0 --- /dev/null +++ b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/exception/InvalidVersionFormatException.java @@ -0,0 +1,9 @@ +package au.org.aodn.ardcvocabs.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class InvalidVersionFormatException extends RuntimeException { + public InvalidVersionFormatException(String message) { super(message); }; +} diff --git a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java index ee562f8a..f6fcae26 100644 --- a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java +++ b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java @@ -1,5 +1,7 @@ package au.org.aodn.ardcvocabs.service; +import au.org.aodn.ardcvocabs.exception.ExtractingPathVersionsException; +import au.org.aodn.ardcvocabs.exception.InvalidVersionFormatException; import au.org.aodn.ardcvocabs.model.ArdcCurrentPaths; import au.org.aodn.ardcvocabs.model.PathName; import au.org.aodn.ardcvocabs.model.VocabApiPaths; @@ -36,36 +38,49 @@ public class ArdcVocabServiceImpl implements ArdcVocabService { public Map> getResolvedPathCollection() { Map> resolvedPathCollection = new HashMap<>(); + for (ArdcCurrentPaths currentPath : ArdcCurrentPaths.values()) { try { + // Fetch current contents ObjectNode categoryCurrentContent = fetchCurrentContents(currentPath.getCategoryCurrent()); ObjectNode vocabCurrentContent = fetchCurrentContents(currentPath.getVocabCurrent()); + validateContentNotNull(currentPath, categoryCurrentContent, vocabCurrentContent); - if (categoryCurrentContent != null && vocabCurrentContent != null) { - // Extract versions - String categoryVersion = extractVersionFromCurrentContent(categoryCurrentContent); - String vocabVersion = extractVersionFromCurrentContent(vocabCurrentContent); + // Extract versions + String categoryVersion = extractVersionFromCurrentContent(categoryCurrentContent); + String vocabVersion = extractVersionFromCurrentContent(vocabCurrentContent); + validateVersionsNotNull(currentPath, categoryVersion, vocabVersion); - if (categoryVersion != null && vocabVersion != null) { - log.info("Fetched ARDC category version for {}: {}", currentPath.name(), categoryVersion); - log.info("Fetched ARDC vocab version for {}: {}", currentPath.name(), vocabVersion); + log.info("Fetched ARDC category version for {}: {}", currentPath.name(), categoryVersion); + log.info("Fetched ARDC vocab version for {}: {}", currentPath.name(), vocabVersion); + + // Build and store resolved paths + Map resolvedPaths = buildResolvedPaths(currentPath, categoryVersion, vocabVersion); + resolvedPathCollection.put(currentPath.name(), resolvedPaths); - // Build and store resolved paths - Map resolvedPaths = buildResolvedPaths(currentPath, categoryVersion, vocabVersion); - resolvedPathCollection.put(currentPath.name(), resolvedPaths); - } else { - log.error("Failed to extract versions for {}", currentPath.name()); - } - } else { - log.error("Failed to fetch HTML content for {}", currentPath.name()); - } } catch (Exception e) { log.error("Error initialising versions for {}: {}", currentPath.name(), e.getMessage(), e); + throw new ExtractingPathVersionsException(String.format("Error initialising versions for %s: %s", currentPath.name(), e.getMessage())); } } + return resolvedPathCollection; } + private void validateContentNotNull(ArdcCurrentPaths currentPath, ObjectNode categoryContent, ObjectNode vocabContent) { + if (categoryContent == null || vocabContent == null) { + log.error("Failed to fetch HTML content for {}", currentPath.name()); + throw new ExtractingPathVersionsException(String.format("Failed to fetch HTML content for %s", currentPath.name())); + } + } + + private void validateVersionsNotNull(ArdcCurrentPaths currentPath, String categoryVersion, String vocabVersion) { + if (categoryVersion == null || vocabVersion == null) { + log.error("Version extraction returned null for {}", currentPath.name()); + throw new ExtractingPathVersionsException(String.format("Version extraction returned null for %s", currentPath.name())); + } + } + private ObjectNode fetchCurrentContents(String url) { try { return retryTemplate.execute(context -> restTemplate.getForObject(url, ObjectNode.class)); @@ -90,7 +105,7 @@ protected Map buildResolvedPaths(ArdcCurrentPaths currentPaths return resolvedPaths; } - protected String extractVersionFromCurrentContent(ObjectNode currentContent) { + protected String extractVersionFromCurrentContent(ObjectNode currentContent) throws InvalidPropertiesFormatException { if (currentContent != null && !currentContent.isEmpty()) { JsonNode node = currentContent.get("result"); if (!about.apply(node).isEmpty()) { @@ -103,9 +118,9 @@ protected String extractVersionFromCurrentContent(ObjectNode currentContent) { return version; } else { log.warn("Version does not match the required format: {}", about.apply(node)); + throw new InvalidVersionFormatException(String.format("Version does not match the required format: %s", about.apply(node))); } } - } else { log.warn("Current content is empty or null."); } diff --git a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java index 5c80fdab..0dd13add 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java @@ -408,10 +408,14 @@ public void populateVocabsDataAsync(Map> resolvedP } } - // Call indexAllVocabs only after all tasks are completed - log.info("Indexing fetched vocabs to {}", vocabsIndexName); - indexAllVocabs(allResults.get(0), allResults.get(1), allResults.get(2)); - + // Validate allResults to ensure none of the lists are empty + if (allResults.stream().anyMatch(List::isEmpty)) { + log.error("One or more vocab tasks returned empty results. Skipping indexing."); + } else { + // Call indexAllVocabs only after all tasks are completed and validated + log.info("Indexing fetched vocabs to {}", vocabsIndexName); + indexAllVocabs(allResults.get(0), allResults.get(1), allResults.get(2)); + } } catch (InterruptedException | IOException e) { Thread.currentThread().interrupt(); // Restore interrupt status log.error("Thread was interrupted while processing vocab tasks", e); diff --git a/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java b/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java index 3dcb15e6..395769a7 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java @@ -1,5 +1,6 @@ package au.org.aodn.esindexer.utils; +import au.org.aodn.ardcvocabs.exception.ExtractingPathVersionsException; import au.org.aodn.ardcvocabs.model.PathName; import au.org.aodn.ardcvocabs.service.ArdcVocabService; import au.org.aodn.esindexer.service.VocabService; @@ -45,9 +46,13 @@ public void setArdcVocabService(ArdcVocabService ardcVocabService) { public void init() throws IOException { // Check if the initialiseVocabsIndex flag is enabled if (initialiseVocabsIndex) { - log.info("Initialising {} asynchronously", vocabsIndexName); - storedResolvedPathCollection = ardcVocabService.getResolvedPathCollection(); - vocabService.populateVocabsDataAsync(storedResolvedPathCollection); + try { + log.info("Initialising {} asynchronously", vocabsIndexName); + storedResolvedPathCollection = ardcVocabService.getResolvedPathCollection(); + vocabService.populateVocabsDataAsync(storedResolvedPathCollection); + } catch (ExtractingPathVersionsException e) { + log.warn("Skip initialising vocabs with error: {}", e.getMessage()); + } } } From 8b6a0cd76f19d5898b44af4dcf4cc4333384de3c Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Thu, 16 Jan 2025 16:35:08 +1100 Subject: [PATCH 2/7] Add test --- .../esindexer/service/VocabServiceImpl.java | 4 ++- .../esindexer/service/VocabServiceIT.java | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java index 0dd13add..67a658ce 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java @@ -378,7 +378,9 @@ public void populateVocabsData(Map> resolvedPathCo List platformVocabs = ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get(VocabApiPaths.PLATFORM_VOCAB.name())); List organisationVocabs = ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get(VocabApiPaths.ORGANISATION_VOCAB.name())); - indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); + if (!parameterVocabs.isEmpty() && !platformVocabs.isEmpty() && !organisationVocabs.isEmpty()) { + indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); + } } public void populateVocabsDataAsync(Map> resolvedPathCollection) { diff --git a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java index 4ad8454c..24f35451 100644 --- a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java +++ b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java @@ -1,5 +1,6 @@ package au.org.aodn.esindexer.service; +import au.org.aodn.ardcvocabs.model.PathName; import au.org.aodn.ardcvocabs.model.VocabApiPaths; import au.org.aodn.ardcvocabs.model.VocabModel; import au.org.aodn.ardcvocabs.service.ArdcVocabService; @@ -11,6 +12,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.json.JSONException; import org.junit.jupiter.api.*; +import org.mockito.InjectMocks; +import org.mockito.Spy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; @@ -24,6 +27,7 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT @@ -33,8 +37,9 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class VocabServiceIT extends BaseTestClass { - @Autowired - VocabService vocabService; + @InjectMocks + @Spy + VocabServiceImpl vocabService; @Autowired ArdcVocabService ardcVocabService; @@ -115,6 +120,27 @@ void testProcessParameterVocabs() throws IOException, JSONException { ); } + @Test + void testSkipIndexingIfEmptyVocabs() throws IOException { + // Mock resolved path collection + Map> resolvedPathCollection = Map.of( + "PARAMETER_VOCAB", Map.of(), + "PLATFORM_VOCAB", Map.of(), + "ORGANISATION_VOCAB", Map.of() + ); + + // Mock service calls to return empty lists + when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PARAMETER_VOCAB"))).thenReturn(Collections.emptyList()); + when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PLATFORM_VOCAB"))).thenReturn(Collections.emptyList()); + when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("ORGANISATION_VOCAB"))).thenReturn(Collections.emptyList()); + + // Call the method + vocabService.populateVocabsData(resolvedPathCollection); + + // Verify that indexAllVocabs is not called + verify(vocabService, never()).indexAllVocabs(anyList(), anyList(), anyList()); + } + @Test void testProcessPlatformVocabs() throws IOException, JSONException { // read from ARDC From 4d9adcceab65a4ea57e864deaf4034127a46415b Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Thu, 16 Jan 2025 16:42:31 +1100 Subject: [PATCH 3/7] update mock instances --- .../esindexer/service/VocabServiceIT.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java index 24f35451..ed8b82aa 100644 --- a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java +++ b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java @@ -13,6 +13,7 @@ import org.json.JSONException; import org.junit.jupiter.api.*; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Spy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -39,7 +40,13 @@ public class VocabServiceIT extends BaseTestClass { @InjectMocks @Spy - VocabServiceImpl vocabService; + VocabServiceImpl mockVocabService; + + @Autowired + VocabService vocabService; + + @Mock + ArdcVocabService mockArdcVocabService; @Autowired ArdcVocabService ardcVocabService; @@ -130,15 +137,15 @@ void testSkipIndexingIfEmptyVocabs() throws IOException { ); // Mock service calls to return empty lists - when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PARAMETER_VOCAB"))).thenReturn(Collections.emptyList()); - when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PLATFORM_VOCAB"))).thenReturn(Collections.emptyList()); - when(ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("ORGANISATION_VOCAB"))).thenReturn(Collections.emptyList()); + when(mockArdcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PARAMETER_VOCAB"))).thenReturn(Collections.emptyList()); + when(mockArdcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("PLATFORM_VOCAB"))).thenReturn(Collections.emptyList()); + when(mockArdcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("ORGANISATION_VOCAB"))).thenReturn(Collections.emptyList()); // Call the method - vocabService.populateVocabsData(resolvedPathCollection); + mockVocabService.populateVocabsData(resolvedPathCollection); // Verify that indexAllVocabs is not called - verify(vocabService, never()).indexAllVocabs(anyList(), anyList(), anyList()); + verify(mockVocabService, never()).indexAllVocabs(anyList(), anyList(), anyList()); } @Test From ace347adf28ea03c4e476006b36bec4c84f57803 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Thu, 16 Jan 2025 17:01:06 +1100 Subject: [PATCH 4/7] prevent existing caches unintended cleared --- .../IgnoreIndexingVocabsException.java | 9 +++++++++ .../esindexer/service/VocabServiceImpl.java | 5 ++++- .../esindexer/utils/VocabsIndexUtils.java | 20 +++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 indexer/src/main/java/au/org/aodn/esindexer/exception/IgnoreIndexingVocabsException.java diff --git a/indexer/src/main/java/au/org/aodn/esindexer/exception/IgnoreIndexingVocabsException.java b/indexer/src/main/java/au/org/aodn/esindexer/exception/IgnoreIndexingVocabsException.java new file mode 100644 index 00000000..f0c7841f --- /dev/null +++ b/indexer/src/main/java/au/org/aodn/esindexer/exception/IgnoreIndexingVocabsException.java @@ -0,0 +1,9 @@ +package au.org.aodn.esindexer.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class IgnoreIndexingVocabsException extends RuntimeException { + public IgnoreIndexingVocabsException(String message) { super(message); } +} diff --git a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java index 67a658ce..948d7158 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java @@ -7,6 +7,7 @@ import au.org.aodn.ardcvocabs.service.ArdcVocabService; import au.org.aodn.esindexer.configuration.AppConstants; import au.org.aodn.esindexer.exception.DocumentNotFoundException; +import au.org.aodn.esindexer.exception.IgnoreIndexingVocabsException; import au.org.aodn.stac.model.ConceptModel; import au.org.aodn.stac.model.ContactsModel; import au.org.aodn.stac.model.ThemesModel; @@ -380,6 +381,8 @@ public void populateVocabsData(Map> resolvedPathCo if (!parameterVocabs.isEmpty() && !platformVocabs.isEmpty() && !organisationVocabs.isEmpty()) { indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); + } else { + throw new IgnoreIndexingVocabsException("One or more vocab tasks returned empty results. Skipping indexing."); } } @@ -412,7 +415,7 @@ public void populateVocabsDataAsync(Map> resolvedP // Validate allResults to ensure none of the lists are empty if (allResults.stream().anyMatch(List::isEmpty)) { - log.error("One or more vocab tasks returned empty results. Skipping indexing."); + throw new IgnoreIndexingVocabsException("One or more vocab tasks returned empty results. Skipping indexing."); } else { // Call indexAllVocabs only after all tasks are completed and validated log.info("Indexing fetched vocabs to {}", vocabsIndexName); diff --git a/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java b/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java index 395769a7..c5dfd0ee 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/utils/VocabsIndexUtils.java @@ -3,6 +3,7 @@ import au.org.aodn.ardcvocabs.exception.ExtractingPathVersionsException; import au.org.aodn.ardcvocabs.model.PathName; import au.org.aodn.ardcvocabs.service.ArdcVocabService; +import au.org.aodn.esindexer.exception.IgnoreIndexingVocabsException; import au.org.aodn.esindexer.service.VocabService; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; @@ -50,7 +51,7 @@ public void init() throws IOException { log.info("Initialising {} asynchronously", vocabsIndexName); storedResolvedPathCollection = ardcVocabService.getResolvedPathCollection(); vocabService.populateVocabsDataAsync(storedResolvedPathCollection); - } catch (ExtractingPathVersionsException e) { + } catch (ExtractingPathVersionsException | IgnoreIndexingVocabsException e) { log.warn("Skip initialising vocabs with error: {}", e.getMessage()); } } @@ -64,13 +65,16 @@ public void scheduledRefreshVocabsData() { if (!latestResolvedPathCollection.equals(storedResolvedPathCollection)) { log.info("Detected changes in the resolved path collection, updating vocabularies..."); - vocabService.populateVocabsData(latestResolvedPathCollection); - refreshCaches(); - - // update the head if there are new versions - synchronized (this) { - storedResolvedPathCollection = latestResolvedPathCollection; - log.info("Updated storedResolvedPathCollection with the latest data."); + try { + vocabService.populateVocabsData(latestResolvedPathCollection); + refreshCaches(); + // update the head if there are new versions + synchronized (this) { + storedResolvedPathCollection = latestResolvedPathCollection; + log.info("Updated storedResolvedPathCollection with the latest data."); + } + } catch (IgnoreIndexingVocabsException e) { + log.warn("Skip refreshing vocabs: {}", e.getMessage()); } } else { log.info("No changes detected in the resolved path collection. Skip updating caches"); From 06c7aa723b11772482c7e2a9757b43003b1381f6 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Thu, 16 Jan 2025 17:05:41 +1100 Subject: [PATCH 5/7] Fix exception message --- .../java/au/org/aodn/esindexer/service/VocabServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java index 948d7158..92a289a1 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java @@ -382,7 +382,7 @@ public void populateVocabsData(Map> resolvedPathCo if (!parameterVocabs.isEmpty() && !platformVocabs.isEmpty() && !organisationVocabs.isEmpty()) { indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); } else { - throw new IgnoreIndexingVocabsException("One or more vocab tasks returned empty results. Skipping indexing."); + throw new IgnoreIndexingVocabsException("One or more vocab lists are empty. Skipping indexing."); } } From a473e963b2b76da22bfd2d38d80b1071a65e4e04 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Fri, 17 Jan 2025 14:03:38 +1100 Subject: [PATCH 6/7] remove unnecessary else clause --- .../aodn/esindexer/service/VocabServiceImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java index 92a289a1..09a89513 100644 --- a/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java +++ b/indexer/src/main/java/au/org/aodn/esindexer/service/VocabServiceImpl.java @@ -379,11 +379,11 @@ public void populateVocabsData(Map> resolvedPathCo List platformVocabs = ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get(VocabApiPaths.PLATFORM_VOCAB.name())); List organisationVocabs = ardcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get(VocabApiPaths.ORGANISATION_VOCAB.name())); - if (!parameterVocabs.isEmpty() && !platformVocabs.isEmpty() && !organisationVocabs.isEmpty()) { - indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); - } else { + if (parameterVocabs.isEmpty() || platformVocabs.isEmpty() || organisationVocabs.isEmpty()) { throw new IgnoreIndexingVocabsException("One or more vocab lists are empty. Skipping indexing."); } + + indexAllVocabs(parameterVocabs, platformVocabs, organisationVocabs); } public void populateVocabsDataAsync(Map> resolvedPathCollection) { @@ -416,11 +416,11 @@ public void populateVocabsDataAsync(Map> resolvedP // Validate allResults to ensure none of the lists are empty if (allResults.stream().anyMatch(List::isEmpty)) { throw new IgnoreIndexingVocabsException("One or more vocab tasks returned empty results. Skipping indexing."); - } else { - // Call indexAllVocabs only after all tasks are completed and validated - log.info("Indexing fetched vocabs to {}", vocabsIndexName); - indexAllVocabs(allResults.get(0), allResults.get(1), allResults.get(2)); } + + // Call indexAllVocabs only after all tasks are completed and validated + log.info("Indexing fetched vocabs to {}", vocabsIndexName); + indexAllVocabs(allResults.get(0), allResults.get(1), allResults.get(2)); } catch (InterruptedException | IOException e) { Thread.currentThread().interrupt(); // Restore interrupt status log.error("Thread was interrupted while processing vocab tasks", e); From 1cf5a946171c7011c94dcf96f47c5eb1d34135d8 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Date: Fri, 17 Jan 2025 16:28:49 +1100 Subject: [PATCH 7/7] fix the test case --- .../aodn/ardcvocabs/service/ArdcVocabServiceImpl.java | 3 --- .../au/org/aodn/esindexer/service/VocabServiceIT.java | 11 +++++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java index f6fcae26..5417a3f1 100644 --- a/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java +++ b/ardcvocabs/src/main/java/au/org/aodn/ardcvocabs/service/ArdcVocabServiceImpl.java @@ -69,14 +69,12 @@ public Map> getResolvedPathCollection() { private void validateContentNotNull(ArdcCurrentPaths currentPath, ObjectNode categoryContent, ObjectNode vocabContent) { if (categoryContent == null || vocabContent == null) { - log.error("Failed to fetch HTML content for {}", currentPath.name()); throw new ExtractingPathVersionsException(String.format("Failed to fetch HTML content for %s", currentPath.name())); } } private void validateVersionsNotNull(ArdcCurrentPaths currentPath, String categoryVersion, String vocabVersion) { if (categoryVersion == null || vocabVersion == null) { - log.error("Version extraction returned null for {}", currentPath.name()); throw new ExtractingPathVersionsException(String.format("Version extraction returned null for %s", currentPath.name())); } } @@ -117,7 +115,6 @@ protected String extractVersionFromCurrentContent(ObjectNode currentContent) thr log.info("Valid Version Found: {}", version); return version; } else { - log.warn("Version does not match the required format: {}", about.apply(node)); throw new InvalidVersionFormatException(String.format("Version does not match the required format: %s", about.apply(node))); } } diff --git a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java index ed8b82aa..4e64dee6 100644 --- a/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java +++ b/indexer/src/test/java/au/org/aodn/esindexer/service/VocabServiceIT.java @@ -6,6 +6,7 @@ import au.org.aodn.ardcvocabs.service.ArdcVocabService; import au.org.aodn.esindexer.BaseTestClass; import au.org.aodn.esindexer.configuration.AppConstants; +import au.org.aodn.esindexer.exception.IgnoreIndexingVocabsException; import au.org.aodn.stac.model.ConceptModel; import au.org.aodn.stac.model.ThemesModel; import com.fasterxml.jackson.databind.JsonNode; @@ -142,10 +143,12 @@ void testSkipIndexingIfEmptyVocabs() throws IOException { when(mockArdcVocabService.getVocabTreeFromArdcByType(resolvedPathCollection.get("ORGANISATION_VOCAB"))).thenReturn(Collections.emptyList()); // Call the method - mockVocabService.populateVocabsData(resolvedPathCollection); - - // Verify that indexAllVocabs is not called - verify(mockVocabService, never()).indexAllVocabs(anyList(), anyList(), anyList()); + try { + mockVocabService.populateVocabsData(resolvedPathCollection); + } catch (IgnoreIndexingVocabsException e) { + // Verify that indexAllVocabs is not called + verify(mockVocabService, never()).indexAllVocabs(anyList(), anyList(), anyList()); + } } @Test