JPA server transactions sometimes created an incorrect resource reference if a resource being saved contained references that had a display value but not an actual reference. Thanks to David Hay for reporting!
This commit is contained in:
parent
649c6807cb
commit
2bc1950bc1
|
@ -42,6 +42,10 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetai
|
||||||
|
|
||||||
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> {
|
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> {
|
||||||
|
|
||||||
|
public FhirResourceDaoPatientDstu2() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
|
|
|
@ -460,6 +460,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
||||||
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||||
for (BaseResourceReferenceDt nextRef : allRefs) {
|
for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||||
IdDt nextId = nextRef.getReference();
|
IdDt nextId = nextRef.getReference();
|
||||||
|
if (!nextId.hasIdPart()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (idSubstitutions.containsKey(nextId)) {
|
if (idSubstitutions.containsKey(nextId)) {
|
||||||
IdDt newId = idSubstitutions.get(nextId);
|
IdDt newId = idSubstitutions.get(nextId);
|
||||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||||
|
|
|
@ -470,6 +470,9 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
||||||
for (IBaseReference nextRef : allRefs) {
|
for (IBaseReference nextRef : allRefs) {
|
||||||
IIdType nextId = nextRef.getReferenceElement();
|
IIdType nextId = nextRef.getReferenceElement();
|
||||||
|
if (!nextId.hasIdPart()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (idSubstitutions.containsKey(nextId)) {
|
if (idSubstitutions.containsKey(nextId)) {
|
||||||
IdType newId = idSubstitutions.get(nextId);
|
IdType newId = idSubstitutions.get(nextId);
|
||||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||||
|
|
|
@ -18,7 +18,6 @@ import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
@ -41,6 +40,7 @@ import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Appointment;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.ConceptMap;
|
import ca.uhn.fhir.model.dstu2.resource.ConceptMap;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Device;
|
import ca.uhn.fhir.model.dstu2.resource.Device;
|
||||||
|
@ -87,6 +87,9 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
|
||||||
@Qualifier("myConceptMapDaoDstu2")
|
@Qualifier("myConceptMapDaoDstu2")
|
||||||
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myAppointmentDaoDstu2")
|
||||||
|
protected IFhirResourceDao<Appointment> myAppointmentDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myBundleDaoDstu2")
|
@Qualifier("myBundleDaoDstu2")
|
||||||
protected IFhirResourceDao<Bundle> myBundleDao;
|
protected IFhirResourceDao<Bundle> myBundleDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -43,6 +43,7 @@ import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Appointment;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
|
||||||
|
@ -66,19 +67,12 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() {
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReindexing() {
|
public void testReindexing() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -151,7 +145,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertEquals(Long.valueOf(2), entity.getIndexStatus());
|
assertEquals(Long.valueOf(2), entity.getIndexStatus());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSystemMetaOperation() {
|
public void testSystemMetaOperation() {
|
||||||
|
|
||||||
|
@ -240,7 +234,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertEquals("http://profile/2", profiles.get(0).getValue());
|
assertEquals("http://profile/2", profiles.get(0).getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionBatchWithFailingRead() {
|
public void testTransactionBatchWithFailingRead() {
|
||||||
String methodName = "testTransactionBatchWithFailingRead";
|
String methodName = "testTransactionBatchWithFailingRead";
|
||||||
|
@ -287,6 +281,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertThat(respEntry.getStatus(), startsWith("404"));
|
assertThat(respEntry.getStatus(), startsWith("404"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||||
|
@ -329,7 +324,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertEquals("1", o.getId().getVersionIdPart());
|
assertEquals("1", o.getId().getVersionIdPart());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||||
|
@ -929,6 +924,25 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Bundle testTransactionOrderingCreateBundle(String methodName, int pass, IdDt patientPlaceholderId) {
|
||||||
|
Bundle req = new Bundle();
|
||||||
|
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=" + methodName);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.getSubject().setReference(patientPlaceholderId);
|
||||||
|
obs.addIdentifier().setValue(methodName);
|
||||||
|
obs.getCode().setText(methodName + pass);
|
||||||
|
req.addEntry().setResource(obs).getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Observation?identifier=" + methodName);
|
||||||
|
|
||||||
|
Patient pat = new Patient();
|
||||||
|
pat.addIdentifier().setValue(methodName);
|
||||||
|
pat.addName().addFamily(methodName + pass);
|
||||||
|
req.addEntry().setResource(pat).setFullUrl(patientPlaceholderId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
||||||
|
|
||||||
|
req.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=" + methodName);
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
private void testTransactionOrderingValidateResponse(int pass, Bundle resp) {
|
private void testTransactionOrderingValidateResponse(int pass, Bundle resp) {
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
assertEquals(4, resp.getEntry().size());
|
assertEquals(4, resp.getEntry().size());
|
||||||
|
@ -957,25 +971,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertThat(respGetBundle.getLink("self").getUrl(), endsWith("/Patient?identifier=testTransactionOrdering"));
|
assertThat(respGetBundle.getLink("self").getUrl(), endsWith("/Patient?identifier=testTransactionOrdering"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bundle testTransactionOrderingCreateBundle(String methodName, int pass, IdDt patientPlaceholderId) {
|
|
||||||
Bundle req = new Bundle();
|
|
||||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=" + methodName);
|
|
||||||
|
|
||||||
Observation obs = new Observation();
|
|
||||||
obs.getSubject().setReference(patientPlaceholderId);
|
|
||||||
obs.addIdentifier().setValue(methodName);
|
|
||||||
obs.getCode().setText(methodName + pass);
|
|
||||||
req.addEntry().setResource(obs).getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Observation?identifier=" + methodName);
|
|
||||||
|
|
||||||
Patient pat = new Patient();
|
|
||||||
pat.addIdentifier().setValue(methodName);
|
|
||||||
pat.addName().addFamily(methodName + pass);
|
|
||||||
req.addEntry().setResource(pat).setFullUrl(patientPlaceholderId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
|
||||||
|
|
||||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=" + methodName);
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionReadAndSearch() {
|
public void testTransactionReadAndSearch() {
|
||||||
String methodName = "testTransactionReadAndSearch";
|
String methodName = "testTransactionReadAndSearch";
|
||||||
|
@ -1308,6 +1303,87 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From a message from David Hay
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithAppointments() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addName().addFamily("family");
|
||||||
|
final IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
//@formatter:on
|
||||||
|
String input = "{\n" +
|
||||||
|
" \"resourceType\": \"Bundle\",\n" +
|
||||||
|
" \"type\": \"transaction\",\n" +
|
||||||
|
" \"entry\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"resource\": {\n" +
|
||||||
|
" \"resourceType\": \"Appointment\",\n" +
|
||||||
|
" \"status\": \"pending\",\n" +
|
||||||
|
" \"type\": {\"text\": \"Cardiology\"},\n" +
|
||||||
|
" \"description\": \"Investigate Angina\",\n" +
|
||||||
|
" \"start\": \"2016-04-30T18:48:29+12:00\",\n" +
|
||||||
|
" \"end\": \"2016-04-30T19:03:29+12:00\",\n" +
|
||||||
|
" \"minutesDuration\": 15,\n" +
|
||||||
|
" \"participant\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"actor\": {\"display\": \"Clarence cardiology clinic\"},\n" +
|
||||||
|
" \"status\": \"accepted\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"actor\": {\"reference\": \"Patient/" + id.getIdPart() + "\"},\n" +
|
||||||
|
" \"status\": \"accepted\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"text\": {\n" +
|
||||||
|
" \"status\": \"generated\",\n" +
|
||||||
|
" \"div\": \"<div><div>Investigate Angina<\\/div><div>Clarence cardiology clinic<\\/div><\\/div>\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"request\": {\n" +
|
||||||
|
" \"method\": \"POST\",\n" +
|
||||||
|
" \"url\": \"Appointment\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"resource\": {\n" +
|
||||||
|
" \"resourceType\": \"Appointment\",\n" +
|
||||||
|
" \"status\": \"pending\",\n" +
|
||||||
|
" \"type\": {\"text\": \"GP Visit\"},\n" +
|
||||||
|
" \"description\": \"Routine checkup\",\n" +
|
||||||
|
" \"start\": \"2016-05-03T18:48:29+12:00\",\n" +
|
||||||
|
" \"end\": \"2016-05-03T19:03:29+12:00\",\n" +
|
||||||
|
" \"minutesDuration\": 15,\n" +
|
||||||
|
" \"participant\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"actor\": {\"display\": \"Dr Dave\"},\n" +
|
||||||
|
" \"status\": \"accepted\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"actor\": {\"reference\": \"Patient/" + id.getIdPart() + "\"},\n" +
|
||||||
|
" \"status\": \"accepted\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"text\": {\n" +
|
||||||
|
" \"status\": \"generated\",\n" +
|
||||||
|
" \"div\": \"<div><div>Routine checkup<\\/div><div>Dr Dave<\\/div><\\/div>\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"request\": {\n" +
|
||||||
|
" \"method\": \"POST\",\n" +
|
||||||
|
" \"url\": \"Appointment\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}";
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
Bundle inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, input);
|
||||||
|
Bundle outputBundle = mySystemDao.transaction(mySrd, inputBundle);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(outputBundle));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithInvalidType() {
|
public void testTransactionWithInvalidType() {
|
||||||
Bundle request = new Bundle();
|
Bundle request = new Bundle();
|
||||||
|
@ -1324,6 +1400,65 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithNullReference() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addName().addFamily("family");
|
||||||
|
final IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Bundle inputBundle = new Bundle();
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Patient app0 = new Patient();
|
||||||
|
app0.addName().addFamily("NEW PATIENT");
|
||||||
|
String placeholderId0 = IdDt.newRandomUuid().getValue();
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app0)
|
||||||
|
.setFullUrl(placeholderId0)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerbEnum.POST)
|
||||||
|
.setUrl("Patient");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Appointment app1 = new Appointment();
|
||||||
|
app1.addParticipant().getActor().setReference(id);
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app1)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerbEnum.POST)
|
||||||
|
.setUrl("Appointment");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Appointment app2 = new Appointment();
|
||||||
|
app2.addParticipant().getActor().setDisplay("NO REF");
|
||||||
|
app2.addParticipant().getActor().setDisplay("YES REF").setReference(placeholderId0);
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app2)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerbEnum.POST)
|
||||||
|
.setUrl("Appointment");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
Bundle outputBundle = mySystemDao.transaction(mySrd, inputBundle);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(outputBundle));
|
||||||
|
|
||||||
|
assertEquals(3, outputBundle.getEntry().size());
|
||||||
|
IdDt id0 = new IdDt(outputBundle.getEntry().get(0).getResponse().getLocation());
|
||||||
|
IdDt id1 = new IdDt(outputBundle.getEntry().get(1).getResponse().getLocation());
|
||||||
|
IdDt id2 = new IdDt(outputBundle.getEntry().get(2).getResponse().getLocation());
|
||||||
|
|
||||||
|
app2 = myAppointmentDao.read(id2, mySrd);
|
||||||
|
assertEquals("NO REF", app2.getParticipant().get(0).getActor().getDisplay().getValue());
|
||||||
|
assertEquals(null, app2.getParticipant().get(0).getActor().getReference().getValue());
|
||||||
|
assertEquals("YES REF", app2.getParticipant().get(1).getActor().getDisplay().getValue());
|
||||||
|
assertEquals(id0.toUnqualifiedVersionless().getValue(), app2.getParticipant().get(1).getActor().getReference().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
|
@ -1377,6 +1512,46 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertNotEquals(medOrderId1, medOrderId2);
|
assertNotEquals(medOrderId1, medOrderId2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithRelativeOidIds() throws Exception {
|
||||||
|
Bundle res = new Bundle();
|
||||||
|
res.setType(BundleTypeEnum.TRANSACTION);
|
||||||
|
|
||||||
|
Patient p1 = new Patient();
|
||||||
|
p1.setId("urn:oid:0.1.2.3");
|
||||||
|
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
||||||
|
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
||||||
|
|
||||||
|
Observation o1 = new Observation();
|
||||||
|
o1.setId("cid:observation1");
|
||||||
|
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
||||||
|
o1.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Observation o2 = new Observation();
|
||||||
|
o2.setId("cid:observation2");
|
||||||
|
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
||||||
|
o2.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, res);
|
||||||
|
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
||||||
|
assertEquals(3, resp.getEntry().size());
|
||||||
|
|
||||||
|
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdDt(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
|
||||||
|
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
||||||
|
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
||||||
|
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||||
|
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
|
@ -1479,46 +1654,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithRelativeOidIds() throws Exception {
|
|
||||||
Bundle res = new Bundle();
|
|
||||||
res.setType(BundleTypeEnum.TRANSACTION);
|
|
||||||
|
|
||||||
Patient p1 = new Patient();
|
|
||||||
p1.setId("urn:oid:0.1.2.3");
|
|
||||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
|
||||||
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
|
||||||
o1.setId("cid:observation1");
|
|
||||||
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
|
||||||
o1.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
|
|
||||||
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
|
||||||
|
|
||||||
Observation o2 = new Observation();
|
|
||||||
o2.setId("cid:observation2");
|
|
||||||
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
|
||||||
o2.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
|
|
||||||
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, res);
|
|
||||||
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
|
||||||
|
|
||||||
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
|
||||||
assertEquals(3, resp.getEntry().size());
|
|
||||||
|
|
||||||
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdDt(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
|
|
||||||
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
|
||||||
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
|
||||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
|
||||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is not the correct way to do it, but we'll allow it to be lenient
|
* This is not the correct way to do it, but we'll allow it to be lenient
|
||||||
*/
|
*/
|
||||||
|
@ -1562,4 +1697,9 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.Search;
|
import org.hibernate.search.jpa.Search;
|
||||||
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
|
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
|
||||||
|
import org.hl7.fhir.dstu3.model.Appointment;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
|
@ -90,12 +91,15 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myCodeSystemDaoDstu3")
|
@Qualifier("myAppointmentDaoDstu3")
|
||||||
protected IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
protected IFhirResourceDao<Appointment> myAppointmentDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myBundleDaoDstu3")
|
@Qualifier("myBundleDaoDstu3")
|
||||||
protected IFhirResourceDao<Bundle> myBundleDao;
|
protected IFhirResourceDao<Bundle> myBundleDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myCodeSystemDaoDstu3")
|
||||||
|
protected IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myConceptMapDaoDstu3")
|
@Qualifier("myConceptMapDaoDstu3")
|
||||||
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -139,14 +143,14 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myNamingSystemDaoDstu3")
|
@Qualifier("myNamingSystemDaoDstu3")
|
||||||
protected IFhirResourceDao<NamingSystem> myNamingSystemDao;
|
protected IFhirResourceDao<NamingSystem> myNamingSystemDao;
|
||||||
@Autowired
|
|
||||||
@Qualifier("myObservationDaoDstu3")
|
|
||||||
protected IFhirResourceDao<Observation> myObservationDao;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myOrganizationDaoDstu3")
|
@Qualifier("myObservationDaoDstu3")
|
||||||
protected IFhirResourceDao<Organization> myOrganizationDao;
|
protected IFhirResourceDao<Observation> myObservationDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("myOrganizationDaoDstu3")
|
||||||
|
protected IFhirResourceDao<Organization> myOrganizationDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myPatientDaoDstu3")
|
@Qualifier("myPatientDaoDstu3")
|
||||||
protected IFhirResourceDaoPatient<Patient> myPatientDao;
|
protected IFhirResourceDaoPatient<Patient> myPatientDao;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.hl7.fhir.dstu3.model.Appointment;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryRequestComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryRequestComponent;
|
||||||
|
@ -58,6 +59,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
|
@ -77,6 +79,64 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithNullReference() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addName().addFamily("family");
|
||||||
|
final IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Bundle inputBundle = new Bundle();
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Patient app0 = new Patient();
|
||||||
|
app0.addName().addFamily("NEW PATIENT");
|
||||||
|
String placeholderId0 = IdDt.newRandomUuid().getValue();
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app0)
|
||||||
|
.setFullUrl(placeholderId0)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerb.POST)
|
||||||
|
.setUrl("Patient");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Appointment app1 = new Appointment();
|
||||||
|
app1.addParticipant().getActor().setReference(id.getValue());
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app1)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerb.POST)
|
||||||
|
.setUrl("Appointment");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Appointment app2 = new Appointment();
|
||||||
|
app2.addParticipant().getActor().setDisplay("NO REF");
|
||||||
|
app2.addParticipant().getActor().setDisplay("YES REF").setReference(placeholderId0);
|
||||||
|
inputBundle
|
||||||
|
.addEntry()
|
||||||
|
.setResource(app2)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerb.POST)
|
||||||
|
.setUrl("Appointment");
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
Bundle outputBundle = mySystemDao.transaction(mySrd, inputBundle);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(outputBundle));
|
||||||
|
|
||||||
|
assertEquals(3, outputBundle.getEntry().size());
|
||||||
|
IdDt id0 = new IdDt(outputBundle.getEntry().get(0).getResponse().getLocation());
|
||||||
|
IdDt id2 = new IdDt(outputBundle.getEntry().get(2).getResponse().getLocation());
|
||||||
|
|
||||||
|
app2 = myAppointmentDao.read(id2, mySrd);
|
||||||
|
assertEquals("NO REF", app2.getParticipant().get(0).getActor().getDisplay());
|
||||||
|
assertEquals(null, app2.getParticipant().get(0).getActor().getReference());
|
||||||
|
assertEquals("YES REF", app2.getParticipant().get(1).getActor().getDisplay());
|
||||||
|
assertEquals(id0.toUnqualifiedVersionless().getValue(), app2.getParticipant().get(1).getActor().getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReindexing() {
|
public void testReindexing() {
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
Note that existing databases will need to modify index "IDX_FORCEDID" as
|
Note that existing databases will need to modify index "IDX_FORCEDID" as
|
||||||
it is no longer unique, and perform a reindexing pass.
|
it is no longer unique, and perform a reindexing pass.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
JPA server transactions sometimes created an incorrect resource reference
|
||||||
|
if a resource being saved contained references that had a display value but
|
||||||
|
not an actual reference. Thanks to David Hay for reporting!
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="1.5" date="2016-04-20">
|
<release version="1.5" date="2016-04-20">
|
||||||
<action type="fix" issue="339">
|
<action type="fix" issue="339">
|
||||||
|
|
Loading…
Reference in New Issue