From a0004c91666d21b9a350aa48b504b87cf8c892e1 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 27 Jun 2017 21:12:20 -0400 Subject: [PATCH] Fix issue in calling JPA server transactions programmatically where resources are linked by object reference and not by ID where indexes were not correctly generated. This should not affect most users. --- .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 10 ++++ .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 19 ++++--- .../jpa/dao/dstu3/FhirSystemDaoDstu3Test.java | 54 +++++++++++++++++++ src/changes/changes.xml | 5 ++ 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index dd71d3920cb..1ecbd6db105 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -334,6 +334,16 @@ public abstract class BaseHapiFhirDao implements IDao { continue; } nextId = nextValue.getReferenceElement(); + + /* + * This can only really happen if the DAO is being called + * programatically with a Bundle (not through the FHIR REST API) + * but Smile does this + */ + if (nextId.isEmpty() && nextValue.getResource() != null) { + nextId = nextValue.getResource().getIdElement(); + } + if (nextId.isEmpty() || nextId.getValue().startsWith("#")) { // This is a blank or contained resource reference continue; 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 b4017a47416..56400d4f9e5 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 @@ -273,19 +273,24 @@ public abstract class BaseHapiFhirResourceDao extends B // Notify interceptors IdDt idToDelete = entity.getIdDt(); - ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); - notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); - + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); + notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); + } + // Perform delete Date updateTime = new Date(); updateEntity(null, entity, updateTime, updateTime); // Notify JPA interceptors T resourceToDelete = toResource(myResourceType, entity, false); - theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); + if (theRequestDetails != null) { + theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); + for (IServerInterceptor next : getConfig().getInterceptors()) { + if (next instanceof IJpaServerInterceptor) { + ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); + } } } for (IServerInterceptor next : getConfig().getInterceptors()) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java index b6c9bf688d4..19ea6a484fb 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java @@ -542,6 +542,60 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest { } } + @Test + public void testTransactionWithReferenceUuid() { + Bundle request = new Bundle(); + + Patient p = new Patient(); + p.setActive(true); + p.setId(IdType.newRandomUuid()); + request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId()); + + Observation o = new Observation(); + o.getCode().setText("Some Observation"); + o.getSubject().setReference(p.getId()); + request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST); + + Bundle resp = mySystemDao.transaction(mySrd, request); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp)); + + String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue(); + assertThat(patientId, startsWith("Patient/")); + + SearchParameterMap params = new SearchParameterMap(); + params.setLoadSynchronous(true); + params.add("subject", new ReferenceParam(patientId)); + IBundleProvider found = myObservationDao.search(params); + assertEquals(1, found.size().intValue()); + } + + @Test + public void testTransactionWithReferenceResource() { + Bundle request = new Bundle(); + + Patient p = new Patient(); + p.setActive(true); + p.setId(IdType.newRandomUuid()); + request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId()); + + Observation o = new Observation(); + o.getCode().setText("Some Observation"); + o.getSubject().setResource(p); + request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST); + + Bundle resp = mySystemDao.transaction(mySrd, request); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp)); + + String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue(); + assertThat(patientId, startsWith("Patient/")); + + SearchParameterMap params = new SearchParameterMap(); + params.setLoadSynchronous(true); + params.add("subject", new ReferenceParam(patientId)); + IBundleProvider found = myObservationDao.search(params); + assertEquals(1, found.size().intValue()); + } + @Test public void testTransactionCreateInlineMatchUrlWithOneMatch() { String methodName = "testTransactionCreateInlineMatchUrlWithOneMatch"; diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2adefcf2365..913ce9ba185 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,11 @@ Prevent duplicates in $everything query response in JPA server. Thanks to @vlad-ignatov for reporting! + + Fix issue in calling JPA server transactions programmatically where resources + are linked by object reference and not by ID where indexes were not correctly + generated. This should not affect most users. +