From e69fe05e96575c07e59276c3ba9060ab97f333a2 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 29 Mar 2023 19:57:57 -0400 Subject: [PATCH] Re-enable "Flush SP cache after SP change" (#4635) * Revert "Revert "Flush SP cache after SP change (#4566)" (#4614)" This reverts commit 9492999ed6346cff3679e10ef9ef35894abc1eca. * Additions for performance * HAPI version bump * Test logging improvement * Test fixes * Test fix * Test fix * Compile fix * Fix * License headers * Test fix --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- .../java/ca/uhn/fhir/util/BundleBuilder.java | 22 +- .../java/ca/uhn/fhir/util/TaskChunker.java | 53 +++++ .../ca/uhn/fhir/util/TaskChunkerTest.java | 53 +++++ 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/hapi-fhir-cli-jpaserver/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 2 +- .../canonical/VersionCanonicalizer.java | 39 +++- .../canonical/VersionCanonicalizerTest.java | 12 + hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 2 +- .../4566-flush-sp-cache-after-sp-change.yaml | 6 + hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jpa/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 2 +- .../dao/JpaResourceDaoSearchParameter.java | 25 +++ ...rchParamWithInlineReferencesExtractor.java | 6 +- .../ca/uhn/fhir/jpa/util/QueryChunker.java | 17 +- .../pom.xml | 2 +- hapi-fhir-jpaserver-ips/pom.xml | 2 +- hapi-fhir-jpaserver-mdm/pom.xml | 2 +- hapi-fhir-jpaserver-model/pom.xml | 2 +- .../fhir/jpa/model/entity/ResourceTable.java | 4 +- 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 +- .../FhirResourceDaoR4ConcurrentWriteTest.java | 2 +- ...ourceDaoR4SearchCustomSearchParamTest.java | 6 +- .../r4/MultitenantBatchOperationR4Test.java | 2 +- ...sourceProviderCustomSearchParamR4Test.java | 4 - 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-server-mdm/pom.xml | 2 +- hapi-fhir-server-openapi/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- .../hapi-fhir-caching-api/pom.xml | 2 +- .../hapi-fhir-caching-caffeine/pom.xml | 4 +- .../hapi-fhir-caching-guava/pom.xml | 2 +- .../hapi-fhir-caching-testing/pom.xml | 2 +- hapi-fhir-serviceloaders/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../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 +- .../pom.xml | 2 +- hapi-fhir-storage-batch2/pom.xml | 2 +- hapi-fhir-storage-cr/pom.xml | 2 +- hapi-fhir-storage-mdm/pom.xml | 2 +- hapi-fhir-storage-test-utilities/pom.xml | 2 +- hapi-fhir-storage/pom.xml | 2 +- .../BaseRequestPartitionHelperSvc.java | 27 ++- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- .../uhn/fhir/util/BundleBuilderDstu2Test.java | 212 ++++++++++++++++++ hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- ...lderTest.java => BundleBuilderR4Test.java} | 6 +- 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 +- .../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 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 94 files changed, 534 insertions(+), 120 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/TaskChunker.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/util/TaskChunkerTest.java create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4566-flush-sp-cache-after-sp-change.yaml create mode 100644 hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/BundleBuilderDstu2Test.java rename hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/{BundleBuilderTest.java => BundleBuilderR4Test.java} (98%) diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index 9f1cea95131..1b7c182e078 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index c12f4590109..5818dfe25a1 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 883720ac38c..09ddbf0237c 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleBuilder.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleBuilder.java index ad5866f8492..97ac2506828 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleBuilder.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleBuilder.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.util; import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeElementDefinition; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.model.primitive.IdDt; import org.apache.commons.lang3.Validate; @@ -85,8 +86,13 @@ public class BundleBuilder { mySearchChild = myEntryDef.getChildByName("search"); mySearchDef = mySearchChild.getChildByName("search"); - myMetaChild = myBundleDef.getChildByName("meta"); - myMetaDef = myMetaChild.getChildByName("meta"); + if (myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { + myMetaChild = myBundleDef.getChildByName("meta"); + myMetaDef = myMetaChild.getChildByName("meta"); + } else { + myMetaChild = null; + myMetaDef = null; + } myEntryResourceChild = myEntryDef.getChildByName("resource"); myEntryFullUrlChild = myEntryDef.getChildByName("fullUrl"); @@ -346,12 +352,16 @@ public class BundleBuilder { } /** - * Creates new search instance for the specified entry + * Creates new search instance for the specified entry. + * Note that this method does not work for DSTU2 model classes, it will only work + * on DSTU3+. * * @param entry Entry to create search instance for * @return Returns the search instance */ public IBaseBackboneElement addSearch(IBase entry) { + Validate.isTrue(myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3), "This method may only be called for FHIR version DSTU3 and above"); + IBase searchInstance = mySearchDef.newInstance(); mySearchChild.getMutator().setValue(entry, searchInstance); return (IBaseBackboneElement) searchInstance; @@ -400,7 +410,13 @@ public class BundleBuilder { return (T) myBundle; } + /** + * Note that this method does not work for DSTU2 model classes, it will only work + * on DSTU3+. + */ public BundleBuilder setMetaField(String theFieldName, IBase theFieldValue) { + Validate.isTrue(myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3), "This method may only be called for FHIR version DSTU3 and above"); + BaseRuntimeChildDefinition.IMutator mutator = myMetaDef.getChildByName(theFieldName).getMutator(); mutator.setValue(myBundle.getMeta(), theFieldValue); return this; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/TaskChunker.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/TaskChunker.java new file mode 100644 index 00000000000..d10ad74594e --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/TaskChunker.java @@ -0,0 +1,53 @@ +package ca.uhn.fhir.util; + +/*- + * #%L + * HAPI FHIR - Core Library + * %% + * Copyright (C) 2014 - 2023 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +/** + * This utility takes an input collection, breaks it up into chunks of a + * given maximum chunk size, and then passes those chunks to a consumer for + * processing. Use this to break up large tasks into smaller tasks. + * + * @since 6.6.0 + * @param The type for the chunks + */ +public class TaskChunker { + + public void chunk(Collection theInput, int theChunkSize, Consumer> theBatchConsumer) { + List input; + if (theInput instanceof List) { + input = (List) theInput; + } else { + input = new ArrayList<>(theInput); + } + for (int i = 0; i < input.size(); i += theChunkSize) { + int to = i + theChunkSize; + to = Math.min(to, input.size()); + List batch = input.subList(i, to); + theBatchConsumer.accept(batch); + } + } + +} diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/TaskChunkerTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/TaskChunkerTest.java new file mode 100644 index 00000000000..811608c0b8a --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/TaskChunkerTest.java @@ -0,0 +1,53 @@ +package ca.uhn.fhir.util; + +import com.google.common.collect.Lists; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.annotation.Nonnull; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.IntStream; + +@ExtendWith(MockitoExtension.class) +public class TaskChunkerTest { + + @Mock + private Consumer> myConsumer; + @Captor + private ArgumentCaptor> myConsumerCaptor; + + @Test + public void testChunk() { + // Setup + List input = newIntRangeList(0, 35); + + // Execute + new TaskChunker().chunk(input, 10, myConsumer); + + // Verify + verify(myConsumer, times(4)).accept(myConsumerCaptor.capture()); + assertEquals(newIntRangeList(0, 10), myConsumerCaptor.getAllValues().get(0)); + assertEquals(newIntRangeList(10, 20), myConsumerCaptor.getAllValues().get(1)); + assertEquals(newIntRangeList(20, 30), myConsumerCaptor.getAllValues().get(2)); + assertEquals(newIntRangeList(30, 35), myConsumerCaptor.getAllValues().get(3)); + + } + + @Nonnull + private static List newIntRangeList(int startInclusive, int endExclusive) { + List input = IntStream.range(startInclusive, endExclusive).boxed().toList(); + return input; + } + +} diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 41d6c376b9a..a99eaf1df80 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -4,14 +4,14 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT pom HAPI FHIR BOM ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index bf5f7d3be73..ce1e98b167d 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-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 bfaa6125453..eb6a202b53f 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 - 6.5.7-SNAPSHOT + 6.5.8-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 881490acf4e..7ea8223ec77 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index b6217c969d5..395e1c3804f 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../../hapi-deployable-pom diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index 0de209d19e2..b10e5c6a525 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index a35869d97c1..d286cbfe899 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index dadd943595d..46e3d673a8a 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 404b0c668f5..59fc6c3391f 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizer.java b/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizer.java index 6d66774be87..6681948f0fb 100644 --- a/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizer.java +++ b/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizer.java @@ -180,6 +180,10 @@ public class VersionCanonicalizer { return myStrategy.searchParameterToCanonical(theSearchParameter); } + public IBaseResource searchParameterFromCanonical(SearchParameter theSearchParameter) { + return myStrategy.searchParameterFromCanonical(theSearchParameter); + } + public IBaseParameters parametersFromCanonical(Parameters theParameters) { return myStrategy.parametersFromCanonical(theParameters); } @@ -245,6 +249,8 @@ public class VersionCanonicalizer { org.hl7.fhir.r5.model.ValueSet valueSetToValidatorCanonical(IBaseResource theResource); org.hl7.fhir.r5.model.CodeSystem codeSystemToValidatorCanonical(IBaseResource theResource); + + IBaseResource searchParameterFromCanonical(SearchParameter theResource); } private static class Dstu2Strategy implements IStrategy { @@ -374,7 +380,7 @@ public class VersionCanonicalizer { @Override public IBaseResource valueSetFromValidatorCanonical(org.hl7.fhir.r5.model.ValueSet theResource) { Resource converted = VersionConvertorFactory_10_50.convertResource(theResource, ADVISOR_10_50); - return reencodeToHl7Org(converted); + return reencodeFromHl7Org(converted); } @Override @@ -395,6 +401,12 @@ public class VersionCanonicalizer { return (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_10_50.convertResource(reencoded, ADVISOR_10_50); } + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + Resource resource = VersionConvertorFactory_10_50.convertResource(theResource, ADVISOR_10_50); + return reencodeFromHl7Org(resource); + } + private Resource reencodeToHl7Org(IBaseResource theInput) { if (myHl7OrgStructures) { return (Resource) theInput; @@ -487,6 +499,11 @@ public class VersionCanonicalizer { public org.hl7.fhir.r5.model.CodeSystem codeSystemToValidatorCanonical(IBaseResource theResource) { return (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_14_50.convertResource((org.hl7.fhir.dstu2016may.model.Resource) theResource, ADVISOR_14_50); } + + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + return VersionConvertorFactory_14_50.convertResource(theResource, ADVISOR_14_50); + } } private static class Dstu3Strategy implements IStrategy { @@ -565,6 +582,11 @@ public class VersionCanonicalizer { public org.hl7.fhir.r5.model.CodeSystem codeSystemToValidatorCanonical(IBaseResource theResource) { return (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_30_50.convertResource((org.hl7.fhir.dstu3.model.Resource) theResource, ADVISOR_30_50); } + + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + return VersionConvertorFactory_30_50.convertResource(theResource, ADVISOR_30_50); + } } private static class R4Strategy implements IStrategy { @@ -643,6 +665,11 @@ public class VersionCanonicalizer { return (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_40_50.convertResource((org.hl7.fhir.r4.model.Resource) theResource, ADVISOR_40_50); } + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + return VersionConvertorFactory_40_50.convertResource(theResource, ADVISOR_40_50); + } + } private static class R4BStrategy implements IStrategy { @@ -729,6 +756,11 @@ public class VersionCanonicalizer { return (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_43_50.convertResource((org.hl7.fhir.r4b.model.Resource) theResource, ADVISOR_43_50); } + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + return VersionConvertorFactory_43_50.convertResource(theResource, ADVISOR_43_50); + } + } @@ -809,6 +841,11 @@ public class VersionCanonicalizer { return (org.hl7.fhir.r5.model.CodeSystem) theResource; } + @Override + public IBaseResource searchParameterFromCanonical(SearchParameter theResource) { + return theResource; + } + } diff --git a/hapi-fhir-converter/src/test/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizerTest.java b/hapi-fhir-converter/src/test/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizerTest.java index ed28c56cb25..2aa21b3c84a 100644 --- a/hapi-fhir-converter/src/test/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizerTest.java +++ b/hapi-fhir-converter/src/test/java/ca/uhn/hapi/converters/canonical/VersionCanonicalizerTest.java @@ -3,7 +3,9 @@ package ca.uhn.hapi.converters.canonical; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.model.dstu2.composite.CodingDt; import org.hl7.fhir.instance.model.api.IBaseCoding; +import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r5.model.SearchParameter; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -19,4 +21,14 @@ class VersionCanonicalizerTest { assertEquals("dstuSystem", convertedCoding.getSystem()); } + @Test + public void testFromCanonicalSearchParameter() { + VersionCanonicalizer canonicalizer = new VersionCanonicalizer(FhirVersionEnum.DSTU2); + + SearchParameter inputR5 = new SearchParameter(); + inputR5.setUrl("http://foo"); + ca.uhn.fhir.model.dstu2.resource.SearchParameter outputDstu2 = (ca.uhn.fhir.model.dstu2.resource.SearchParameter) canonicalizer.searchParameterFromCanonical(inputR5); + assertEquals("http://foo", outputDstu2.getUrl()); + } + } diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index a2c8e6100e4..34b5ae46560 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index 4a3d1d713b0..76a4092c1ae 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4566-flush-sp-cache-after-sp-change.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4566-flush-sp-cache-after-sp-change.yaml new file mode 100644 index 00000000000..82c981df95f --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4566-flush-sp-cache-after-sp-change.yaml @@ -0,0 +1,6 @@ +--- +type: add +issue: 4566 +title: "When creating or modifying a SearchParameter in the JPA server, the local SearchParameter cache + is now immediately flushed. This should help with situations such as tests where a SearchParameter + is created and then used before the scheduled cache refresh typically occurs." diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index 27d77c671fd..8e631445293 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index 7279a1438e8..51905769ddc 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index e06684395af..5a975911383 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-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 df744700159..15ff024a435 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 268e680831b..b81328ae895 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -1025,7 +1025,7 @@ public abstract class BaseHapiFhirResourceDao extends B mySearchParamRegistry.requestRefresh(); } - private boolean shouldSkipReindex(RequestDetails theRequestDetails) { + protected final boolean shouldSkipReindex(RequestDetails theRequestDetails) { if (theRequestDetails == null) { return false; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoSearchParameter.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoSearchParameter.java index 89230025d09..2d64ea920b8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoSearchParameter.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoSearchParameter.java @@ -28,12 +28,17 @@ import com.google.common.annotations.VisibleForTesting; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r5.model.CodeType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; public class JpaResourceDaoSearchParameter extends BaseHapiFhirResourceDao implements IFhirResourceDaoSearchParameter { + private final AtomicBoolean myCacheReloadTriggered = new AtomicBoolean(false); + @Autowired private VersionCanonicalizer myVersionCanonicalizer; @@ -41,6 +46,26 @@ public class JpaResourceDaoSearchParameter extends Base private SearchParameterDaoValidator mySearchParameterDaoValidator; protected void reindexAffectedResources(T theResource, RequestDetails theRequestDetails) { + + /* + * After we commit, flush the search parameter cache. This only helps on the + * local server (ie in a cluster the other servers won't be flushed) but + * the cache is short anyhow, and flushing locally is better than nothing. + * Many use cases where you would create a search parameter and immediately + * try to use it tend to be on single-server setups anyhow, e.g. unit tests + */ + if (!shouldSkipReindex(theRequestDetails)) { + if (!myCacheReloadTriggered.getAndSet(true)) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + myCacheReloadTriggered.set(false); + mySearchParamRegistry.forceRefresh(); + } + }); + } + } + // N.B. Don't do this on the canonicalized version Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java index c4bcfb1fd33..e13ff5972e6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java @@ -40,6 +40,7 @@ import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.NotFoundPid; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ResourceSearchParams; import com.google.common.annotations.VisibleForTesting; @@ -185,7 +186,10 @@ public class SearchParamWithInlineReferencesExtractor extends BaseSearchParamWit } String msg = myFhirContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue(), searchParameterId); - throw new PreconditionFailedException(Msg.code(1093) + msg); + + // Use ResourceVersionConflictException here because the HapiTransactionService + // catches this and can retry it if needed + throw new ResourceVersionConflictException(Msg.code(1093) + msg); } } ourLog.debug("Persisting unique index: {}", next); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/QueryChunker.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/QueryChunker.java index b624d9ccf48..6a2d79cae7a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/QueryChunker.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/QueryChunker.java @@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.util; import ca.uhn.fhir.jpa.search.builder.SearchBuilder; +import ca.uhn.fhir.util.TaskChunker; import java.util.ArrayList; import java.util.Collection; @@ -32,24 +33,10 @@ import java.util.function.Consumer; * if it's lots of IDs. I suppose maybe we should be doing this as a join anyhow * but this should work too. Sigh. */ -public class QueryChunker { +public class QueryChunker extends TaskChunker { public void chunk(Collection theInput, Consumer> theBatchConsumer) { chunk(theInput, SearchBuilder.getMaximumPageSize(), theBatchConsumer); } - public void chunk(Collection theInput, int theChunkSize, Consumer> theBatchConsumer) { - List input; - if (theInput instanceof List) { - input = (List) theInput; - } else { - input = new ArrayList<>(theInput); - } - for (int i = 0; i < input.size(); i += theChunkSize) { - int to = i + theChunkSize; - to = Math.min(to, input.size()); - List batch = input.subList(i, to); - theBatchConsumer.accept(batch); - } - } } diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml index 71ec68659d0..155f910781b 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-ips/pom.xml b/hapi-fhir-jpaserver-ips/pom.xml index 4f8ce2d090d..a5299f65b0c 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 1bed4465bf8..7c7e3cf63df 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 1542b0e382b..32bda9446b2 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java index 771955b23af..cc7a33b61f9 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java @@ -818,7 +818,9 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas } private void populateId(IIdType retVal) { - if (getTransientForcedId() != null) { + if (myFhirId != null) { + retVal.setValue(getResourceType() + '/' + myFhirId + '/' + Constants.PARAM_HISTORY + '/' + getVersion()); + } else if (getTransientForcedId() != null) { // Avoid a join query if possible retVal.setValue(getResourceType() + '/' + getTransientForcedId() + '/' + Constants.PARAM_HISTORY + '/' + getVersion()); } else if (getForcedId() == null) { diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 390f6a55a4a..919bc44e3d2 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 9499987dc63..31057f5d5cf 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 - 6.5.7-SNAPSHOT + 6.5.8-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 2c45137f444..b47403a8aed 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 - 6.5.7-SNAPSHOT + 6.5.8-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 25eb94536ee..6e3d678efaa 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 - 6.5.7-SNAPSHOT + 6.5.8-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 dd53b28ac7b..9440a00dd7f 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java index 6ac3af5f7a5..7f0603d11d8 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java @@ -474,7 +474,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test { assertThat(e.getMessage(), containsString("duplicate unique index matching query: Patient?gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale")); } catch (ResourceVersionConflictException e) { // expected - This is as a result of the unique SP - assertThat(e.getMessage(), containsString("would have resulted in a duplicate value for a unique index")); + assertThat(e.getMessage(), containsString("duplicate")); } }; Future future = myExecutor.submit(task); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java index c6a8c78b1c2..406b1fc398d 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java @@ -1744,6 +1744,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test @Test public void testCompositeWithInvalidTarget() { + // Setup SearchParameter sp = new SearchParameter(); sp.addBase("Patient"); sp.setCode("myDoctor"); @@ -1752,14 +1753,15 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test sp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE); sp.addComponent() .setDefinition("http://foo"); - mySearchParameterDao.create(sp); IAnonymousInterceptor interceptor = mock(IAnonymousInterceptor.class); myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.JPA_PERFTRACE_WARNING, interceptor); try { - mySearchParamRegistry.forceRefresh(); + // Test + mySearchParameterDao.create(sp); + // Verify ArgumentCaptor paramsCaptor = ArgumentCaptor.forClass(HookParams.class); verify(interceptor, times(1)).invoke(any(), paramsCaptor.capture()); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java index 17cd6cdc530..53d457be3ae 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java @@ -228,6 +228,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv IIdType obsCancelledB = doCreateResource(reindexTestHelper.buildObservationWithAlleleExtension(Observation.ObservationStatus.CANCELLED)); reindexTestHelper.createAlleleSearchParameter(); + ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames()); // The searchparam value is on the observation, but it hasn't been indexed yet myTenantClientInterceptor.setTenantId(TENANT_A); @@ -255,7 +256,6 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv myBatch2JobHelper.awaitJobCompletion(jobId.getValue()); // validate - ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames()); logAllTokenIndexes(); List alleleObservationIds = reindexTestHelper.getAlleleObservationIds(myClient); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java index 261c04a8a69..22f2e3e19df 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java @@ -401,10 +401,6 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE); mySearchParameterDao.create(fooSp, mySrd); - myCaptureQueriesListener.clear(); - mySearchParamRegistry.forceRefresh(); - myCaptureQueriesListener.logAllQueriesForCurrentThread(); - Patient pat = new Patient(); pat.setGender(AdministrativeGender.MALE); IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless(); diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml index 3c0c389eafb..4ec28024f50 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 - 6.5.7-SNAPSHOT + 6.5.8-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 7993d6a802b..dc6d9004053 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 - 6.5.7-SNAPSHOT + 6.5.8-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 7acd9ef12a7..1c1d73a5bcb 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index c3d5f21a2a7..1f402d2e2b8 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index cefcb5182ec..fbc55be0278 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index 489f8883358..a6b7820b943 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index d642ac9af9a..ca546a930b7 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-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 2ae77976e80..7bf0def22b2 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 - 6.5.7-SNAPSHOT + 6.5.8-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 80237bad884..1c714597adc 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml @@ -20,7 +20,7 @@ ca.uhn.hapi.fhir hapi-fhir-caching-api - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT com.github.ben-manes.caffeine diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml index 7e16a136021..d4b4fb9eef3 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 - 6.5.7-SNAPSHOT + 6.5.8-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 c8943686e1e..431ae23be57 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../../pom.xml diff --git a/hapi-fhir-serviceloaders/pom.xml b/hapi-fhir-serviceloaders/pom.xml index dca1c429b21..fb1f0f59a34 100644 --- a/hapi-fhir-serviceloaders/pom.xml +++ b/hapi-fhir-serviceloaders/pom.xml @@ -5,7 +5,7 @@ hapi-deployable-pom ca.uhn.hapi.fhir - 6.5.7-SNAPSHOT + 6.5.8-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 912ee0d7aa4..3d08b37a1a8 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 - 6.5.7-SNAPSHOT + 6.5.8-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 695afca4418..aeca5576baf 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 - 6.5.7-SNAPSHOT + 6.5.8-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 a70090d9cf6..d80bae417aa 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT hapi-fhir-spring-boot-sample-client-okhttp 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 713a4b26866..9564ad68070 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT hapi-fhir-spring-boot-sample-server-jersey 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 e46269bfc71..d770448c31e 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT hapi-fhir-spring-boot-samples 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 feae5a0513c..dc9f2ef620d 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 9d029521b08..facbc3d28e9 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index b40305e994b..efeb350e52f 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 - 6.5.7-SNAPSHOT + 6.5.8-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 2e77f2682d1..937c77e9ca2 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-batch2-test-utilities/pom.xml b/hapi-fhir-storage-batch2-test-utilities/pom.xml index c15ef77d66d..e529da84be2 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index 42b256577f9..6dc1ae63e3d 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-cr/pom.xml b/hapi-fhir-storage-cr/pom.xml index 19ad7e8570c..318071ec63e 100644 --- a/hapi-fhir-storage-cr/pom.xml +++ b/hapi-fhir-storage-cr/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index 283166a8ef8..0dcdf83e306 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index b744cf08696..7b277fc3371 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index d1ae3d20ef5..d197455d9ec 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/partition/BaseRequestPartitionHelperSvc.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/partition/BaseRequestPartitionHelperSvc.java index f67b96ae382..b8abb469ee4 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/partition/BaseRequestPartitionHelperSvc.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/partition/BaseRequestPartitionHelperSvc.java @@ -138,17 +138,26 @@ public abstract class BaseRequestPartitionHelperSvc implements IRequestPartition public RequestPartitionId determineGenericPartitionForRequest(RequestDetails theRequestDetails) { RequestPartitionId retVal = null; - if (hasHooks(Pointcut.STORAGE_PARTITION_IDENTIFY_ANY, myInterceptorBroadcaster, theRequestDetails)) { - // Interceptor call: STORAGE_PARTITION_IDENTIFY_ANY - HookParams params = new HookParams() - .add(RequestDetails.class, theRequestDetails) - .addIfMatchesType(ServletRequestDetails.class, theRequestDetails); - retVal = (RequestPartitionId) doCallHooksAndReturnObject(myInterceptorBroadcaster, theRequestDetails, Pointcut.STORAGE_PARTITION_IDENTIFY_ANY, params); - - if (retVal != null) { - retVal = validateNormalizeAndNotifyHooksForRead(retVal, theRequestDetails, null); + if (myPartitionSettings.isPartitioningEnabled()) { + if (theRequestDetails instanceof SystemRequestDetails) { + SystemRequestDetails systemRequestDetails = (SystemRequestDetails) theRequestDetails; + retVal = systemRequestDetails.getRequestPartitionId(); } + } + if (retVal == null) { + if (hasHooks(Pointcut.STORAGE_PARTITION_IDENTIFY_ANY, myInterceptorBroadcaster, theRequestDetails)) { + // Interceptor call: STORAGE_PARTITION_IDENTIFY_ANY + HookParams params = new HookParams() + .add(RequestDetails.class, theRequestDetails) + .addIfMatchesType(ServletRequestDetails.class, theRequestDetails); + retVal = (RequestPartitionId) doCallHooksAndReturnObject(myInterceptorBroadcaster, theRequestDetails, Pointcut.STORAGE_PARTITION_IDENTIFY_ANY, params); + + if (retVal != null) { + retVal = validateNormalizeAndNotifyHooksForRead(retVal, theRequestDetails, null); + } + + } } return retVal; diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index ad776e66c0c..066b36b5c17 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 1dadf69eee6..dbdca017748 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/BundleBuilderDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/BundleBuilderDstu2Test.java new file mode 100644 index 00000000000..0d1c4143a6e --- /dev/null +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/BundleBuilderDstu2Test.java @@ -0,0 +1,212 @@ +package ca.uhn.fhir.util; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.dstu2.resource.Bundle; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; +import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; +import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum; +import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.fail; + + +public class BundleBuilderDstu2Test { + + private static final Logger ourLog = LoggerFactory.getLogger(BundleBuilderDstu2Test.class); + private FhirContext myFhirContext = FhirContext.forDstu2Cached(); + private Date myCheckDate; + + @BeforeEach + public void initDate() { + Calendar cal = GregorianCalendar.getInstance(); + cal.set(2021, 0, 0); + myCheckDate = cal.getTime(); + } + + + @Test + public void testAddEntryUpdate() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + Patient patient = new Patient(); + patient.setId("http://foo/Patient/123"); + patient.setActive(true); + builder.addTransactionUpdateEntry(patient); + + Bundle bundle = (Bundle) builder.getBundle(); + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(BundleTypeEnum.TRANSACTION, bundle.getTypeElement().getValueAsEnum()); + assertEquals(1, bundle.getEntry().size()); + assertSame(patient, bundle.getEntry().get(0).getResource()); + assertEquals("http://foo/Patient/123", bundle.getEntry().get(0).getFullUrl()); + assertEquals("Patient/123", bundle.getEntry().get(0).getRequest().getUrl()); + assertEquals(HTTPVerbEnum.PUT, bundle.getEntry().get(0).getRequest().getMethodElement().getValueAsEnum()); + } + + @Test + public void testNewPrimitive() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + IPrimitiveType datePrimitive = builder.newPrimitive("instant", myCheckDate); + assertNotNull(datePrimitive); + assertEquals(myCheckDate, datePrimitive.getValue()); + } + + @Test + public void testSettingBundleFields() { + String uuid = UUID.randomUUID().toString(); + + BundleBuilder builder = new BundleBuilder(myFhirContext); + try { + builder.setBundleField("id", uuid); + fail(); + } catch (NullPointerException e) { + assertEquals("Unable to find field id", e.getMessage()); + + } + + try { + builder.setMetaField("lastUpdated", builder.newPrimitive("instant", myCheckDate)); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("This method may only be called for FHIR version DSTU3 and above", e.getMessage()); + } + + } + + + @Test + public void testAddEntryUpdateConditional() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + Patient patient = new Patient(); + patient.setId("http://foo/Patient/123"); + patient.setActive(true); + builder.addTransactionUpdateEntry(patient).conditional("Patient?active=true"); + + Bundle bundle = (Bundle) builder.getBundle(); + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(BundleTypeEnum.TRANSACTION, bundle.getTypeElement().getValueAsEnum()); + assertEquals(1, bundle.getEntry().size()); + assertSame(patient, bundle.getEntry().get(0).getResource()); + assertEquals("http://foo/Patient/123", bundle.getEntry().get(0).getFullUrl()); + assertEquals("Patient?active=true", bundle.getEntry().get(0).getRequest().getUrl()); + assertEquals(HTTPVerbEnum.PUT, bundle.getEntry().get(0).getRequest().getMethodElement().getValueAsEnum()); + } + + @Test + public void testSearchHandling() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + IBase entry = builder.addEntry(); + assertNotNull(entry); + + try { + builder.addSearch(entry); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("This method may only be called for FHIR version DSTU3 and above", e.getMessage()); + } + } + + @Test + public void testAddToEntry() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + IBase entry = builder.addEntry(); + + Patient patient = new Patient(); + patient.setActive(true); + builder.addToEntry(entry, "resource", patient); + + Bundle bundle = (Bundle) builder.getBundle(); + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(1, bundle.getEntry().size()); + } + + @Test + public void testAddEntryCreate() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + Patient patient = new Patient(); + patient.setActive(true); + builder.addTransactionCreateEntry(patient); + + Bundle bundle = (Bundle) builder.getBundle(); + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(BundleTypeEnum.TRANSACTION, bundle.getTypeElement().getValueAsEnum()); + assertEquals(1, bundle.getEntry().size()); + assertSame(patient, bundle.getEntry().get(0).getResource()); + assertEquals(null, bundle.getEntry().get(0).getFullUrl()); + assertEquals("Patient", bundle.getEntry().get(0).getRequest().getUrl()); + assertEquals(HTTPVerbEnum.POST, bundle.getEntry().get(0).getRequest().getMethodElement().getValueAsEnum()); + } + + @Test + public void testAddEntryDelete() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + Patient patient = new Patient(); + patient.setActive(true); + patient.setId("123"); + builder.addTransactionDeleteEntry(patient); + builder.addTransactionDeleteEntry("Patient", "123"); + Bundle bundle = (Bundle) builder.getBundle(); + + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(BundleTypeEnum.TRANSACTION, bundle.getTypeElement().getValueAsEnum()); + assertEquals(2, bundle.getEntry().size()); + + //Check the IBaseresource style entry + assertNull(bundle.getEntry().get(0).getResource()); + assertEquals("Patient/123", bundle.getEntry().get(0).getRequest().getUrl()); + assertEquals(HTTPVerbEnum.DELETE, bundle.getEntry().get(0).getRequest().getMethodElement().getValueAsEnum()); + + //Check the resourcetype + id style entry. + assertNull(bundle.getEntry().get(1).getResource()); + assertEquals("Patient/123", bundle.getEntry().get(1).getRequest().getUrl()); + assertEquals(HTTPVerbEnum.DELETE, bundle.getEntry().get(1).getRequest().getMethodElement().getValueAsEnum()); + + + } + + @Test + public void testAddEntryCreateConditional() { + BundleBuilder builder = new BundleBuilder(myFhirContext); + + Patient patient = new Patient(); + patient.setActive(true); + builder.addTransactionCreateEntry(patient).conditional("Patient?active=true"); + + Bundle bundle = (Bundle) builder.getBundle(); + ourLog.debug("Bundle:\n{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + assertEquals(BundleTypeEnum.TRANSACTION, bundle.getTypeElement().getValueAsEnum()); + assertEquals(1, bundle.getEntry().size()); + assertSame(patient, bundle.getEntry().get(0).getResource()); + assertEquals(null, bundle.getEntry().get(0).getFullUrl()); + assertEquals("Patient", bundle.getEntry().get(0).getRequest().getUrl()); + assertEquals("Patient?active=true", bundle.getEntry().get(0).getRequest().getIfNoneExist()); + assertEquals(HTTPVerbEnum.POST, bundle.getEntry().get(0).getRequest().getMethodElement().getValueAsEnum()); + } + +} diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 655b535a2cd..8aa760dfab6 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 - 6.5.7-SNAPSHOT + 6.5.8-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 62718524c9e..73edc71cc41 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index 086b3268a84..ceb20fc4ec0 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderR4Test.java similarity index 98% rename from hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderTest.java rename to hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderR4Test.java index ce439b30e70..2f2371be67b 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/BundleBuilderR4Test.java @@ -24,10 +24,10 @@ import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals; -public class BundleBuilderTest { +public class BundleBuilderR4Test { - private static final Logger ourLog = LoggerFactory.getLogger(BundleBuilderTest.class); - private FhirContext myFhirContext = FhirContext.forR4(); + private static final Logger ourLog = LoggerFactory.getLogger(BundleBuilderR4Test.class); + private FhirContext myFhirContext = FhirContext.forR4Cached(); private Date myCheckDate; @BeforeEach diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml index 8f468a1a8f5..d51ebda76ae 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 85f73add583..d6621fd2841 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index 21ed8dddb7b..d3d0acdffbf 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 7d09c9a607e..cdd792a2ce3 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index c6d14a902b9..15d181a865a 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 - 6.5.7-SNAPSHOT + 6.5.8-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 4d89a741970..c3d4c9fbeef 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 - 6.5.7-SNAPSHOT + 6.5.8-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 a97fb51b9b2..a1e8fda645c 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 - 6.5.7-SNAPSHOT + 6.5.8-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 1257a6ec8da..905ea60c365 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 - 6.5.7-SNAPSHOT + 6.5.8-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 80dd9c6fa35..a9d496a3785 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 - 6.5.7-SNAPSHOT + 6.5.8-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 65988c56a1a..b4286969d75 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 8cbf0df796f..c43a1655cb7 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 95b56e91ef0..fed176ffb19 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 760a337bece..f139afbd6a9 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2f6b27ba00f..1febbf2698f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. https://hapifhir.io diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index 2613268fa5c..22ef9bfaad8 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.5.7-SNAPSHOT + 6.5.8-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 106f0cbb89d..8e59b0fdc44 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 - 6.5.7-SNAPSHOT + 6.5.8-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 3e85d2eda4e..133c3fc38cb 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 - 6.5.7-SNAPSHOT + 6.5.8-SNAPSHOT ../../pom.xml