From 320a0d895f8710e8708b3f7f16041b03f627b0f2 Mon Sep 17 00:00:00 2001 From: Nathan Doef Date: Tue, 24 Jan 2023 10:58:11 -0500 Subject: [PATCH] Fix ConceptMap processing in transaction (#4442) * failing test * fix * only store ConceptMap once * remove new myPreliminaryTransactionWrite flag and use thePerformIndexing Co-authored-by: nathaniel.doef --- ...ocessing-conceptmap-using-transaction.yaml | 6 +++ .../jpa/dao/JpaResourceDaoConceptMap.java | 4 +- .../jpa/term/TermConceptMappingSvcImpl.java | 3 ++ .../provider/r4/ResourceProviderR4Test.java | 54 ++++++++++++++++++- 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/4457-error-processing-conceptmap-using-transaction.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/4457-error-processing-conceptmap-using-transaction.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/4457-error-processing-conceptmap-using-transaction.yaml new file mode 100644 index 00000000000..bc69a4cc0a0 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/4457-error-processing-conceptmap-using-transaction.yaml @@ -0,0 +1,6 @@ +--- +type: fix +issue: 4457 +jira: SMILE-5685 +title: "Previously, when a `ConceptMap` was created or updated using a transaction `Bundle`, the transaction failed with +error code `HAPI-0550: could not execute statement`. This has been fixed." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoConceptMap.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoConceptMap.java index 3afe6ca95cf..cda03b4ef4b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoConceptMap.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/JpaResourceDaoConceptMap.java @@ -55,7 +55,9 @@ public class JpaResourceDaoConceptMap extends JpaResour boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry); - if (!retVal.isUnchangedInCurrentOperation()) { + boolean entityWasSaved = !retVal.isUnchangedInCurrentOperation(); + boolean shouldProcessUpdate = entityWasSaved && thePerformIndexing; + if (shouldProcessUpdate) { if (retVal.getDeleted() == null) { ConceptMap conceptMap = myVersionCanonicalizer.conceptMapToCanonical(theResource); myTermConceptMappingSvc.storeTermConceptMapAndChildren(retVal, conceptMap); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermConceptMappingSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermConceptMappingSvcImpl.java index d663b9e608c..c907b2ea3c5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermConceptMappingSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermConceptMappingSvcImpl.java @@ -227,6 +227,7 @@ public class TermConceptMappingSvcImpl implements ITermConceptMappingSvc { termConceptMapGroup.setSourceVersion(group.getSourceVersion()); termConceptMapGroup.setTarget(groupTarget); termConceptMapGroup.setTargetVersion(group.getTargetVersion()); + termConceptMap.getConceptMapGroups().add(termConceptMapGroup); termConceptMapGroup = myConceptMapGroupDao.save(termConceptMapGroup); if (group.hasElement()) { @@ -239,6 +240,7 @@ public class TermConceptMappingSvcImpl implements ITermConceptMappingSvc { termConceptMapGroupElement.setConceptMapGroup(termConceptMapGroup); termConceptMapGroupElement.setCode(element.getCode()); termConceptMapGroupElement.setDisplay(element.getDisplay()); + termConceptMapGroup.getConceptMapGroupElements().add(termConceptMapGroupElement); termConceptMapGroupElement = myConceptMapGroupElementDao.save(termConceptMapGroupElement); if (element.hasTarget()) { @@ -252,6 +254,7 @@ public class TermConceptMappingSvcImpl implements ITermConceptMappingSvc { termConceptMapGroupElementTarget.setCode(elementTarget.getCode()); termConceptMapGroupElementTarget.setDisplay(elementTarget.getDisplay()); termConceptMapGroupElementTarget.setEquivalence(elementTarget.getEquivalence()); + termConceptMapGroupElement.getConceptMapGroupElementTargets().add(termConceptMapGroupElementTarget); myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget); if (++codesSaved % 250 == 0) { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index dac28cdaba5..086dc8f91ac 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -15,6 +15,7 @@ import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.term.ZipCollectionBuilder; import ca.uhn.fhir.jpa.test.config.TestR4Config; import ca.uhn.fhir.jpa.util.QueryParameterUtils; +import ca.uhn.fhir.model.api.StorageResponseCodeEnum; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; @@ -93,6 +94,7 @@ import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.Condition; import org.hl7.fhir.r4.model.Coverage; import org.hl7.fhir.r4.model.DateTimeType; @@ -166,7 +168,6 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Nonnull; -import javax.sql.DataSource; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -7657,6 +7658,57 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { assertEquals(0, results.getEntry().size()); } + @Test + public void testConceptMapInTransactionBundle() { + ConceptMap conceptMap = new ConceptMap(); + conceptMap.setUrl("http://www.acme.org"); + conceptMap.setStatus(Enumerations.PublicationStatus.ACTIVE); + + ConceptMap.ConceptMapGroupComponent group = conceptMap.addGroup(); + group.setSource("http://www.some-source.ca/codeSystem/CS"); + group.setTarget("http://www.some-target.ca/codeSystem/CS"); + + ConceptMap.SourceElementComponent source = group.addElement(); + source.setCode("TEST1"); + ConceptMap.TargetElementComponent target = source.addTarget(); + target.setCode("TEST2"); + target.setDisplay("TEST CODE"); + target.setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL); + + Bundle requestBundle = new Bundle(); + requestBundle.setType(BundleType.TRANSACTION); + Bundle.BundleEntryRequestComponent request = new Bundle.BundleEntryRequestComponent(); + request.setUrl("/ConceptMap?url=http://www.acme.org"); + request.setMethod(HTTPVerb.POST); + requestBundle.addEntry().setResource(conceptMap).setRequest(request); + + Bundle responseBundle = myClient.transaction().withBundle(requestBundle).execute(); + OperationOutcome oo = (OperationOutcome) responseBundle.getEntry().get(0).getResponse().getOutcome(); + assertEquals(StorageResponseCodeEnum.SUCCESSFUL_CREATE.name(), oo.getIssueFirstRep().getDetails().getCodingFirstRep().getCode()); + assertEquals(StorageResponseCodeEnum.SYSTEM, oo.getIssueFirstRep().getDetails().getCodingFirstRep().getSystem()); + assertEquals(1, responseBundle.getEntry().size()); + + IdType id = new IdType(responseBundle.getEntry().get(0).getResponse().getLocationElement()); + ConceptMap savedConceptMap = (ConceptMap) myClient.read().resource("ConceptMap").withId(id).execute(); + assertEquals(conceptMap.getUrl(), savedConceptMap.getUrl()); + assertEquals(conceptMap.getStatus(), savedConceptMap.getStatus()); + assertEquals(1, savedConceptMap.getGroup().size()); + + ConceptMap.ConceptMapGroupComponent savedGroup = savedConceptMap.getGroup().get(0); + assertEquals(group.getSource(), savedGroup.getSource()); + assertEquals(group.getTarget(), savedGroup.getTarget()); + assertEquals(1, savedGroup.getElement().size()); + + ConceptMap.SourceElementComponent savedSource = savedGroup.getElement().get(0); + assertEquals(source.getCode(), savedSource.getCode()); + assertEquals(1, source.getTarget().size()); + + ConceptMap.TargetElementComponent savedTarget = savedSource.getTarget().get(0); + assertEquals(target.getCode(), savedTarget.getCode()); + assertEquals(target.getDisplay(), savedTarget.getDisplay()); + assertEquals(target.getEquivalence(), savedTarget.getEquivalence()); + } + @Nonnull private IIdType createNewPatientWithHistory() { String TEST_SYSTEM_NAME = "testHistoryRewrite";