Allow JPA server to restore resources and link to them in a single
transaction
This commit is contained in:
parent
cc9c8dfa80
commit
ba8795ed0f
|
@ -1253,6 +1253,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
IBaseResource oldResource = toResource(entity, false);
|
IBaseResource oldResource = toResource(entity, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark the entity as not deleted - This is also done in the actual updateInternal()
|
||||||
|
* method later on so it usually doesn't matter whether we do it here, but in the
|
||||||
|
* case of a transaction with multiple PUTs we don't get there until later so
|
||||||
|
* having this here means that a transaction can have a reference in one
|
||||||
|
* resource to another resource in the same transaction that is being
|
||||||
|
* un-deleted by the transaction. Wacky use case, sure. But it's real.
|
||||||
|
*
|
||||||
|
* See SystemProviderR4Test#testTransactionReSavesPreviouslyDeletedResources
|
||||||
|
* for a test that needs this.
|
||||||
|
*/
|
||||||
|
entity.setDeleted(null);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we aren't indexing, that means we're doing this inside a transaction.
|
* If we aren't indexing, that means we're doing this inside a transaction.
|
||||||
* The transaction will do the actual storage to the database a bit later on,
|
* The transaction will do the actual storage to the database a bit later on,
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.provider;
|
package ca.uhn.fhir.jpa.provider;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.junit.Assert.*;
|
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
|
||||||
|
import ca.uhn.fhir.jpa.rp.dstu2.*;
|
||||||
import java.io.InputStream;
|
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||||
import java.nio.charset.StandardCharsets;
|
import ca.uhn.fhir.model.dstu2.resource.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
@ -17,46 +30,32 @@ import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
|
import java.io.InputStream;
|
||||||
import ca.uhn.fhir.jpa.rp.dstu2.*;
|
import java.nio.charset.StandardCharsets;
|
||||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.*;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
import static org.hamcrest.Matchers.*;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.model.primitive.*;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu2Test.class);
|
||||||
private static RestfulServer myRestServer;
|
private static RestfulServer myRestServer;
|
||||||
private static IGenericClient ourClient;
|
private static IGenericClient ourClient;
|
||||||
private static FhirContext ourCtx;
|
private static FhirContext ourCtx;
|
||||||
private static CloseableHttpClient ourHttpClient;
|
private static CloseableHttpClient ourHttpClient;
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu2Test.class);
|
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static String ourServerBase;
|
private static String ourServerBase;
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
ourServer.stop();
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeStartServer() throws Exception {
|
public void beforeStartServer() throws Exception {
|
||||||
if (myRestServer == null) {
|
if (myRestServer == null) {
|
||||||
|
@ -72,9 +71,23 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
||||||
organizationRp.setDao(myOrganizationDao);
|
organizationRp.setDao(myOrganizationDao);
|
||||||
|
|
||||||
|
LocationResourceProvider locationRp = new LocationResourceProvider();
|
||||||
|
locationRp.setDao(myLocationDao);
|
||||||
|
|
||||||
|
BinaryResourceProvider binaryRp = new BinaryResourceProvider();
|
||||||
|
binaryRp.setDao(myBinaryDao);
|
||||||
|
|
||||||
|
DiagnosticReportResourceProvider diagnosticReportRp = new DiagnosticReportResourceProvider();
|
||||||
|
diagnosticReportRp.setDao(myDiagnosticReportDao);
|
||||||
|
DiagnosticOrderResourceProvider diagnosticOrderRp = new DiagnosticOrderResourceProvider();
|
||||||
|
diagnosticOrderRp.setDao(myDiagnosticOrderDao);
|
||||||
|
PractitionerResourceProvider practitionerRp = new PractitionerResourceProvider();
|
||||||
|
practitionerRp.setDao(myPractitionerDao);
|
||||||
|
|
||||||
|
|
||||||
RestfulServer restServer = new RestfulServer(ourCtx);
|
RestfulServer restServer = new RestfulServer(ourCtx);
|
||||||
restServer.setPagingProvider(new FifoMemoryPagingProvider(10).setDefaultPageSize(10));
|
restServer.setPagingProvider(new FifoMemoryPagingProvider(10).setDefaultPageSize(10));
|
||||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
|
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, binaryRp, locationRp, diagnosticReportRp, diagnosticOrderRp, practitionerRp);
|
||||||
|
|
||||||
restServer.setPlainProviders(mySystemProvider);
|
restServer.setPlainProviders(mySystemProvider);
|
||||||
|
|
||||||
|
@ -157,10 +170,10 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
ourLog.info(response);
|
ourLog.info(response);
|
||||||
assertThat(response, not(containsString("_format")));
|
assertThat(response, not(containsString("_format")));
|
||||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
Bundle responseBundle = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
Bundle responseBundle = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||||
assertEquals(BundleTypeEnum.SEARCH_RESULTS, responseBundle.getTypeElement().getValueAsEnum());
|
assertEquals(BundleTypeEnum.SEARCH_RESULTS, responseBundle.getTypeElement().getValueAsEnum());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
http.close();
|
http.close();
|
||||||
}
|
}
|
||||||
|
@ -179,10 +192,10 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation=Propagation.NEVER)
|
@Transactional(propagation = Propagation.NEVER)
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestKeywords() throws Exception {
|
public void testSuggestKeywords() throws Exception {
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addName().addFamily("testSuggest");
|
patient.addName().addFamily("testSuggest");
|
||||||
IIdType ptId = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
IIdType ptId = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
@ -197,21 +210,21 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
obs.getSubject().setReference(ptId);
|
obs.getSubject().setReference(ptId);
|
||||||
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
|
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
|
||||||
myObservationDao.update(obs, mySrd);
|
myObservationDao.update(obs, mySrd);
|
||||||
|
|
||||||
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
|
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
|
||||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||||
try {
|
try {
|
||||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
|
|
||||||
Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
|
Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
|
||||||
assertEquals(2, parameters.getParameter().size());
|
assertEquals(2, parameters.getParameter().size());
|
||||||
assertEquals("keyword", parameters.getParameter().get(0).getPart().get(0).getName());
|
assertEquals("keyword", parameters.getParameter().get(0).getPart().get(0).getName());
|
||||||
assertEquals(new StringDt("ZXCVBNM"), parameters.getParameter().get(0).getPart().get(0).getValue());
|
assertEquals(new StringDt("ZXCVBNM"), parameters.getParameter().get(0).getPart().get(0).getValue());
|
||||||
assertEquals("score", parameters.getParameter().get(0).getPart().get(1).getName());
|
assertEquals("score", parameters.getParameter().get(0).getPart().get(1).getName());
|
||||||
assertEquals(new DecimalDt("1.0"), parameters.getParameter().get(0).getPart().get(1).getValue());
|
assertEquals(new DecimalDt("1.0"), parameters.getParameter().get(0).getPart().get(1).getValue());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
http.close();
|
http.close();
|
||||||
}
|
}
|
||||||
|
@ -227,7 +240,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
obs.getSubject().setReference(ptId);
|
obs.getSubject().setReference(ptId);
|
||||||
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
|
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
|
||||||
myObservationDao.create(obs, mySrd);
|
myObservationDao.create(obs, mySrd);
|
||||||
|
|
||||||
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords");
|
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords");
|
||||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||||
try {
|
try {
|
||||||
|
@ -238,7 +251,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
http.close();
|
http.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything");
|
get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything");
|
||||||
http = ourHttpClient.execute(get);
|
http = ourHttpClient.execute(get);
|
||||||
try {
|
try {
|
||||||
|
@ -269,6 +282,44 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
assertEquals("get-resource-counts", op.getCode());
|
assertEquals("get-resource-counts", op.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionReSavesPreviouslyDeletedResources() throws IOException {
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
ourLog.info("** Beginning pass {}", i);
|
||||||
|
|
||||||
|
Bundle input = myFhirCtx.newJsonParser().parseResource(Bundle.class, IOUtils.toString(getClass().getResourceAsStream("/dstu2/createdeletebundle.json"), Charsets.UTF_8));
|
||||||
|
ourClient.transaction().withBundle(input).execute();
|
||||||
|
|
||||||
|
myPatientDao.read(new IdType("Patient/Patient1063259"));
|
||||||
|
|
||||||
|
deleteAllOfType("Binary");
|
||||||
|
deleteAllOfType("Location");
|
||||||
|
deleteAllOfType("DiagnosticReport");
|
||||||
|
deleteAllOfType("Observation");
|
||||||
|
deleteAllOfType("DiagnosticOrder");
|
||||||
|
deleteAllOfType("Practitioner");
|
||||||
|
deleteAllOfType("Patient");
|
||||||
|
deleteAllOfType("Organization");
|
||||||
|
|
||||||
|
try {
|
||||||
|
myPatientDao.read(new IdType("Patient/Patient1063259"));
|
||||||
|
fail();
|
||||||
|
} catch (ResourceGoneException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteAllOfType(String theType) {
|
||||||
|
BundleUtil.toListOfResources(myFhirCtx, ourClient.search().forResource(theType).execute())
|
||||||
|
.forEach(t -> {
|
||||||
|
ourClient.delete().resourceById(t.getIdElement()).execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionFromBundle() throws Exception {
|
public void testTransactionFromBundle() throws Exception {
|
||||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
||||||
|
@ -372,20 +423,20 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionSearch() throws Exception {
|
public void testTransactionSearch() throws Exception {
|
||||||
for (int i = 0; i < 20; i ++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addName().addFamily("PATIENT_" + i);
|
p.addName().addFamily("PATIENT_" + i);
|
||||||
myPatientDao.create(p, mySrd);
|
myPatientDao.create(p, mySrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bundle req = new Bundle();
|
Bundle req = new Bundle();
|
||||||
req.setType(BundleTypeEnum.TRANSACTION);
|
req.setType(BundleTypeEnum.TRANSACTION);
|
||||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?");
|
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?");
|
||||||
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
||||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
assertEquals(1, resp.getEntry().size());
|
assertEquals(1, resp.getEntry().size());
|
||||||
Bundle respSub = (Bundle)resp.getEntry().get(0).getResource();
|
Bundle respSub = (Bundle) resp.getEntry().get(0).getResource();
|
||||||
assertEquals("self", respSub.getLink().get(0).getRelation());
|
assertEquals("self", respSub.getLink().get(0).getRelation());
|
||||||
assertEquals(ourServerBase + "/Patient", respSub.getLink().get(0).getUrl());
|
assertEquals(ourServerBase + "/Patient", respSub.getLink().get(0).getUrl());
|
||||||
assertEquals("next", respSub.getLink().get(1).getRelation());
|
assertEquals("next", respSub.getLink().get(1).getRelation());
|
||||||
|
@ -396,20 +447,20 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCount() throws Exception {
|
public void testTransactionCount() throws Exception {
|
||||||
for (int i = 0; i < 20; i ++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addName().addFamily("PATIENT_" + i);
|
p.addName().addFamily("PATIENT_" + i);
|
||||||
myPatientDao.create(p, mySrd);
|
myPatientDao.create(p, mySrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bundle req = new Bundle();
|
Bundle req = new Bundle();
|
||||||
req.setType(BundleTypeEnum.TRANSACTION);
|
req.setType(BundleTypeEnum.TRANSACTION);
|
||||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?_summary=count");
|
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?_summary=count");
|
||||||
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
||||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
assertEquals(1, resp.getEntry().size());
|
assertEquals(1, resp.getEntry().size());
|
||||||
Bundle respSub = (Bundle)resp.getEntry().get(0).getResource();
|
Bundle respSub = (Bundle) resp.getEntry().get(0).getResource();
|
||||||
assertEquals(20, respSub.getTotal().intValue());
|
assertEquals(20, respSub.getTotal().intValue());
|
||||||
assertEquals(0, respSub.getEntry().size());
|
assertEquals(0, respSub.getEntry().size());
|
||||||
}
|
}
|
||||||
|
@ -423,9 +474,16 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||||
} finally {
|
} finally {
|
||||||
IOUtils.closeQuietly(http);;
|
IOUtils.closeQuietly(http);
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@ package ca.uhn.fhir.jpa.provider.r4;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
||||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.ObservationResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.*;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.OrganizationResourceProvider;
|
|
||||||
import ca.uhn.fhir.jpa.rp.r4.PatientResourceProvider;
|
|
||||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
@ -17,8 +15,10 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
@ -42,6 +42,7 @@ import org.junit.*;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -88,8 +89,21 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
||||||
organizationRp.setDao(myOrganizationDao);
|
organizationRp.setDao(myOrganizationDao);
|
||||||
|
|
||||||
|
LocationResourceProvider locationRp = new LocationResourceProvider();
|
||||||
|
locationRp.setDao(myLocationDao);
|
||||||
|
|
||||||
|
BinaryResourceProvider binaryRp = new BinaryResourceProvider();
|
||||||
|
binaryRp.setDao(myBinaryDao);
|
||||||
|
|
||||||
|
DiagnosticReportResourceProvider diagnosticReportRp = new DiagnosticReportResourceProvider();
|
||||||
|
diagnosticReportRp.setDao(myDiagnosticReportDao);
|
||||||
|
ServiceRequestResourceProvider diagnosticOrderRp = new ServiceRequestResourceProvider();
|
||||||
|
diagnosticOrderRp.setDao(myServiceRequestDao);
|
||||||
|
PractitionerResourceProvider practitionerRp = new PractitionerResourceProvider();
|
||||||
|
practitionerRp.setDao(myPractitionerDao);
|
||||||
|
|
||||||
RestfulServer restServer = new RestfulServer(ourCtx);
|
RestfulServer restServer = new RestfulServer(ourCtx);
|
||||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
|
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, locationRp, binaryRp, diagnosticReportRp, diagnosticOrderRp, practitionerRp);
|
||||||
|
|
||||||
restServer.setPlainProviders(mySystemProvider);
|
restServer.setPlainProviders(mySystemProvider);
|
||||||
|
|
||||||
|
@ -385,6 +399,45 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());
|
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionReSavesPreviouslyDeletedResources() throws IOException {
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
ourLog.info("** Beginning pass {}", i);
|
||||||
|
|
||||||
|
Bundle input = myFhirCtx.newJsonParser().parseResource(Bundle.class, IOUtils.toString(getClass().getResourceAsStream("/r4/createdeletebundle.json"), Charsets.UTF_8));
|
||||||
|
ourClient.transaction().withBundle(input).execute();
|
||||||
|
|
||||||
|
myPatientDao.read(new IdType("Patient/Patient1063259"));
|
||||||
|
|
||||||
|
deleteAllOfType("Binary");
|
||||||
|
deleteAllOfType("Location");
|
||||||
|
deleteAllOfType("DiagnosticReport");
|
||||||
|
deleteAllOfType("Observation");
|
||||||
|
deleteAllOfType("ServiceRequest");
|
||||||
|
deleteAllOfType("Practitioner");
|
||||||
|
deleteAllOfType("Patient");
|
||||||
|
deleteAllOfType("Organization");
|
||||||
|
|
||||||
|
try {
|
||||||
|
myPatientDao.read(new IdType("Patient/Patient1063259"));
|
||||||
|
fail();
|
||||||
|
} catch (ResourceGoneException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteAllOfType(String theType) {
|
||||||
|
BundleUtil.toListOfResources(myFhirCtx, ourClient.search().forResource(theType).execute())
|
||||||
|
.forEach(t -> {
|
||||||
|
ourClient.delete().resourceById(t.getIdElement()).execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionDeleteWithDuplicateDeletes() throws Exception {
|
public void testTransactionDeleteWithDuplicateDeletes() throws Exception {
|
||||||
myDaoConfig.setAllowInlineMatchUrlReferences(true);
|
myDaoConfig.setAllowInlineMatchUrlReferences(true);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"resourceType": "Bundle",
|
||||||
|
"type": "transaction",
|
||||||
|
"entry": [
|
||||||
|
{
|
||||||
|
"fullUrl": "Patient/Patient1063259",
|
||||||
|
"resource": {
|
||||||
|
"resourceType": "Patient",
|
||||||
|
"id": "Patient1063259",
|
||||||
|
"identifier": [
|
||||||
|
{
|
||||||
|
"system": "http://www.foo.com/fhir/identifier-type/EnterpriseId",
|
||||||
|
"value": "1063259"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"url": "Patient/Patient1063259"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "DiagnosticReport/ReportSPATH",
|
||||||
|
"resource": {
|
||||||
|
"resourceType": "DiagnosticReport",
|
||||||
|
"id": "ReportSPATH",
|
||||||
|
"subject": {
|
||||||
|
"reference": "Patient/Patient1063259"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"url": "DiagnosticReport/ReportSPATH"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -104,6 +104,11 @@
|
||||||
The JPA server version migrator tool now runs in a multithreaded way, allowing it to
|
The JPA server version migrator tool now runs in a multithreaded way, allowing it to
|
||||||
upgrade th database faster when migration tasks require data updates.
|
upgrade th database faster when migration tasks require data updates.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
A bug in the JPA server was fixed: When a resource was previously deleted,
|
||||||
|
a transaction could not be posted that both restored the deleted resource but
|
||||||
|
also contained references to the now-restored resource.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
|
|
||||||
<release version="3.5.0" date="2018-09-17">
|
<release version="3.5.0" date="2018-09-17">
|
||||||
|
|
Loading…
Reference in New Issue