From b2a90bb8eab1752719196824881706e102890ad9 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 19 Nov 2025 10:35:16 -0500 Subject: [PATCH 01/16] fix with test --- .../ca/uhn/fhir/jpa/term/TermReadSvcImpl.java | 4 +- .../jpa/term/ValueSetExpansionR4Test.java | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java index 3b3ca09ed687..b1b9ee43d73a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java @@ -1348,7 +1348,7 @@ private SearchProperties buildSearchScrolls( private ValueSet.ConceptReferenceComponent getMatchedConceptIncludedInValueSet( ValueSet.ConceptSetComponent theIncludeOrExclude, TermConcept concept) { return theIncludeOrExclude.getConcept().stream() - .filter(includedConcept -> includedConcept.getCode().equalsIgnoreCase(concept.getCode())) + .filter(includedConcept -> includedConcept.getCode().equals(concept.getCode())) .findFirst() .orElse(null); } @@ -1358,7 +1358,7 @@ private ValueSet.ConceptReferenceComponent getMatchedConceptIncludedInValueSet( */ private PredicateFinalStep buildExpansionPredicate(List theCodes, SearchPredicateFactory thePredicate) { assert !theCodes.isEmpty(); - return thePredicate.simpleQueryString().field("myCode").matching(String.join(" | ", theCodes)); + return thePredicate.terms().field("myCode").matchingAny(theCodes); } private String buildCodeSystemUrlAndVersion(String theSystem, String theIncludeOrExcludeVersion) { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java index 661c13cd473c..6788c8c7dd43 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java @@ -2314,4 +2314,68 @@ public void reindexCodeSystems_withDeferredCodeSystems_reindexesAllCodeSystems() ReindexUtils.setRetryDelay(null); } } + + /** + * Test for case-sensitive code matching in ValueSet expansion. + * When a CodeSystem has caseSensitive=true and contains codes that differ only in case + * (e.g., "Drug" vs "drug"), and a ValueSet explicitly includes both codes, the expansion + * should return both codes, not just one. + *

+ * This test reproduces a bug where simpleQueryString() performs case-insensitive matching, + * causing only one code to be returned when both should be included. + */ + @Test + void testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase() { + // Arrange: Create case-sensitive CodeSystem with content=COMPLETE + CodeSystem codeSystem = new CodeSystem(); + codeSystem.setId("insurance-plan-type"); + codeSystem.setUrl("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); + codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); + codeSystem.setCaseSensitive(true); + codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); + + // Add "Drug" code (uppercase D) - mark as retired to match real HL7 resource + CodeSystem.ConceptDefinitionComponent drugRetired = codeSystem.addConcept(); + drugRetired.setCode("Drug"); + drugRetired.setDisplay("Drug"); + CodeSystem.ConceptPropertyComponent statusProp = drugRetired.addProperty(); + statusProp.setCode("status"); + statusProp.setValue(new CodeType("retired")); + CodeSystem.ConceptPropertyComponent inactiveProp = drugRetired.addProperty(); + inactiveProp.setCode("inactive"); + inactiveProp.setValue(new CodeType("true")); + + // Add "drug" code (lowercase d) - active + CodeSystem.ConceptDefinitionComponent drugActive = codeSystem.addConcept(); + drugActive.setCode("drug"); + drugActive.setDisplay("Drug"); + + myCodeSystemDao.create(codeSystem, mySrd); + myTerminologyDeferredStorageSvc.saveAllDeferred(); + + // Create ValueSet that explicitly includes both codes + ValueSet valueSet = new ValueSet(); + valueSet.setId("insuranceplan-type"); + valueSet.setUrl("http://terminology.hl7.org/ValueSet/insuranceplan-type"); + valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); + + ValueSet.ConceptSetComponent include = valueSet.getCompose().addInclude(); + include.setSystem("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); + include.addConcept().setCode("Drug"); // uppercase + include.addConcept().setCode("drug"); // lowercase + + myValueSetDao.create(valueSet, mySrd); + + // Act: Expand the ValueSet + ValueSet expanded = myTermSvc.expandValueSet(null, valueSet); + + // Assert: Both codes should be present + assertThat(expanded.getExpansion().getContains()).hasSize(2); + + List codes = expanded.getExpansion().getContains().stream() + .map(ValueSet.ValueSetExpansionContainsComponent::getCode) + .collect(Collectors.toList()); + + assertThat(codes).containsExactlyInAnyOrder("Drug", "drug"); + } } From 45af0fae16c0b6ed90e78a8d3e6116d756942fdb Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 19 Nov 2025 18:38:32 -0500 Subject: [PATCH 02/16] Add changelog entry for ValueSet case-sensitive code fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml new file mode 100644 index 000000000000..32334c69d18f --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 7394 +title: "Fixed an issue where ValueSet expansion did not properly handle case-sensitive codes that differ only in case. When a case-sensitive CodeSystem contained codes like Drug and drug, and a ValueSet explicitly included both codes, the expansion would previously return only one code instead of both. This has been corrected." From ab487ef71dce992906b847dfcb0f8d7f3b2c8610 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 19 Nov 2025 20:11:04 -0500 Subject: [PATCH 03/16] Fix ValueSet expansion test to properly validate case-sensitive code matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase to use FRAGMENT content mode and include entire system instead of enumerating specific concepts. This ensures the test exercises the Hibernate Search code path where the case-sensitivity bug manifests, providing proper TDD validation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../jpa/term/ValueSetExpansionR4Test.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java index 6788c8c7dd43..c29673339a41 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java @@ -2318,21 +2318,19 @@ public void reindexCodeSystems_withDeferredCodeSystems_reindexesAllCodeSystems() /** * Test for case-sensitive code matching in ValueSet expansion. * When a CodeSystem has caseSensitive=true and contains codes that differ only in case - * (e.g., "Drug" vs "drug"), and a ValueSet explicitly includes both codes, the expansion - * should return both codes, not just one. + * (e.g., "Drug" vs "drug"), the ValueSet expansion should return both codes, not just one. *

* This test reproduces a bug where simpleQueryString() performs case-insensitive matching, * causing only one code to be returned when both should be included. */ @Test void testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase() { - // Arrange: Create case-sensitive CodeSystem with content=COMPLETE + // Arrange: Create case-sensitive CodeSystem with content=FRAGMENT CodeSystem codeSystem = new CodeSystem(); - codeSystem.setId("insurance-plan-type"); - codeSystem.setUrl("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); + codeSystem.setUrl("http://example.com/fhir/CodeSystem/case-sensitive-test"); codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); codeSystem.setCaseSensitive(true); - codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); + codeSystem.setContent(CodeSystem.CodeSystemContentMode.FRAGMENT); // Add "Drug" code (uppercase D) - mark as retired to match real HL7 resource CodeSystem.ConceptDefinitionComponent drugRetired = codeSystem.addConcept(); @@ -2350,19 +2348,19 @@ void testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase() { drugActive.setCode("drug"); drugActive.setDisplay("Drug"); + // CRITICAL: Use create() and saveAllDeferred() to index concepts myCodeSystemDao.create(codeSystem, mySrd); myTerminologyDeferredStorageSvc.saveAllDeferred(); - // Create ValueSet that explicitly includes both codes + // Create ValueSet that includes the entire CodeSystem (not specific concepts) + // This triggers the Hibernate Search code path ValueSet valueSet = new ValueSet(); - valueSet.setId("insuranceplan-type"); - valueSet.setUrl("http://terminology.hl7.org/ValueSet/insuranceplan-type"); + valueSet.setUrl("http://example.com/fhir/ValueSet/case-sensitive-test"); valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); ValueSet.ConceptSetComponent include = valueSet.getCompose().addInclude(); - include.setSystem("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); - include.addConcept().setCode("Drug"); // uppercase - include.addConcept().setCode("drug"); // lowercase + include.setSystem("http://example.com/fhir/CodeSystem/case-sensitive-test"); + // CRITICAL: Do NOT enumerate specific concepts - include entire system to trigger Hibernate Search myValueSetDao.create(valueSet, mySrd); @@ -2370,12 +2368,13 @@ void testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase() { ValueSet expanded = myTermSvc.expandValueSet(null, valueSet); // Assert: Both codes should be present - assertThat(expanded.getExpansion().getContains()).hasSize(2); - List codes = expanded.getExpansion().getContains().stream() .map(ValueSet.ValueSetExpansionContainsComponent::getCode) .collect(Collectors.toList()); - assertThat(codes).containsExactlyInAnyOrder("Drug", "drug"); + // The bug causes only one of "Drug" or "drug" to be included due to case-insensitive matching + assertThat(codes) + .as("ValueSet expansion should include both case variants") + .contains("Drug", "drug"); } } From 3d42e442bfd297bcea2a3f091937f540ab4e57d4 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Thu, 20 Nov 2025 11:46:11 -0500 Subject: [PATCH 04/16] fix with test --- .../7394-valueset-code-case-sensitivity.yaml | 4 -- .../ca/uhn/fhir/jpa/term/TermReadSvcImpl.java | 4 +- .../jpa/term/ValueSetExpansionR4Test.java | 63 ------------------- 3 files changed, 2 insertions(+), 69 deletions(-) delete mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml deleted file mode 100644 index 32334c69d18f..000000000000 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -type: fix -issue: 7394 -title: "Fixed an issue where ValueSet expansion did not properly handle case-sensitive codes that differ only in case. When a case-sensitive CodeSystem contained codes like Drug and drug, and a ValueSet explicitly included both codes, the expansion would previously return only one code instead of both. This has been corrected." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java index b1b9ee43d73a..3b3ca09ed687 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java @@ -1348,7 +1348,7 @@ private SearchProperties buildSearchScrolls( private ValueSet.ConceptReferenceComponent getMatchedConceptIncludedInValueSet( ValueSet.ConceptSetComponent theIncludeOrExclude, TermConcept concept) { return theIncludeOrExclude.getConcept().stream() - .filter(includedConcept -> includedConcept.getCode().equals(concept.getCode())) + .filter(includedConcept -> includedConcept.getCode().equalsIgnoreCase(concept.getCode())) .findFirst() .orElse(null); } @@ -1358,7 +1358,7 @@ private ValueSet.ConceptReferenceComponent getMatchedConceptIncludedInValueSet( */ private PredicateFinalStep buildExpansionPredicate(List theCodes, SearchPredicateFactory thePredicate) { assert !theCodes.isEmpty(); - return thePredicate.terms().field("myCode").matchingAny(theCodes); + return thePredicate.simpleQueryString().field("myCode").matching(String.join(" | ", theCodes)); } private String buildCodeSystemUrlAndVersion(String theSystem, String theIncludeOrExcludeVersion) { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java index c29673339a41..661c13cd473c 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java @@ -2314,67 +2314,4 @@ public void reindexCodeSystems_withDeferredCodeSystems_reindexesAllCodeSystems() ReindexUtils.setRetryDelay(null); } } - - /** - * Test for case-sensitive code matching in ValueSet expansion. - * When a CodeSystem has caseSensitive=true and contains codes that differ only in case - * (e.g., "Drug" vs "drug"), the ValueSet expansion should return both codes, not just one. - *

- * This test reproduces a bug where simpleQueryString() performs case-insensitive matching, - * causing only one code to be returned when both should be included. - */ - @Test - void testExpandValueSet_CaseSensitiveCodeSystem_CodesWithDifferentCase() { - // Arrange: Create case-sensitive CodeSystem with content=FRAGMENT - CodeSystem codeSystem = new CodeSystem(); - codeSystem.setUrl("http://example.com/fhir/CodeSystem/case-sensitive-test"); - codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); - codeSystem.setCaseSensitive(true); - codeSystem.setContent(CodeSystem.CodeSystemContentMode.FRAGMENT); - - // Add "Drug" code (uppercase D) - mark as retired to match real HL7 resource - CodeSystem.ConceptDefinitionComponent drugRetired = codeSystem.addConcept(); - drugRetired.setCode("Drug"); - drugRetired.setDisplay("Drug"); - CodeSystem.ConceptPropertyComponent statusProp = drugRetired.addProperty(); - statusProp.setCode("status"); - statusProp.setValue(new CodeType("retired")); - CodeSystem.ConceptPropertyComponent inactiveProp = drugRetired.addProperty(); - inactiveProp.setCode("inactive"); - inactiveProp.setValue(new CodeType("true")); - - // Add "drug" code (lowercase d) - active - CodeSystem.ConceptDefinitionComponent drugActive = codeSystem.addConcept(); - drugActive.setCode("drug"); - drugActive.setDisplay("Drug"); - - // CRITICAL: Use create() and saveAllDeferred() to index concepts - myCodeSystemDao.create(codeSystem, mySrd); - myTerminologyDeferredStorageSvc.saveAllDeferred(); - - // Create ValueSet that includes the entire CodeSystem (not specific concepts) - // This triggers the Hibernate Search code path - ValueSet valueSet = new ValueSet(); - valueSet.setUrl("http://example.com/fhir/ValueSet/case-sensitive-test"); - valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); - - ValueSet.ConceptSetComponent include = valueSet.getCompose().addInclude(); - include.setSystem("http://example.com/fhir/CodeSystem/case-sensitive-test"); - // CRITICAL: Do NOT enumerate specific concepts - include entire system to trigger Hibernate Search - - myValueSetDao.create(valueSet, mySrd); - - // Act: Expand the ValueSet - ValueSet expanded = myTermSvc.expandValueSet(null, valueSet); - - // Assert: Both codes should be present - List codes = expanded.getExpansion().getContains().stream() - .map(ValueSet.ValueSetExpansionContainsComponent::getCode) - .collect(Collectors.toList()); - - // The bug causes only one of "Drug" or "drug" to be included due to case-insensitive matching - assertThat(codes) - .as("ValueSet expansion should include both case variants") - .contains("Drug", "drug"); - } } From 33ccfb9d0be7107bc7909240e6e5e7d15bc7f6a0 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 25 Nov 2025 17:33:03 -0500 Subject: [PATCH 05/16] fix with test --- .../validation/JpaValidationSupportChain.java | 6 +- ...alueSetExpansionCaseSensitiveManualIT.java | 83 +++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java index 426972bf19df..bd8860e7448f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java @@ -90,8 +90,12 @@ public void flush() { public void postConstruct() { myWorkerContextValidationSupportAdapter.setValidationSupport(this); - addValidationSupport(myDefaultProfileValidationSupport); + // JPA validation support comes first so that user-persisted resources + // take precedence over built-in default profile resources. + // This is important for case-sensitive CodeSystems where the user may + // have added additional codes that differ only by case from built-in codes. addValidationSupport(myJpaValidationSupport); + addValidationSupport(myDefaultProfileValidationSupport); addValidationSupport(myTerminologyService); addValidationSupport( new SnapshotGeneratingValidationSupport(myFhirContext, myWorkerContextValidationSupportAdapter)); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java new file mode 100644 index 000000000000..3bd71611112e --- /dev/null +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java @@ -0,0 +1,83 @@ +// Created by claude-sonnet-4-5 +package ca.uhn.fhir.jpa.term; + +import ca.uhn.fhir.jpa.test.BaseJpaR4Test; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.CodeType; +import org.hl7.fhir.r4.model.Enumerations; +import org.hl7.fhir.r4.model.ValueSet; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * This test validates that ValueSet expansion correctly handles case-sensitive + * CodeSystems where codes differ only by case (e.g., "drug" vs "Drug"). + * + * The test uses FRAGMENT content mode to reproduce the bug scenario where + * a user-defined CodeSystem should override the built-in HL7 CodeSystem. + */ +class ValueSetExpansionCaseSensitiveManualIT extends BaseJpaR4Test { + + @Test + void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { + // Create case-sensitive CodeSystem with FRAGMENT content mode + CodeSystem codeSystem = new CodeSystem(); + codeSystem.setUrl("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); + codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); + codeSystem.setCaseSensitive(true); + codeSystem.setContent(CodeSystem.CodeSystemContentMode.FRAGMENT); + + // Add all the codes from the real HL7 resource + codeSystem.addConcept().setCode("medical").setDisplay("Medical"); + codeSystem.addConcept().setCode("dental").setDisplay("Dental"); + codeSystem.addConcept().setCode("mental").setDisplay("Mental Health"); + codeSystem.addConcept().setCode("subst-ab").setDisplay("Substance Abuse"); + codeSystem.addConcept().setCode("vision").setDisplay("Vision"); + codeSystem.addConcept().setCode("drug").setDisplay("Drug"); // lowercase - active + codeSystem.addConcept().setCode("short-term").setDisplay("Short Term"); + codeSystem.addConcept().setCode("long-term").setDisplay("Long Term Care"); + codeSystem.addConcept().setCode("hospice").setDisplay("Hospice"); + codeSystem.addConcept().setCode("home").setDisplay("Home Health"); + + // Add "Drug" (uppercase D) - retired + CodeSystem.ConceptDefinitionComponent drugRetired = codeSystem.addConcept(); + drugRetired.setCode("Drug"); + drugRetired.setDisplay("Drug"); + CodeSystem.ConceptPropertyComponent statusProp = drugRetired.addProperty(); + statusProp.setCode("status"); + statusProp.setValue(new CodeType("retired")); + CodeSystem.ConceptPropertyComponent inactiveProp = drugRetired.addProperty(); + inactiveProp.setCode("inactive"); + inactiveProp.setValue(new CodeType("true")); + + myCodeSystemDao.create(codeSystem, mySrd); + myTerminologyDeferredStorageSvc.saveAllDeferred(); + + // Create ValueSet that includes the entire CodeSystem (NOT enumerated concepts) + ValueSet valueSet = new ValueSet(); + valueSet.setUrl("http://terminology.hl7.org/ValueSet/insuranceplan-type"); + valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); + + ValueSet.ConceptSetComponent include = valueSet.getCompose().addInclude(); + include.setSystem("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); + // CRITICAL: Do NOT enumerate specific concepts - include entire system + + myValueSetDao.create(valueSet, mySrd); + + // Act: Expand the ValueSet + ValueSet expanded = myTermSvc.expandValueSet(null, valueSet); + + // Assert: Both case variants should be present + List codes = expanded.getExpansion().getContains().stream() + .map(ValueSet.ValueSetExpansionContainsComponent::getCode) + .collect(Collectors.toList()); + + assertThat(codes) + .as("ValueSet expansion should include both case variants") + .contains("Drug", "drug"); + } +} From 9d7988978a83a0ac112c3ae9e5eafd5c4fd8d99b Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 25 Nov 2025 18:49:18 -0500 Subject: [PATCH 06/16] Fix ValueSet expansion for case-sensitive CodeSystems with FRAGMENT content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a user persists a CodeSystem that overrides a built-in HL7 CodeSystem, the JPA-persisted version should take precedence over the built-in default. This is critical for case-sensitive CodeSystems where codes differ only by case (e.g., "drug" vs "Drug"). The fix: - Add removeCodeSystem/removeValueSet methods to DefaultProfileValidationSupport to selectively remove URLs from the in-memory cache - At startup, scan JPA for persisted CodeSystem/ValueSet URLs and remove them from the default profile cache so JPA versions take precedence - When a CodeSystem or ValueSet is created/updated, remove its URL from the default profile cache and invalidate validation caches - Fix lazy initialization issue where removal was silently ignored if the terminology maps hadn't been initialized yet - Add null checks for delete operations where the resource may be null 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../DefaultProfileValidationSupport.java | 24 ++++ ...rofileValidationSupportBundleStrategy.java | 68 +++++++--- .../jpa/dao/JpaResourceDaoCodeSystem.java | 13 ++ .../fhir/jpa/dao/JpaResourceDaoValueSet.java | 28 ++++- .../validation/JpaValidationSupportChain.java | 118 +++++++++++++++++- ...alueSetExpansionCaseSensitiveManualIT.java | 7 ++ 6 files changed, 231 insertions(+), 27 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java index 48b1b7e5b762..663d2deacee3 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java @@ -169,6 +169,30 @@ public void flush() { myFlush.run(); } + /** + * Removes a CodeSystem with the given URL from the in-memory cache. + * This allows JPA-persisted resources to override built-in defaults. + * + * @param theUrl The canonical URL of the CodeSystem to remove + */ + public void removeCodeSystem(String theUrl) { + if (myDelegate instanceof DefaultProfileValidationSupportBundleStrategy) { + ((DefaultProfileValidationSupportBundleStrategy) myDelegate).removeCodeSystem(theUrl); + } + } + + /** + * Removes a ValueSet with the given URL from the in-memory cache. + * This allows JPA-persisted resources to override built-in defaults. + * + * @param theUrl The canonical URL of the ValueSet to remove + */ + public void removeValueSet(String theUrl) { + if (myDelegate instanceof DefaultProfileValidationSupportBundleStrategy) { + ((DefaultProfileValidationSupportBundleStrategy) myDelegate).removeValueSet(theUrl); + } + } + @Override public FhirContext getFhirContext() { return myCtx; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java index 16c97cb43e94..0d8c97c96934 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java @@ -215,20 +215,7 @@ public IBaseResource fetchCodeSystem(String theSystem) { private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSystem) { synchronized (this) { - Map codeSystems = myCodeSystems; - Map valueSets = myValueSets; - if (codeSystems == null || valueSets == null) { - codeSystems = new HashMap<>(); - valueSets = new HashMap<>(); - - initializeResourceLists(); - for (String next : myTerminologyResources) { - loadCodeSystems(codeSystems, valueSets, next); - } - - myCodeSystems = codeSystems; - myValueSets = valueSets; - } + ensureTerminologyMapsInitialized(); // System can take the form "http://url|version" String system = theSystem; @@ -241,9 +228,9 @@ private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSy IBaseResource candidate; if (codeSystem) { - candidate = codeSystems.get(system); + candidate = myCodeSystems.get(system); } else { - candidate = valueSets.get(system); + candidate = myValueSets.get(system); } if (candidate != null @@ -311,6 +298,55 @@ public void flush() { myStructureDefinitions = null; } + /** + * Removes a CodeSystem with the given URL from the in-memory cache. + * This allows JPA-persisted resources to override built-in defaults. + * + * @param theUrl The canonical URL of the CodeSystem to remove + */ + public void removeCodeSystem(String theUrl) { + synchronized (this) { + // Force initialization of the maps if not already done, + // then remove the URL so it won't be found by fetchCodeSystem + ensureTerminologyMapsInitialized(); + myCodeSystems.remove(theUrl); + } + } + + /** + * Removes a ValueSet with the given URL from the in-memory cache. + * This allows JPA-persisted resources to override built-in defaults. + * + * @param theUrl The canonical URL of the ValueSet to remove + */ + public void removeValueSet(String theUrl) { + synchronized (this) { + // Force initialization of the maps if not already done, + // then remove the URL so it won't be found by fetchValueSet + ensureTerminologyMapsInitialized(); + myValueSets.remove(theUrl); + } + } + + /** + * Ensures that myCodeSystems and myValueSets maps are initialized. + * Must be called while holding the synchronized lock on 'this'. + */ + private void ensureTerminologyMapsInitialized() { + if (myCodeSystems == null || myValueSets == null) { + Map codeSystems = new HashMap<>(); + Map valueSets = new HashMap<>(); + + initializeResourceLists(); + for (String next : myTerminologyResources) { + loadCodeSystems(codeSystems, valueSets, next); + } + + myCodeSystems = codeSystems; + myValueSets = valueSets; + } + } + @Override public FhirContext getFhirContext() { return myCtx; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java index 254991c9ca05..12eee89627d6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java @@ -38,6 +38,7 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; +import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; @@ -93,6 +94,9 @@ public class JpaResourceDaoCodeSystem extends BaseHapiF @Autowired private VersionCanonicalizer myVersionCanonicalizer; + @Autowired + private JpaValidationSupportChain myJpaValidationSupportChain; + @Override @PostConstruct public void start() { @@ -251,6 +255,15 @@ public ResourceTable updateEntity( myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded( cs, (ResourceTable) theEntity, theRequest); + + // Remove this CodeSystem URL from the default profile cache so that + // the JPA-persisted version takes precedence over built-in defaults + if (cs != null) { + String url = cs.getUrl(); + if (url != null) { + myJpaValidationSupportChain.removeCodeSystemFromDefaultCache(url); + } + } } /* diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java index d0b53eebbbf3..ce04e100e364 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java @@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.search.autocomplete.ValueSetAutocompleteOptions; +import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -65,6 +66,9 @@ public class JpaResourceDaoValueSet extends BaseHapiFhi @Autowired(required = false) private IFulltextSearchSvc myFulltextSearch; + @Autowired + private JpaValidationSupportChain myJpaValidationSupportChain; + @Override public T expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) { T source = read(theId, theRequestDetails); @@ -304,12 +308,24 @@ public ResourceTable updateEntity( theCreateNewHistoryEntry); if (thePerformIndexing) { - if (getStorageSettings().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) { - if (retVal.getDeleted() == null) { - ValueSet valueSet = myVersionCanonicalizer.valueSetToCanonical(theResource); - myTerminologySvc.storeTermValueSet(retVal, valueSet); - } else { - myTerminologySvc.deleteValueSetAndChildren(retVal); + if (!retVal.isUnchangedInCurrentOperation()) { + ValueSet valueSet = myVersionCanonicalizer.valueSetToCanonical(theResource); + + if (getStorageSettings().isPreExpandValueSets()) { + if (retVal.getDeleted() == null) { + myTerminologySvc.storeTermValueSet(retVal, valueSet); + } else { + myTerminologySvc.deleteValueSetAndChildren(retVal); + } + } + + // Remove this ValueSet URL from the default profile cache so that + // the JPA-persisted version takes precedence over built-in defaults + if (valueSet != null) { + String url = valueSet.getUrl(); + if (url != null) { + myJpaValidationSupportChain.removeValueSetFromDefaultCache(url); + } } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java index bd8860e7448f..680763d404ed 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java @@ -20,11 +20,17 @@ package ca.uhn.fhir.jpa.validation; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.config.JpaConfig; import ca.uhn.fhir.jpa.packages.NpmJpaValidationSupport; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.api.ITermConceptMappingSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService; @@ -32,11 +38,19 @@ import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport; import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain; import org.hl7.fhir.common.hapi.validation.validator.WorkerContextValidationSupportAdapter; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import java.util.List; + public class JpaValidationSupportChain extends ValidationSupportChain { + private static final Logger ourLog = LoggerFactory.getLogger(JpaValidationSupportChain.class); + private final FhirContext myFhirContext; private final WorkerContextValidationSupportAdapter myWorkerContextValidationSupportAdapter; @@ -60,6 +74,9 @@ public class JpaValidationSupportChain extends ValidationSupportChain { @Autowired private InMemoryTerminologyServerValidationSupport myInMemoryTerminologyServerValidationSupport; + @Autowired + private DaoRegistry myDaoRegistry; + /** * Constructor */ @@ -90,12 +107,11 @@ public void flush() { public void postConstruct() { myWorkerContextValidationSupportAdapter.setValidationSupport(this); - // JPA validation support comes first so that user-persisted resources - // take precedence over built-in default profile resources. - // This is important for case-sensitive CodeSystems where the user may - // have added additional codes that differ only by case from built-in codes. - addValidationSupport(myJpaValidationSupport); + // DefaultProfileValidationSupport comes first for performance (in-memory lookup). + // We then remove any URLs from its cache that exist in JPA, so that user-persisted + // resources take precedence over built-in defaults. addValidationSupport(myDefaultProfileValidationSupport); + addValidationSupport(myJpaValidationSupport); addValidationSupport(myTerminologyService); addValidationSupport( new SnapshotGeneratingValidationSupport(myFhirContext, myWorkerContextValidationSupportAdapter)); @@ -103,5 +119,97 @@ public void postConstruct() { addValidationSupport(myNpmJpaValidationSupport); addValidationSupport(new CommonCodeSystemsTerminologyService(myFhirContext)); addValidationSupport(myConceptMappingSvc); + + // Remove any URLs from the default profile cache that exist in JPA, + // so that JPA-persisted resources take precedence over built-in defaults. + removeJpaPersistedUrlsFromDefaultProfileCache(); + } + + /** + * Removes URLs from the DefaultProfileValidationSupport cache for any CodeSystem or ValueSet + * resources that have been persisted in JPA. This allows user-uploaded resources to override + * built-in defaults while maintaining the performance benefit of checking the in-memory + * default profile cache first. + */ + private void removeJpaPersistedUrlsFromDefaultProfileCache() { + if (!(myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport)) { + return; + } + DefaultProfileValidationSupport defaultSupport = + (DefaultProfileValidationSupport) myDefaultProfileValidationSupport; + + // Query for all CodeSystem URLs in JPA + removeUrlsFromDefaultCache(defaultSupport, "CodeSystem"); + + // Query for all ValueSet URLs in JPA + removeUrlsFromDefaultCache(defaultSupport, "ValueSet"); + } + + @SuppressWarnings("unchecked") + private void removeUrlsFromDefaultCache(DefaultProfileValidationSupport theDefaultSupport, String theResourceType) { + if (!myDaoRegistry.isResourceTypeSupported(theResourceType)) { + return; + } + + IFhirResourceDao dao = myDaoRegistry.getResourceDao(theResourceType); + SearchParameterMap searchMap = SearchParameterMap.newSynchronous(); + IBundleProvider results = dao.search(searchMap, new SystemRequestDetails()); + + List resources = results.getAllResources(); + for (IBaseResource resource : resources) { + String url = extractUrl(resource); + if (url != null) { + if ("CodeSystem".equals(theResourceType)) { + theDefaultSupport.removeCodeSystem(url); + } else if ("ValueSet".equals(theResourceType)) { + theDefaultSupport.removeValueSet(url); + } else { + ourLog.warn( + "Unexpected resource type {} when removing URL from default profile cache", + theResourceType); + return; + } + ourLog.debug( + "Removed {} URL {} from default profile cache (JPA-persisted resource takes precedence)", + theResourceType, + url); + } + } + + if (!resources.isEmpty()) { + ourLog.info( + "Removed {} {} URLs from default profile cache to allow JPA-persisted resources to take precedence", + resources.size(), + theResourceType); + } + } + + @SuppressWarnings("unchecked") + private String extractUrl(IBaseResource theResource) { + IPrimitiveType urlElement = (IPrimitiveType) + myFhirContext.newTerser().getSingleValueOrNull(theResource, "url", IPrimitiveType.class); + return urlElement != null ? urlElement.getValue() : null; + } + + /** + * Removes a CodeSystem URL from the default profile cache. + * Called when a CodeSystem is created or updated in JPA. + */ + public void removeCodeSystemFromDefaultCache(String theUrl) { + if (myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport defaultSupport) { + defaultSupport.removeCodeSystem(theUrl); + invalidateCaches(); + } + } + + /** + * Removes a ValueSet URL from the default profile cache. + * Called when a ValueSet is created or updated in JPA. + */ + public void removeValueSetFromDefaultCache(String theUrl) { + if (myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport defaultSupport) { + defaultSupport.removeValueSet(theUrl); + invalidateCaches(); + } } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java index 3bd71611112e..18029201c4ba 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java @@ -8,6 +8,9 @@ import org.hl7.fhir.r4.model.ValueSet; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.List; import java.util.stream.Collectors; @@ -22,6 +25,8 @@ */ class ValueSetExpansionCaseSensitiveManualIT extends BaseJpaR4Test { + private static final Logger ourLog = LoggerFactory.getLogger(ValueSetExpansionCaseSensitiveManualIT.class); + @Test void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { // Create case-sensitive CodeSystem with FRAGMENT content mode @@ -76,6 +81,8 @@ void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { .map(ValueSet.ValueSetExpansionContainsComponent::getCode) .collect(Collectors.toList()); + ourLog.info("Expanded ValueSet contains {} codes: {}", codes.size(), codes); + assertThat(codes) .as("ValueSet expansion should include both case variants") .contains("Drug", "drug"); From 6f8612032d23b6868fc9886c6567d367576d551f Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 13:23:03 -0500 Subject: [PATCH 07/16] fix test --- .../uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java | 4 ++-- ...IT.java => ValueSetExpansionCaseSensitiveManualTest.java} | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) rename hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/{ValueSetExpansionCaseSensitiveManualIT.java => ValueSetExpansionCaseSensitiveManualTest.java} (96%) diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java index 9b3cb7d5aa0f..9c5940080274 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java @@ -782,11 +782,11 @@ public void testValidate() { fail(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome())); } myCaptureQueriesListener.logSelectQueriesForCurrentThread(); - assertEquals(11, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size()); + assertEquals(13, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size()); - assertEquals(9, myCaptureQueriesListener.countCommits()); + assertEquals(11, myCaptureQueriesListener.countCommits()); // Validate again (should rely only on caches) myCaptureQueriesListener.clear(); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java similarity index 96% rename from hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java rename to hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java index 18029201c4ba..3756f3829c35 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualIT.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java @@ -23,9 +23,9 @@ * The test uses FRAGMENT content mode to reproduce the bug scenario where * a user-defined CodeSystem should override the built-in HL7 CodeSystem. */ -class ValueSetExpansionCaseSensitiveManualIT extends BaseJpaR4Test { +class ValueSetExpansionCaseSensitiveManualTest extends BaseJpaR4Test { - private static final Logger ourLog = LoggerFactory.getLogger(ValueSetExpansionCaseSensitiveManualIT.class); + private static final Logger ourLog = LoggerFactory.getLogger(ValueSetExpansionCaseSensitiveManualTest.class); @Test void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { @@ -35,6 +35,7 @@ void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); codeSystem.setCaseSensitive(true); codeSystem.setContent(CodeSystem.CodeSystemContentMode.FRAGMENT); + codeSystem.setVersion("3.0.0"); // Add all the codes from the real HL7 resource codeSystem.addConcept().setCode("medical").setDisplay("Medical"); From c2cf715fb4a696ea19abfd66941f05d74bcec4db Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 14:40:29 -0500 Subject: [PATCH 08/16] back out first change --- .../DefaultProfileValidationSupport.java | 24 ---- ...rofileValidationSupportBundleStrategy.java | 68 +++-------- .../jpa/dao/JpaResourceDaoCodeSystem.java | 13 -- .../fhir/jpa/dao/JpaResourceDaoValueSet.java | 28 +---- .../validation/JpaValidationSupportChain.java | 112 ------------------ .../r4/FhirResourceDaoR4QueryCountTest.java | 4 +- 6 files changed, 24 insertions(+), 225 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java index 663d2deacee3..48b1b7e5b762 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java @@ -169,30 +169,6 @@ public void flush() { myFlush.run(); } - /** - * Removes a CodeSystem with the given URL from the in-memory cache. - * This allows JPA-persisted resources to override built-in defaults. - * - * @param theUrl The canonical URL of the CodeSystem to remove - */ - public void removeCodeSystem(String theUrl) { - if (myDelegate instanceof DefaultProfileValidationSupportBundleStrategy) { - ((DefaultProfileValidationSupportBundleStrategy) myDelegate).removeCodeSystem(theUrl); - } - } - - /** - * Removes a ValueSet with the given URL from the in-memory cache. - * This allows JPA-persisted resources to override built-in defaults. - * - * @param theUrl The canonical URL of the ValueSet to remove - */ - public void removeValueSet(String theUrl) { - if (myDelegate instanceof DefaultProfileValidationSupportBundleStrategy) { - ((DefaultProfileValidationSupportBundleStrategy) myDelegate).removeValueSet(theUrl); - } - } - @Override public FhirContext getFhirContext() { return myCtx; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java index 0d8c97c96934..16c97cb43e94 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupportBundleStrategy.java @@ -215,7 +215,20 @@ public IBaseResource fetchCodeSystem(String theSystem) { private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSystem) { synchronized (this) { - ensureTerminologyMapsInitialized(); + Map codeSystems = myCodeSystems; + Map valueSets = myValueSets; + if (codeSystems == null || valueSets == null) { + codeSystems = new HashMap<>(); + valueSets = new HashMap<>(); + + initializeResourceLists(); + for (String next : myTerminologyResources) { + loadCodeSystems(codeSystems, valueSets, next); + } + + myCodeSystems = codeSystems; + myValueSets = valueSets; + } // System can take the form "http://url|version" String system = theSystem; @@ -228,9 +241,9 @@ private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSy IBaseResource candidate; if (codeSystem) { - candidate = myCodeSystems.get(system); + candidate = codeSystems.get(system); } else { - candidate = myValueSets.get(system); + candidate = valueSets.get(system); } if (candidate != null @@ -298,55 +311,6 @@ public void flush() { myStructureDefinitions = null; } - /** - * Removes a CodeSystem with the given URL from the in-memory cache. - * This allows JPA-persisted resources to override built-in defaults. - * - * @param theUrl The canonical URL of the CodeSystem to remove - */ - public void removeCodeSystem(String theUrl) { - synchronized (this) { - // Force initialization of the maps if not already done, - // then remove the URL so it won't be found by fetchCodeSystem - ensureTerminologyMapsInitialized(); - myCodeSystems.remove(theUrl); - } - } - - /** - * Removes a ValueSet with the given URL from the in-memory cache. - * This allows JPA-persisted resources to override built-in defaults. - * - * @param theUrl The canonical URL of the ValueSet to remove - */ - public void removeValueSet(String theUrl) { - synchronized (this) { - // Force initialization of the maps if not already done, - // then remove the URL so it won't be found by fetchValueSet - ensureTerminologyMapsInitialized(); - myValueSets.remove(theUrl); - } - } - - /** - * Ensures that myCodeSystems and myValueSets maps are initialized. - * Must be called while holding the synchronized lock on 'this'. - */ - private void ensureTerminologyMapsInitialized() { - if (myCodeSystems == null || myValueSets == null) { - Map codeSystems = new HashMap<>(); - Map valueSets = new HashMap<>(); - - initializeResourceLists(); - for (String next : myTerminologyResources) { - loadCodeSystems(codeSystems, valueSets, next); - } - - myCodeSystems = codeSystems; - myValueSets = valueSets; - } - } - @Override public FhirContext getFhirContext() { return myCtx; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java index 12eee89627d6..254991c9ca05 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoCodeSystem.java @@ -38,7 +38,6 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; -import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; @@ -94,9 +93,6 @@ public class JpaResourceDaoCodeSystem extends BaseHapiF @Autowired private VersionCanonicalizer myVersionCanonicalizer; - @Autowired - private JpaValidationSupportChain myJpaValidationSupportChain; - @Override @PostConstruct public void start() { @@ -255,15 +251,6 @@ public ResourceTable updateEntity( myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded( cs, (ResourceTable) theEntity, theRequest); - - // Remove this CodeSystem URL from the default profile cache so that - // the JPA-persisted version takes precedence over built-in defaults - if (cs != null) { - String url = cs.getUrl(); - if (url != null) { - myJpaValidationSupportChain.removeCodeSystemFromDefaultCache(url); - } - } } /* diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java index ce04e100e364..d0b53eebbbf3 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoValueSet.java @@ -29,7 +29,6 @@ import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.search.autocomplete.ValueSetAutocompleteOptions; -import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -66,9 +65,6 @@ public class JpaResourceDaoValueSet extends BaseHapiFhi @Autowired(required = false) private IFulltextSearchSvc myFulltextSearch; - @Autowired - private JpaValidationSupportChain myJpaValidationSupportChain; - @Override public T expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) { T source = read(theId, theRequestDetails); @@ -308,24 +304,12 @@ public ResourceTable updateEntity( theCreateNewHistoryEntry); if (thePerformIndexing) { - if (!retVal.isUnchangedInCurrentOperation()) { - ValueSet valueSet = myVersionCanonicalizer.valueSetToCanonical(theResource); - - if (getStorageSettings().isPreExpandValueSets()) { - if (retVal.getDeleted() == null) { - myTerminologySvc.storeTermValueSet(retVal, valueSet); - } else { - myTerminologySvc.deleteValueSetAndChildren(retVal); - } - } - - // Remove this ValueSet URL from the default profile cache so that - // the JPA-persisted version takes precedence over built-in defaults - if (valueSet != null) { - String url = valueSet.getUrl(); - if (url != null) { - myJpaValidationSupportChain.removeValueSetFromDefaultCache(url); - } + if (getStorageSettings().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) { + if (retVal.getDeleted() == null) { + ValueSet valueSet = myVersionCanonicalizer.valueSetToCanonical(theResource); + myTerminologySvc.storeTermValueSet(retVal, valueSet); + } else { + myTerminologySvc.deleteValueSetAndChildren(retVal); } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java index 680763d404ed..426972bf19df 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java @@ -20,17 +20,11 @@ package ca.uhn.fhir.jpa.validation; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport; -import ca.uhn.fhir.jpa.api.dao.DaoRegistry; -import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.config.JpaConfig; import ca.uhn.fhir.jpa.packages.NpmJpaValidationSupport; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.api.ITermConceptMappingSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc; -import ca.uhn.fhir.rest.api.server.IBundleProvider; -import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService; @@ -38,19 +32,11 @@ import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport; import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain; import org.hl7.fhir.common.hapi.validation.validator.WorkerContextValidationSupportAdapter; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IPrimitiveType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import java.util.List; - public class JpaValidationSupportChain extends ValidationSupportChain { - private static final Logger ourLog = LoggerFactory.getLogger(JpaValidationSupportChain.class); - private final FhirContext myFhirContext; private final WorkerContextValidationSupportAdapter myWorkerContextValidationSupportAdapter; @@ -74,9 +60,6 @@ public class JpaValidationSupportChain extends ValidationSupportChain { @Autowired private InMemoryTerminologyServerValidationSupport myInMemoryTerminologyServerValidationSupport; - @Autowired - private DaoRegistry myDaoRegistry; - /** * Constructor */ @@ -107,9 +90,6 @@ public void flush() { public void postConstruct() { myWorkerContextValidationSupportAdapter.setValidationSupport(this); - // DefaultProfileValidationSupport comes first for performance (in-memory lookup). - // We then remove any URLs from its cache that exist in JPA, so that user-persisted - // resources take precedence over built-in defaults. addValidationSupport(myDefaultProfileValidationSupport); addValidationSupport(myJpaValidationSupport); addValidationSupport(myTerminologyService); @@ -119,97 +99,5 @@ public void postConstruct() { addValidationSupport(myNpmJpaValidationSupport); addValidationSupport(new CommonCodeSystemsTerminologyService(myFhirContext)); addValidationSupport(myConceptMappingSvc); - - // Remove any URLs from the default profile cache that exist in JPA, - // so that JPA-persisted resources take precedence over built-in defaults. - removeJpaPersistedUrlsFromDefaultProfileCache(); - } - - /** - * Removes URLs from the DefaultProfileValidationSupport cache for any CodeSystem or ValueSet - * resources that have been persisted in JPA. This allows user-uploaded resources to override - * built-in defaults while maintaining the performance benefit of checking the in-memory - * default profile cache first. - */ - private void removeJpaPersistedUrlsFromDefaultProfileCache() { - if (!(myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport)) { - return; - } - DefaultProfileValidationSupport defaultSupport = - (DefaultProfileValidationSupport) myDefaultProfileValidationSupport; - - // Query for all CodeSystem URLs in JPA - removeUrlsFromDefaultCache(defaultSupport, "CodeSystem"); - - // Query for all ValueSet URLs in JPA - removeUrlsFromDefaultCache(defaultSupport, "ValueSet"); - } - - @SuppressWarnings("unchecked") - private void removeUrlsFromDefaultCache(DefaultProfileValidationSupport theDefaultSupport, String theResourceType) { - if (!myDaoRegistry.isResourceTypeSupported(theResourceType)) { - return; - } - - IFhirResourceDao dao = myDaoRegistry.getResourceDao(theResourceType); - SearchParameterMap searchMap = SearchParameterMap.newSynchronous(); - IBundleProvider results = dao.search(searchMap, new SystemRequestDetails()); - - List resources = results.getAllResources(); - for (IBaseResource resource : resources) { - String url = extractUrl(resource); - if (url != null) { - if ("CodeSystem".equals(theResourceType)) { - theDefaultSupport.removeCodeSystem(url); - } else if ("ValueSet".equals(theResourceType)) { - theDefaultSupport.removeValueSet(url); - } else { - ourLog.warn( - "Unexpected resource type {} when removing URL from default profile cache", - theResourceType); - return; - } - ourLog.debug( - "Removed {} URL {} from default profile cache (JPA-persisted resource takes precedence)", - theResourceType, - url); - } - } - - if (!resources.isEmpty()) { - ourLog.info( - "Removed {} {} URLs from default profile cache to allow JPA-persisted resources to take precedence", - resources.size(), - theResourceType); - } - } - - @SuppressWarnings("unchecked") - private String extractUrl(IBaseResource theResource) { - IPrimitiveType urlElement = (IPrimitiveType) - myFhirContext.newTerser().getSingleValueOrNull(theResource, "url", IPrimitiveType.class); - return urlElement != null ? urlElement.getValue() : null; - } - - /** - * Removes a CodeSystem URL from the default profile cache. - * Called when a CodeSystem is created or updated in JPA. - */ - public void removeCodeSystemFromDefaultCache(String theUrl) { - if (myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport defaultSupport) { - defaultSupport.removeCodeSystem(theUrl); - invalidateCaches(); - } - } - - /** - * Removes a ValueSet URL from the default profile cache. - * Called when a ValueSet is created or updated in JPA. - */ - public void removeValueSetFromDefaultCache(String theUrl) { - if (myDefaultProfileValidationSupport instanceof DefaultProfileValidationSupport defaultSupport) { - defaultSupport.removeValueSet(theUrl); - invalidateCaches(); - } } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java index 9c5940080274..9b3cb7d5aa0f 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java @@ -782,11 +782,11 @@ public void testValidate() { fail(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome())); } myCaptureQueriesListener.logSelectQueriesForCurrentThread(); - assertEquals(13, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size()); + assertEquals(11, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size()); assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size()); - assertEquals(11, myCaptureQueriesListener.countCommits()); + assertEquals(9, myCaptureQueriesListener.countCommits()); // Validate again (should rely only on caches) myCaptureQueriesListener.clear(); From 892e24ec4354fa214c30bcdcf705ecf1ee0ba71c Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 14:43:30 -0500 Subject: [PATCH 09/16] back out first change --- .../fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java index 3756f3829c35..69b1989bc634 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java @@ -35,7 +35,7 @@ void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { codeSystem.setStatus(Enumerations.PublicationStatus.ACTIVE); codeSystem.setCaseSensitive(true); codeSystem.setContent(CodeSystem.CodeSystemContentMode.FRAGMENT); - codeSystem.setVersion("3.0.0"); + codeSystem.setVersion("4.0.1"); // Add all the codes from the real HL7 resource codeSystem.addConcept().setCode("medical").setDisplay("Medical"); From fcbe49cb0fea6b8d31eafaa65abe07fc771c02f8 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 18:06:40 -0500 Subject: [PATCH 10/16] add fix discussed with James --- .../validation/JpaValidationSupportChain.java | 26 +++++++++++- ...ueSetExpansionCaseSensitiveManualTest.java | 16 ++++++++ .../jpa/api/config/JpaStorageSettings.java | 40 ++++++++++++++++++- .../support/ValidationSupportChain.java | 11 +++++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java index 426972bf19df..664c5f35dace 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/validation/JpaValidationSupportChain.java @@ -21,10 +21,12 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.config.JpaConfig; import ca.uhn.fhir.jpa.packages.NpmJpaValidationSupport; import ca.uhn.fhir.jpa.term.api.ITermConceptMappingSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc; +import com.google.common.annotations.VisibleForTesting; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService; @@ -60,6 +62,9 @@ public class JpaValidationSupportChain extends ValidationSupportChain { @Autowired private InMemoryTerminologyServerValidationSupport myInMemoryTerminologyServerValidationSupport; + @Autowired + private JpaStorageSettings myJpaStorageSettings; + /** * Constructor */ @@ -90,8 +95,13 @@ public void flush() { public void postConstruct() { myWorkerContextValidationSupportAdapter.setValidationSupport(this); - addValidationSupport(myDefaultProfileValidationSupport); - addValidationSupport(myJpaValidationSupport); + if (myJpaStorageSettings.isAllowDatabaseValidationOverride()) { + addValidationSupport(myJpaValidationSupport); + addValidationSupport(myDefaultProfileValidationSupport); + } else { + addValidationSupport(myDefaultProfileValidationSupport); + addValidationSupport(myJpaValidationSupport); + } addValidationSupport(myTerminologyService); addValidationSupport( new SnapshotGeneratingValidationSupport(myFhirContext, myWorkerContextValidationSupportAdapter)); @@ -100,4 +110,16 @@ public void postConstruct() { addValidationSupport(new CommonCodeSystemsTerminologyService(myFhirContext)); addValidationSupport(myConceptMappingSvc); } + + /** + * Clears and rebuilds the validation support chain. + * This method is intended for unit testing purposes only to allow + * re-initializing the chain after changing configuration settings + * such as {@link JpaStorageSettings#setAllowDatabaseValidationOverride(boolean)}. + */ + @VisibleForTesting + public void rebuildChainForUnitTest() { + super.clearChainForUnitTest(); + postConstruct(); + } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java index 69b1989bc634..84a54959bdc5 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionCaseSensitiveManualTest.java @@ -1,15 +1,20 @@ // Created by claude-sonnet-4-5 package ca.uhn.fhir.jpa.term; +import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; +import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.ValueSet; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.stream.Collectors; @@ -26,9 +31,20 @@ class ValueSetExpansionCaseSensitiveManualTest extends BaseJpaR4Test { private static final Logger ourLog = LoggerFactory.getLogger(ValueSetExpansionCaseSensitiveManualTest.class); + @Autowired + private IValidationSupport myJpaValidationSupportChain; + + @AfterEach + public void after() { + myStorageSettings.setAllowDatabaseValidationOverride(new JpaStorageSettings().isAllowDatabaseValidationOverride()); + ((JpaValidationSupportChain)myJpaValidationSupportChain).rebuildChainForUnitTest(); + } @Test void testValueSetExpansion_CaseSensitive_IncludeEntireSystem() { + myStorageSettings.setAllowDatabaseValidationOverride(true); + ((JpaValidationSupportChain)myJpaValidationSupportChain).rebuildChainForUnitTest(); + // Create case-sensitive CodeSystem with FRAGMENT content mode CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl("http://terminology.hl7.org/CodeSystem/insurance-plan-type"); diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java index 7e603a12309d..d08b6bac0ed5 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java @@ -426,6 +426,20 @@ public class JpaStorageSettings extends StorageSettings { */ private boolean myWriteToSearchParamIdentityTable = true; + /** + * Controls whether database-stored validation resources (CodeSystem, ValueSet, etc.) take precedence + * over built-in default profile validation resources when resolving during validation. + *

+ * When set to {@code true}, the JPA validation support is registered before the default profile + * validation support in the validation chain, allowing database-stored resources to override + * built-in definitions. + *

+ * Defaults to {@code false}, meaning built-in default profiles take precedence. + * + * @since 8.2.0 + */ + private boolean myAllowDatabaseValidationOverride = false; + /** * Constructor */ @@ -2738,7 +2752,31 @@ public void setWriteToSearchParamIdentityTable(boolean theWriteToSearchParamIden myWriteToSearchParamIdentityTable = theWriteToSearchParamIdentityTable; } - public enum StoreMetaSourceInformationEnum { + /** + * Sets whether database-stored validation resources should take precedence over built-in + * default profile validation resources. + * + * @param theAllowDatabaseValidationOverride if {@code true}, database resources override defaults + * @see #isAllowDatabaseValidationOverride() + * @since 8.2.0 + */ + public void setAllowDatabaseValidationOverride(boolean theAllowDatabaseValidationOverride) { + myAllowDatabaseValidationOverride = theAllowDatabaseValidationOverride; + } + + /** + * Returns whether database-stored validation resources take precedence over built-in + * default profile validation resources. + * + * @return {@code true} if database resources override defaults; {@code false} otherwise + * @see #setAllowDatabaseValidationOverride(boolean) + * @since 8.2.0 + */ + public boolean isAllowDatabaseValidationOverride() { + return myAllowDatabaseValidationOverride; + } + + public enum StoreMetaSourceInformationEnum { NONE(false, false), SOURCE_URI(true, false), REQUEST_ID(false, true), diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java index 2e024aeb4cd3..5113e4aa2089 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java @@ -18,6 +18,7 @@ import ca.uhn.fhir.util.Logs; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.UrlUtil; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -1071,6 +1072,16 @@ int getMetricExpiringCacheMaxSize() { return myCacheConfiguration.getCacheSize(); } + /** + * Clears all validation support modules from the chain. + * This method is intended for unit testing purposes only to allow + * rebuilding the chain with different configurations. + */ + @VisibleForTesting + protected void clearChainForUnitTest() { + myChain.clear(); + } + /** * @since 5.4.0 */ From 50738b8c16aab1b867ac52f8415c64b48c40e43c Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 18:10:34 -0500 Subject: [PATCH 11/16] Add changelog entry for database validation override setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds changelog documenting the new JpaStorageSettings.setAllowDatabaseValidationOverride() setting which allows database-stored CodeSystem and ValueSet resources to take precedence over built-in default profile validation resources. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../8_8_0/7394-valueset-code-case-sensitivity.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml new file mode 100644 index 000000000000..c3b0175e2fd2 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml @@ -0,0 +1,7 @@ +--- +type: add +issue: 7394 +title: "A new setting JpaStorageSettings.setAllowDatabaseValidationOverride(boolean) has been added. + When enabled, database-stored CodeSystem and ValueSet resources take precedence over built-in + default profile validation resources. This allows user-defined terminology resources to override + built-in HL7 definitions." \ No newline at end of file From 271bfe3b0f73a38990c25a6a33f08ac493e2e416 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 19:08:45 -0500 Subject: [PATCH 12/16] fix version --- .../java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java index d08b6bac0ed5..73011426cd6a 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java @@ -436,7 +436,7 @@ public class JpaStorageSettings extends StorageSettings { *

* Defaults to {@code false}, meaning built-in default profiles take precedence. * - * @since 8.2.0 + * @since 8.8.0 */ private boolean myAllowDatabaseValidationOverride = false; @@ -2758,7 +2758,7 @@ public void setWriteToSearchParamIdentityTable(boolean theWriteToSearchParamIden * * @param theAllowDatabaseValidationOverride if {@code true}, database resources override defaults * @see #isAllowDatabaseValidationOverride() - * @since 8.2.0 + * @since 8.8.0 */ public void setAllowDatabaseValidationOverride(boolean theAllowDatabaseValidationOverride) { myAllowDatabaseValidationOverride = theAllowDatabaseValidationOverride; @@ -2770,7 +2770,7 @@ public void setAllowDatabaseValidationOverride(boolean theAllowDatabaseValidatio * * @return {@code true} if database resources override defaults; {@code false} otherwise * @see #setAllowDatabaseValidationOverride(boolean) - * @since 8.2.0 + * @since 8.8.0 */ public boolean isAllowDatabaseValidationOverride() { return myAllowDatabaseValidationOverride; From 378dc865ae94f535e22b0105782697f2e4c67478 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 19:11:18 -0500 Subject: [PATCH 13/16] Add documentation for allowDatabaseValidationOverride setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the new JpaStorageSettings.setAllowDatabaseValidationOverride(boolean) setting in the validation support modules documentation, explaining how it can be used to give database-stored terminology resources precedence over built-in HL7 definitions during validation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../validation/validation_support_modules.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md index a7ac3d16d202..57eac711f5ba 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md @@ -177,6 +177,34 @@ these generated issues, you can use the [ValidationMessageUnknownCodeSystemPostP This module is deprecated and no longer provides any functionality. Caching is provided by [ValidationSupportChain](#validationsupportchain). +# JPA Server Validation Chain Configuration + +When using the JPA Server, the validation support chain is configured automatically. By default, the built-in FHIR definitions (from `DefaultProfileValidationSupport`) take precedence over user-defined terminology resources stored in the database (from `JpaPersistedResourceValidationSupport`). + +## Allowing Database Validation Override + +In some cases, you may want your database-stored CodeSystem and ValueSet resources to take precedence over the built-in HL7 definitions. This is useful when: + +* You need to override a built-in terminology resource with a different version + +To enable this behavior, use the `allowDatabaseValidationOverride` setting: + +```java +@Bean +public JpaStorageSettings storageSettings() { + JpaStorageSettings retVal = new JpaStorageSettings(); + // Allow database-stored validation resources to take precedence + retVal.setAllowDatabaseValidationOverride(true); + return retVal; +} +``` + +When this setting is enabled (`true`), the JPA validation support (database-stored resources) is placed before the default profile validation support in the chain. When disabled (`false`, the default), the built-in definitions take precedence. + +

+Note: Enabling this setting means that any CodeSystem or ValueSet you store in the database with the same URL as a built-in HL7 resource will override the built-in version during validation. Use this setting carefully as it can affect validation behavior for standard FHIR resources. +

+ # Recipes The IValidationSupport instance passed to the FhirInstanceValidator will often resemble the chain shown in the diagram below. In this diagram: From 67c7e075ff74e7a7ca535a7dedef6637a7a8994c Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 26 Nov 2025 19:13:55 -0500 Subject: [PATCH 14/16] doc --- .../hapi/fhir/docs/validation/validation_support_modules.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md index 57eac711f5ba..2b70530387fa 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/validation/validation_support_modules.md @@ -183,9 +183,7 @@ When using the JPA Server, the validation support chain is configured automatica ## Allowing Database Validation Override -In some cases, you may want your database-stored CodeSystem and ValueSet resources to take precedence over the built-in HL7 definitions. This is useful when: - -* You need to override a built-in terminology resource with a different version +In some cases, you may want your database-stored CodeSystem and ValueSet resources to take precedence over the built-in HL7 definitions. This is useful when you need to override a built-in terminology resource with a different version of that resource. To enable this behavior, use the `allowDatabaseValidationOverride` setting: From 578b823b7970d55fe46ff5944818cdcc542c01ee Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Thu, 27 Nov 2025 12:28:13 -0500 Subject: [PATCH 15/16] spotless and review feedback --- .../changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml | 2 +- .../java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml index c3b0175e2fd2..8679520a674d 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7394-valueset-code-case-sensitivity.yaml @@ -4,4 +4,4 @@ issue: 7394 title: "A new setting JpaStorageSettings.setAllowDatabaseValidationOverride(boolean) has been added. When enabled, database-stored CodeSystem and ValueSet resources take precedence over built-in default profile validation resources. This allows user-defined terminology resources to override - built-in HL7 definitions." \ No newline at end of file + built-in HL7 definitions when performing validation operations." diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java index 73011426cd6a..13e0bec51174 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.java @@ -2776,7 +2776,7 @@ public boolean isAllowDatabaseValidationOverride() { return myAllowDatabaseValidationOverride; } - public enum StoreMetaSourceInformationEnum { + public enum StoreMetaSourceInformationEnum { NONE(false, false), SOURCE_URI(true, false), REQUEST_ID(false, true), From 459c5b589251cf2920c9b32009eee6511da10674 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Thu, 27 Nov 2025 12:35:24 -0500 Subject: [PATCH 16/16] version bump --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- hapi-fhir-bom/pom.xml | 4 ++-- hapi-fhir-checkstyle/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-api/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-apache-http5/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 2 +- hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 2 +- hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jpa-hibernate-services/pom.xml | 2 +- hapi-fhir-jpa/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- hapi-fhir-jpaserver-elastic-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-hfql/pom.xml | 2 +- hapi-fhir-jpaserver-ips/pom.xml | 2 +- hapi-fhir-jpaserver-mdm/pom.xml | 2 +- hapi-fhir-jpaserver-model/pom.xml | 2 +- hapi-fhir-jpaserver-searchparam/pom.xml | 2 +- hapi-fhir-jpaserver-subscription/pom.xml | 2 +- hapi-fhir-jpaserver-test-dstu2/pom.xml | 2 +- hapi-fhir-jpaserver-test-dstu3/pom.xml | 2 +- hapi-fhir-jpaserver-test-r4/pom.xml | 2 +- hapi-fhir-jpaserver-test-r4b/pom.xml | 2 +- hapi-fhir-jpaserver-test-r5/pom.xml | 2 +- hapi-fhir-jpaserver-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 2 +- hapi-fhir-repositories/pom.xml | 2 +- hapi-fhir-server-cds-hooks/pom.xml | 2 +- hapi-fhir-server-mdm/pom.xml | 2 +- hapi-fhir-server-openapi/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml | 2 +- hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml | 4 ++-- hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml | 2 +- hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml | 2 +- hapi-fhir-serviceloaders/pom.xml | 2 +- .../hapi-fhir-spring-boot-autoconfigure/pom.xml | 2 +- .../hapi-fhir-spring-boot-sample-client-apache/pom.xml | 2 +- .../hapi-fhir-spring-boot-sample-client-okhttp/pom.xml | 2 +- .../hapi-fhir-spring-boot-sample-server-jersey/pom.xml | 2 +- hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml | 2 +- hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-sql-migrate/pom.xml | 2 +- hapi-fhir-storage-batch2-jobs/pom.xml | 2 +- hapi-fhir-storage-batch2-test-utilities/pom.xml | 2 +- hapi-fhir-storage-batch2/pom.xml | 2 +- hapi-fhir-storage-mdm/pom.xml | 2 +- hapi-fhir-storage-test-utilities/pom.xml | 2 +- hapi-fhir-storage/pom.xml | 2 +- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- hapi-fhir-structures-r4b/pom.xml | 2 +- hapi-fhir-structures-r5/pom.xml | 2 +- hapi-fhir-test-utilities/pom.xml | 2 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- hapi-fhir-validation-resources-dstu2.1/pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation-resources-r4b/pom.xml | 2 +- hapi-fhir-validation-resources-r5/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 2 +- hapi-tinder-test/pom.xml | 2 +- pom.xml | 2 +- tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml | 2 +- tests/hapi-fhir-base-test-mindeps-client/pom.xml | 2 +- tests/hapi-fhir-base-test-mindeps-server/pom.xml | 2 +- 79 files changed, 81 insertions(+), 81 deletions(-) diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index f5a45ad66136..67e76f525de5 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index 93ef46249d43..7e036b9bb934 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 66fde1eac1a9..ee58dc5b285a 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 10afb0b09b4e..c24b5e5ea4e5 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT pom HAPI FHIR BOM @@ -12,7 +12,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index d79de111925a..36873ef8a77d 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index ecf17562e062..7f0063c3f5a0 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index ad6bb69f5cf4..7b2e3ed7c92b 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index c3b8a50a8fdc..a7013e0413b2 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-apache-http5/pom.xml b/hapi-fhir-client-apache-http5/pom.xml index 5dd8e79fd9b9..2c288cf1054d 100644 --- a/hapi-fhir-client-apache-http5/pom.xml +++ b/hapi-fhir-client-apache-http5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index a53934d738e7..d9fd49e71245 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index cfa2400f292a..52cbf472c60b 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 65c6a24fd9e1..6d46f95dcfa1 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index 1f11c4bb8d71..7dca996c0853 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index 93815f083541..ff2327d62817 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index f46ba71aa9ba..30409babe3de 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index ec3bca24c1f9..bd1994aaf2f2 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa-hibernate-services/pom.xml b/hapi-fhir-jpa-hibernate-services/pom.xml index 428c086a6639..2a70c100669e 100644 --- a/hapi-fhir-jpa-hibernate-services/pom.xml +++ b/hapi-fhir-jpa-hibernate-services/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index 513e2aea020b..891c7b586a5f 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 3af3588e90dc..9f2c05103528 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml index fa89d228c901..b04880220908 100644 --- a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-hfql/pom.xml b/hapi-fhir-jpaserver-hfql/pom.xml index 472f2fe508a5..ed58c0f76fb1 100644 --- a/hapi-fhir-jpaserver-hfql/pom.xml +++ b/hapi-fhir-jpaserver-hfql/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-ips/pom.xml b/hapi-fhir-jpaserver-ips/pom.xml index 4e143c8ce717..d8c1f3ec8617 100644 --- a/hapi-fhir-jpaserver-ips/pom.xml +++ b/hapi-fhir-jpaserver-ips/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 32fce796d1d5..e231c06159f1 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index e58ff9af7f8e..948fdb867786 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 6a3fa73c9b9b..7f14c6886502 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 84f32710a2d0..50bd22a6524d 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu2/pom.xml b/hapi-fhir-jpaserver-test-dstu2/pom.xml index eb714f37966d..17d553edefc5 100644 --- a/hapi-fhir-jpaserver-test-dstu2/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu3/pom.xml b/hapi-fhir-jpaserver-test-dstu3/pom.xml index d6569eebd097..4d0ad737edfb 100644 --- a/hapi-fhir-jpaserver-test-dstu3/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu3/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4/pom.xml b/hapi-fhir-jpaserver-test-r4/pom.xml index bcdd2d22e273..d80ea67de958 100644 --- a/hapi-fhir-jpaserver-test-r4/pom.xml +++ b/hapi-fhir-jpaserver-test-r4/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml index f8cb7ce3d777..706e6ea6df14 100644 --- a/hapi-fhir-jpaserver-test-r4b/pom.xml +++ b/hapi-fhir-jpaserver-test-r4b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r5/pom.xml b/hapi-fhir-jpaserver-test-r5/pom.xml index 9ae03f275917..fa77cf5a5f75 100644 --- a/hapi-fhir-jpaserver-test-r5/pom.xml +++ b/hapi-fhir-jpaserver-test-r5/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 45078b4240eb..5b726fe91de0 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index cba336de8be8..fc1616c0e5df 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-repositories/pom.xml b/hapi-fhir-repositories/pom.xml index 959c45a68970..96daedb22be0 100644 --- a/hapi-fhir-repositories/pom.xml +++ b/hapi-fhir-repositories/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-cds-hooks/pom.xml b/hapi-fhir-server-cds-hooks/pom.xml index 97cccb06f8a4..dc26359fe83f 100644 --- a/hapi-fhir-server-cds-hooks/pom.xml +++ b/hapi-fhir-server-cds-hooks/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index b1b0c1a1170f..ee2f7093cb16 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index e4e5470cc5ff..3ab3d4f8d176 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index 2079aeec9647..be96e7b44ac2 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml index 5d008be3f9a2..5c6f27119a85 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml index af0bb8f9907d..15e75143f177 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ ca.uhn.hapi.fhir hapi-fhir-caching-api - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml index 6c65c7e0a199..789d4c984fb7 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml index 61e76650189e..f5edd3b93856 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml @@ -7,7 +7,7 @@ hapi-fhir ca.uhn.hapi.fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../pom.xml diff --git a/hapi-fhir-serviceloaders/pom.xml b/hapi-fhir-serviceloaders/pom.xml index f2346f70e2a5..421f1a49d1da 100644 --- a/hapi-fhir-serviceloaders/pom.xml +++ b/hapi-fhir-serviceloaders/pom.xml @@ -5,7 +5,7 @@ hapi-deployable-pom ca.uhn.hapi.fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 138626715b75..5343f47de5a6 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index 1c877f93e80a..aa9d2c864d56 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index c5e613bf8290..f68ad304f527 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index 464d47421c0b..e44f814a2f88 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index fe94f0e981fa..6dfb41568601 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 0fcd5de97b0b..70766bb5d1ba 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 7e3f23c21445..9033ea9987f4 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index 23925be7a831..9d382ba609bb 100644 --- a/hapi-fhir-sql-migrate/pom.xml +++ b/hapi-fhir-sql-migrate/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml index 5ff8a1b2d355..4b041007dd23 100644 --- a/hapi-fhir-storage-batch2-jobs/pom.xml +++ b/hapi-fhir-storage-batch2-jobs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-test-utilities/pom.xml b/hapi-fhir-storage-batch2-test-utilities/pom.xml index a7172a814bf7..6c6b14a55332 100644 --- a/hapi-fhir-storage-batch2-test-utilities/pom.xml +++ b/hapi-fhir-storage-batch2-test-utilities/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index 8b0ae50d53f9..c2586f3c8328 100644 --- a/hapi-fhir-storage-batch2/pom.xml +++ b/hapi-fhir-storage-batch2/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index 22cda489c8e4..1cad32fc4dbd 100644 --- a/hapi-fhir-storage-mdm/pom.xml +++ b/hapi-fhir-storage-mdm/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index f465302f5d02..8b68bbd6e4bd 100644 --- a/hapi-fhir-storage-test-utilities/pom.xml +++ b/hapi-fhir-storage-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index 253ba7a36af7..163abb4db7cf 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index 9c5e9ba44afa..7b65adf492cf 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index d96c71a63e4f..62ae64754e5e 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 892becf18def..aaf95b1d4373 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index f45a0838f896..284e41d99a71 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index d1da43c310bf..f201fb82b1b6 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml index da05da6eed2b..0aef3a270766 100644 --- a/hapi-fhir-structures-r4b/pom.xml +++ b/hapi-fhir-structures-r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 6284c54e945c..2ea02908f255 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index 76bcf64c13de..2a69460713f9 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 9ea51c6148c7..ad5f4d1b3b28 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index 6a34b6f99b5a..68524e60d870 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index db3793f45f94..5583b14a1076 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 39ba4d6566d0..7f5491af0eb1 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index 6e17f5ea8897..002664fc2187 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4b/pom.xml b/hapi-fhir-validation-resources-r4b/pom.xml index 2ad667edad8d..40a594ec1ad7 100644 --- a/hapi-fhir-validation-resources-r4b/pom.xml +++ b/hapi-fhir-validation-resources-r4b/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index 9340821d28c6..91cc4e0efff0 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 1732a39bc4db..64247b33c7b4 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 1948548c7350..c54f9da44688 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index f927837f4a33..71db820a74cf 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index f5858a17d999..084f4ae5fb22 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index 9da7c662cbfe..21219df3051f 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index 20f46c957cd7..08de24cc6543 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index cd20fcec18ed..9606788266e2 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 8.7.0-SNAPSHOT + 8.7.1-SNAPSHOT ../../pom.xml