From 8cf14c8c0ecc9f6198c178adda2bcf73f03766af Mon Sep 17 00:00:00 2001 From: James Agnew Date: Sun, 14 May 2023 21:33:32 -0400 Subject: [PATCH] Dont crash indexing contained references on Bundle (#4881) * Dont crash indexing contained references on Bundle * Add changelog --- ...bundle-with-index-contained-resources.yaml | 6 ++++ .../SearchParamExtractorService.java | 3 ++ .../fhir/jpa/dao/r4/ChainingR4SearchTest.java | 36 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4881-fix-create-bundle-with-index-contained-resources.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4881-fix-create-bundle-with-index-contained-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4881-fix-create-bundle-with-index-contained-resources.yaml new file mode 100644 index 00000000000..5796ab153e7 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4881-fix-create-bundle-with-index-contained-resources.yaml @@ -0,0 +1,6 @@ +--- +type: fix +issue: 4881 +title: "When _Index Contained References_ is enabled in the JPA server, Bundle resources could not be + stored or indexed due to an incompatibility with the default Bundle search parameters. This has been + corrected." diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java index 0718f9b4808..9a66cfb0e81 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java @@ -224,6 +224,9 @@ public class SearchParamExtractorService { @Override public IBaseResource fetchResourceAtPath(@Nonnull PathAndRef thePathAndRef) { + if (thePathAndRef.getRef() == null) { + return null; + } return findContainedResource(containedResources, thePathAndRef.getRef()); } }; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java index 042622b574c..31fecd59bdd 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.dao.r4; +import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; @@ -13,11 +14,14 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.AuditEvent; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Device; import org.hl7.fhir.r4.model.DomainResource; import org.hl7.fhir.r4.model.Encounter; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.MessageHeader; import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Patient; @@ -37,6 +41,7 @@ import java.util.List; import static org.apache.commons.lang3.StringUtils.countMatches; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.in; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -72,6 +77,37 @@ public class ChainingR4SearchTest extends BaseJpaR4Test { myStorageSettings.setIndexMissingFields(JpaStorageSettings.IndexEnabledEnum.DISABLED); } + @Test + public void testIndexSearchParamPointingToResource() { + // Setup + + myStorageSettings.setIndexOnContainedResources(true); + + Bundle inputBundle = new Bundle(); + inputBundle.setType(Bundle.BundleType.MESSAGE); + + MessageHeader msgHeader = new MessageHeader(); + msgHeader.setEvent(new Coding("http://foo", "bar", "blah")); + inputBundle.addEntry().setResource(msgHeader); + + RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Bundle", "message"); + assertEquals("Bundle.entry[0].resource", sp.getPath()); + assertThat(sp.getBase(), contains("Bundle")); + assertEquals(RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, sp.getStatus()); + + // Test + myBundleDao.create(inputBundle, mySrd); + + // Verify - We'll check that the right indexes got written, but the main test is that + // the create step didn't crash + runInTransaction(()->{ + assertEquals(0, myResourceIndexedSearchParamStringDao.count()); + assertEquals(1, myResourceIndexedSearchParamTokenDao.count()); + assertEquals(0, myResourceLinkDao.count()); + }); + } + + @Test public void testShouldResolveATwoLinkChainWithStandAloneResourcesWithoutContainedResourceIndexing() throws Exception {