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. +