Fix #822 - Respect chained method params in a transaction search

This commit is contained in:
James Agnew 2018-01-30 16:20:25 -06:00
parent c5165e860b
commit 1c5a07b5a0
14 changed files with 261 additions and 178 deletions

View File

@ -69,14 +69,12 @@ public class TokenOrListParam extends BaseOrListParam<TokenOrListParam, TokenPar
/** /**
* Add a new token to this list * Add a new token to this list
* * @param theSystem
* @param theSystem
* The system to use for the one token to pre-populate in this list * The system to use for the one token to pre-populate in this list
* @param theValue
* The value to use for the one token to pre-populate in this list
*/ */
public void add(String theSystem, String theValue) { public TokenOrListParam add(String theSystem, String theValue) {
add(new TokenParam(theSystem, theValue)); add(new TokenParam(theSystem, theValue));
return this;
} }
public List<BaseCodingDt> getListAsCodings() { public List<BaseCodingDt> getListAsCodings() {

View File

@ -114,7 +114,7 @@ public class JaxRsResponseDstu3Test {
boolean allowPrefer = true; boolean allowPrefer = true;
String resourceName = "Patient"; String resourceName = "Patient";
MethodOutcome methodOutcome = new MethodOutcome(theId); MethodOutcome methodOutcome = new MethodOutcome(theId);
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML}); response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
boolean addContentLocationHeader = true; boolean addContentLocationHeader = true;
boolean respondGzip = true; boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request); Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
@ -126,7 +126,7 @@ public class JaxRsResponseDstu3Test {
@Test @Test
public void testNoOutcomeXml() throws IOException { public void testNoOutcomeXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML}); response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
boolean addContentLocationHeader = true; boolean addContentLocationHeader = true;
boolean respondGzip = true; boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), null, theSummaryMode, 204, addContentLocationHeader, respondGzip, this.request); Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), null, theSummaryMode, 204, addContentLocationHeader, respondGzip, this.request);

View File

@ -88,7 +88,7 @@ public class JaxRsResponseTest {
@Test @Test
public void testReturnResponseAsXml() throws IOException { public void testReturnResponseAsXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML }); response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
boolean addContentLocationHeader = true; boolean addContentLocationHeader = true;
boolean respondGzip = true; boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request); Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
@ -100,7 +100,7 @@ public class JaxRsResponseTest {
@Test @Test
public void testNoOutcomeXml() throws IOException { public void testNoOutcomeXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML }); response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
boolean addContentLocationHeader = true; boolean addContentLocationHeader = true;
boolean respondGzip = true; boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request); Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);

View File

@ -532,7 +532,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
} }
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) { for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]); String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue); requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
} }
url = url.substring(0, qIndex); url = url.substring(0, qIndex);
} }

View File

@ -260,7 +260,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
} }
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) { for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]); String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue); requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
} }
url = url.substring(0, qIndex); url = url.substring(0, qIndex);
} }

View File

@ -266,7 +266,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
} }
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) { for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]); String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue); requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
} }
url = url.substring(0, qIndex); url = url.substring(0, qIndex);
} }
@ -290,7 +290,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
requestDetails.addHeader(Constants.HEADER_IF_NONE_MATCH, nextReqEntry.getRequest().getIfNoneMatch()); requestDetails.addHeader(Constants.HEADER_IF_NONE_MATCH, nextReqEntry.getRequest().getIfNoneMatch());
} }
Validate.isTrue(method instanceof BaseResourceReturningMethodBinding, "Unable to handle GET {}", url); Validate.isTrue(method instanceof BaseResourceReturningMethodBinding, "Unable to handle GET {0}", url);
try { try {
IBaseResource resource = ((BaseResourceReturningMethodBinding) method).doInvokeServer(theRequestDetails.getServer(), requestDetails); IBaseResource resource = ((BaseResourceReturningMethodBinding) method).doInvokeServer(theRequestDetails.getServer(), requestDetails);
if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) { if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) {

View File

@ -29,13 +29,13 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class ServletSubRequestDetails extends ServletRequestDetails { public class ServletSubRequestDetails extends ServletRequestDetails {
private Map<String, ArrayList<String>> myHeaders = new HashMap<String, ArrayList<String>>(); private Map<String, ArrayList<String>> myHeaders = new HashMap<>();
public void addHeader(String theName, String theValue) { public void addHeader(String theName, String theValue) {
String lowerCase = theName.toLowerCase(); String lowerCase = theName.toLowerCase();
ArrayList<String> list = myHeaders.get(lowerCase); ArrayList<String> list = myHeaders.get(lowerCase);
if (list == null) { if (list == null) {
list = new ArrayList<String>(); list = new ArrayList<>();
myHeaders.put(lowerCase, list); myHeaders.put(lowerCase, list);
} }
list.add(theValue); list.add(theValue);

View File

@ -158,7 +158,7 @@ public abstract class BaseJpaTest {
} }
protected List<IIdType> toUnqualifiedVersionlessIds(IBundleProvider theFound) { protected List<IIdType> toUnqualifiedVersionlessIds(IBundleProvider theFound) {
List<IIdType> retVal = new ArrayList<IIdType>(); List<IIdType> retVal = new ArrayList<>();
Integer size = theFound.size(); Integer size = theFound.size();
StopWatch sw = new StopWatch(); StopWatch sw = new StopWatch();
while (size == null) { while (size == null) {
@ -171,6 +171,7 @@ public abstract class BaseJpaTest {
} catch (InterruptedException theE) { } catch (InterruptedException theE) {
//ignore //ignore
} }
size = theFound.size();
} }
ourLog.info("Found {} results", size); ourLog.info("Found {} results", size);

View File

@ -3,7 +3,6 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.SearchParameterMap; import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
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;
@ -12,11 +11,11 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.server.exceptions.*; import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.*;
@ -25,7 +24,6 @@ import org.hl7.fhir.r4.model.Observation.ObservationStatus;
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity; import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
import org.junit.*; import org.junit.*;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallback;
@ -57,46 +55,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete()); myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
} }
/**
* See #811
*/
@Test
public void testUpdatePreviouslyDeletedResourceInBatch() {
AllergyIntolerance ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
IIdType id = myAllergyIntoleranceDao.update(ai).getId();
assertEquals("1", id.getVersionIdPart());
id = myAllergyIntoleranceDao.delete(ai.getIdElement().toUnqualifiedVersionless()).getId();
assertEquals("2", id.getVersionIdPart());
try {
myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
Bundle batch = new Bundle();
batch.setType(BundleType.BATCH);
ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
batch
.addEntry()
.setFullUrl("AllergyIntolerance/AIA1914009")
.setResource(ai)
.getRequest()
.setUrl("AllergyIntolerance/AIA1914009")
.setMethod(HTTPVerb.PUT);
mySystemDao.transaction(mySrd, batch);
id = myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless()).getIdElement();
assertEquals("3", id.getVersionIdPart());
}
@Before @Before
public void beforeDisableResultReuse() { public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null); myDaoConfig.setReuseCachedSearchResultsForMillis(null);
@ -2489,7 +2447,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
/* /*
* Make sure we are able to handle placeholder IDs in match URLs, e.g. * Make sure we are able to handle placeholder IDs in match URLs, e.g.
* *
* "request": { * "request": {
* "method": "PUT", * "method": "PUT",
* "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00" * "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00"
@ -2519,7 +2477,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
/* /*
* Make sure we are able to handle placeholder IDs in match URLs, e.g. * Make sure we are able to handle placeholder IDs in match URLs, e.g.
* *
* "request": { * "request": {
* "method": "PUT", * "method": "PUT",
* "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00" * "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00"
@ -2583,7 +2541,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString()); assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
} }
@Test @Test
public void testTransactionWithReferenceResource() { public void testTransactionWithReferenceResource() {
Bundle request = new Bundle(); Bundle request = new Bundle();
@ -2611,7 +2568,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertEquals(1, found.size().intValue()); assertEquals(1, found.size().intValue());
} }
@Test @Test
public void testTransactionWithReferenceToCreateIfNoneExist() { public void testTransactionWithReferenceToCreateIfNoneExist() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -2635,9 +2591,9 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
IdType medId1 = new IdType(outcome.getEntry().get(0).getResponse().getLocation()); IdType medId1 = new IdType(outcome.getEntry().get(0).getResponse().getLocation());
IdType medOrderId1 = new IdType(outcome.getEntry().get(1).getResponse().getLocation()); IdType medOrderId1 = new IdType(outcome.getEntry().get(1).getResponse().getLocation());
/* /*
* Again! * Again!
*/ */
bundle = new Bundle(); bundle = new Bundle();
bundle.setType(BundleType.TRANSACTION); bundle.setType(BundleType.TRANSACTION);
@ -2665,6 +2621,33 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertNotEquals(medOrderId1, medOrderId2); assertNotEquals(medOrderId1, medOrderId2);
} }
@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());
}
// //
// //
// /** // /**
@ -2767,34 +2750,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
// //
// } // }
@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 @Test
public void testTransactionWithRelativeOidIds() throws Exception { public void testTransactionWithRelativeOidIds() throws Exception {
Bundle res = new Bundle(); Bundle res = new Bundle();
@ -2959,6 +2914,46 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
} }
/**
* See #811
*/
@Test
public void testUpdatePreviouslyDeletedResourceInBatch() {
AllergyIntolerance ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
IIdType id = myAllergyIntoleranceDao.update(ai).getId();
assertEquals("1", id.getVersionIdPart());
id = myAllergyIntoleranceDao.delete(ai.getIdElement().toUnqualifiedVersionless()).getId();
assertEquals("2", id.getVersionIdPart());
try {
myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
Bundle batch = new Bundle();
batch.setType(BundleType.BATCH);
ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
batch
.addEntry()
.setFullUrl("AllergyIntolerance/AIA1914009")
.setResource(ai)
.getRequest()
.setUrl("AllergyIntolerance/AIA1914009")
.setMethod(HTTPVerb.PUT);
mySystemDao.transaction(mySrd, batch);
id = myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless()).getIdElement();
assertEquals("3", id.getVersionIdPart());
}
@AfterClass @AfterClass
public static void afterClassClearContext() { public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest(); TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -1,35 +1,41 @@
package ca.uhn.fhir.jpa.provider.r4; package ca.uhn.fhir.jpa.provider.r4;
import static org.hamcrest.Matchers.*; import ca.uhn.fhir.context.FhirContext;
import static org.junit.Assert.assertEquals; import ca.uhn.fhir.jpa.dao.DaoConfig;
import static org.junit.Assert.assertThat; import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import java.util.ArrayList; import ca.uhn.fhir.jpa.rp.r4.*;
import java.util.List; import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import java.util.concurrent.TimeUnit; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server; 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.r4.model.Bundle; import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.*; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.r4.model.Patient; import org.junit.After;
import org.junit.*; import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext; import java.util.ArrayList;
import ca.uhn.fhir.jpa.dao.DaoConfig; import java.util.List;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.jpa.rp.r4.*;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider; import static org.hamcrest.Matchers.*;
import ca.uhn.fhir.rest.api.EncodingEnum; import static org.junit.Assert.*;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test { public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
@ -43,7 +49,6 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor; private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@After @After
public void after() { public void after() {
@ -57,7 +62,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor(); mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
ourClient.registerInterceptor(mySimpleHeaderInterceptor); ourClient.registerInterceptor(mySimpleHeaderInterceptor);
} }
@Before @Before
public void beforeStartServer() throws Exception { public void beforeStartServer() throws Exception {
if (myRestServer == null) { if (myRestServer == null) {
@ -73,8 +78,14 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider(); OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
organizationRp.setDao(myOrganizationDao); organizationRp.setDao(myOrganizationDao);
MedicationResourceProvider medicationRp = new MedicationResourceProvider();
medicationRp.setDao(myMedicationDao);
MedicationRequestResourceProvider medicationRequestRp = new MedicationRequestResourceProvider();
medicationRequestRp.setDao(myMedicationRequestDao);
RestfulServer restServer = new RestfulServer(ourCtx); RestfulServer restServer = new RestfulServer(ourCtx);
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp); restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, medicationRequestRp, medicationRp);
restServer.setPlainProviders(mySystemProvider); restServer.setPlainProviders(mySystemProvider);
@ -106,11 +117,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
ourClient.setLogRequestAndResponse(true); ourClient.setLogRequestAndResponse(true);
myRestServer = restServer; myRestServer = restServer;
} }
myRestServer.setDefaultResponseEncoding(EncodingEnum.XML); myRestServer.setDefaultResponseEncoding(EncodingEnum.XML);
myRestServer.setPagingProvider(myPagingProvider); myRestServer.setPagingProvider(myPagingProvider);
} }
private List<String> create20Patients() { private List<String> create20Patients() {
List<String> ids = new ArrayList<String>(); List<String> ids = new ArrayList<String>();
@ -120,7 +130,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
patient.setId("" + letter); patient.setId("" + letter);
patient.setGender(AdministrativeGender.MALE); patient.setGender(AdministrativeGender.MALE);
patient.addIdentifier().setSystem("urn:foo").setValue("A"); patient.addIdentifier().setSystem("urn:foo").setValue("A");
patient.addName().setFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i+1)); patient.addName().setFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i + 1));
String id = myPatientDao.update(patient).getId().toUnqualifiedVersionless().getValue(); String id = myPatientDao.update(patient).getId().toUnqualifiedVersionless().getValue();
ids.add(id); ids.add(id);
} }
@ -130,7 +140,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
@Test @Test
public void testBatchWithGetHardLimitLargeSynchronous() { public void testBatchWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.BATCH); input.setType(BundleType.BATCH);
input input
@ -138,12 +148,12 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest() .getRequest()
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=_id"); .setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100); myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size()); assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size()); assertEquals(5, respBundle.getEntry().size());
@ -151,11 +161,11 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
List<String> actualIds = toIds(respBundle); List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0]))); assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
} }
@Test @Test
public void testBatchWithGetNormalSearch() { public void testBatchWithGetNormalSearch() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.BATCH); input.setType(BundleType.BATCH);
input input
@ -163,16 +173,16 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest() .getRequest()
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=name"); .setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size()); assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size()); assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle); List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0]))); assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl(); String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute(); output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output; respBundle = output;
@ -188,7 +198,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
public void testBatchWithManyGets() { public void testBatchWithManyGets() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.BATCH); input.setType(BundleType.BATCH);
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
@ -198,10 +208,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i); .setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
} }
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size()); assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();
@ -212,10 +222,72 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
} }
} }
/**
* See #822
*/
@Test
public void testSearchByBatch() {
Patient p = new Patient();
p.setId("P3000254749");
p.setActive(true);
myPatientDao.update(p);
Medication med = new Medication();
med.setId("MED19795");
med.getCode().addCoding().setCode("00093-0058-05").setSystem("http://hl7.org/fhir/sid/ndc");
myMedicationDao.update(med);
med = new Medication();
med.setId("MED20344");
med.getCode().addCoding().setCode("50580-0449-23").setSystem("http://hl7.org/fhir/sid/ndc");
myMedicationDao.update(med);
MedicationRequest medRequest = new MedicationRequest();
medRequest.setId("MR142528");
medRequest.setMedication(new Reference("Medication/MED19795"));
medRequest.setSubject(new Reference("Patient/P3000254749"));
medRequest.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
myMedicationRequestDao.update(medRequest);
medRequest = new MedicationRequest();
medRequest.setId("MR635079");
medRequest.setMedication(new Reference("Medication/MED20344"));
medRequest.setSubject(new Reference("Patient/P3000254749"));
medRequest.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
myMedicationRequestDao.update(medRequest);
SearchParameterMap map = new SearchParameterMap();
map.add(MedicationRequest.SP_INTENT, new TokenOrListParam().add(null, "plan").add(null, "order"));
map.add(MedicationRequest.SP_MEDICATION, new ReferenceParam().setChain("code").setValue("50580-0449-23"));
Bundle b = ourClient
.search()
.forResource("MedicationRequest")
.where(MedicationRequest.INTENT.exactly().codes("plan", "order"))
.and(MedicationRequest.MEDICATION.hasChainedProperty(Medication.CODE.exactly().code("50580-0449-23")))
.returnBundle(Bundle.class)
.execute();
assertEquals(1, b.getEntry().size());
assertEquals("MedicationRequest/MR635079", b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
b = new Bundle();
b.setType(BundleType.BATCH);
b.addEntry()
.setFullUrl(IdType.newRandomUuid().getValueAsString())
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("MedicationRequest?intent=plan,order&medication.code=50580-0449-23&patient=P3000254749");
Bundle resp = ourClient.transaction().withBundle(b).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
b = (Bundle) resp.getEntry().get(0).getResource();
assertEquals(1, b.getEntry().size());
assertEquals("MedicationRequest/MR635079", b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
}
@Test @Test
public void testTransactionWithGetHardLimitLargeSynchronous() { public void testTransactionWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION); input.setType(BundleType.TRANSACTION);
input input
@ -223,12 +295,12 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest() .getRequest()
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=_id"); .setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100); myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size()); assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size()); assertEquals(5, respBundle.getEntry().size());
@ -236,11 +308,11 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
List<String> actualIds = toIds(respBundle); List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0]))); assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
} }
@Test @Test
public void testTransactionWithGetNormalSearch() { public void testTransactionWithGetNormalSearch() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION); input.setType(BundleType.TRANSACTION);
input input
@ -248,16 +320,16 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest() .getRequest()
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=name"); .setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size()); assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size()); assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle); List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0]))); assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl(); String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute(); output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output; respBundle = output;
@ -273,7 +345,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
public void testTransactionWithManyGets() { public void testTransactionWithManyGets() {
List<String> ids = create20Patients(); List<String> ids = create20Patients();
Bundle input = new Bundle(); Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION); input.setType(BundleType.TRANSACTION);
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
@ -283,10 +355,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.setMethod(HTTPVerb.GET) .setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i); .setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
} }
Bundle output = ourClient.transaction().withBundle(input).execute(); Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size()); assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource(); Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
@ -30,9 +31,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -63,6 +64,11 @@ public abstract class RequestDetails {
private Map<String, List<String>> myUnqualifiedToQualifiedNames; private Map<String, List<String>> myUnqualifiedToQualifiedNames;
private Map<Object, Object> myUserData; private Map<Object, Object> myUserData;
public void addParameter(String theName, String[] theValues) {
getParameters();
myParameters.put(theName, theValues);
}
protected abstract byte[] getByteStreamRequestContents(); protected abstract byte[] getByteStreamRequestContents();
/** /**
@ -170,37 +176,14 @@ public abstract class RequestDetails {
public Map<String, String[]> getParameters() { public Map<String, String[]> getParameters() {
if (myParameters == null) { if (myParameters == null) {
return Collections.emptyMap(); myParameters = new HashMap<>();
} }
return myParameters; return Collections.unmodifiableMap(myParameters);
} }
public void setParameters(Map<String, String[]> theParams) { public void setParameters(Map<String, String[]> theParams) {
myParameters = theParams; myParameters = theParams;
myUnqualifiedToQualifiedNames = null;
for (String next : theParams.keySet()) {
for (int i = 0; i < next.length(); i++) {
char nextChar = next.charAt(i);
if (nextChar == ':' || nextChar == '.') {
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = new HashMap<>();
}
String unqualified = next.substring(0, i);
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
if (list == null) {
list = new ArrayList<>(4);
myUnqualifiedToQualifiedNames.put(unqualified, list);
}
list.add(next);
break;
}
}
}
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = Collections.emptyMap();
}
} }
/** /**
@ -296,6 +279,29 @@ public abstract class RequestDetails {
} }
public Map<String, List<String>> getUnqualifiedToQualifiedNames() { public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
for (String next : myParameters.keySet()) {
for (int i = 0; i < next.length(); i++) {
char nextChar = next.charAt(i);
if (nextChar == ':' || nextChar == '.') {
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = new HashMap<>();
}
String unqualified = next.substring(0, i);
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
if (list == null) {
list = new ArrayList<>(4);
myUnqualifiedToQualifiedNames.put(unqualified, list);
}
list.add(next);
break;
}
}
}
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = Collections.emptyMap();
}
return myUnqualifiedToQualifiedNames; return myUnqualifiedToQualifiedNames;
} }
@ -359,6 +365,12 @@ public abstract class RequestDetails {
return myRequestContents; return myRequestContents;
} }
public void removeParameter(String theName) {
Validate.notNull(theName, "theName must not be null");
getParameters();
myParameters.remove(theName);
}
/** /**
* This method may be used to modify the contents of the incoming * This method may be used to modify the contents of the incoming
* request by hardcoding a value which will be used instead of the * request by hardcoding a value which will be used instead of the

View File

@ -938,8 +938,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
/* /*
* If we're handling an exception, no summary mode should be applied * If we're handling an exception, no summary mode should be applied
*/ */
requestDetails.getParameters().remove(Constants.PARAM_SUMMARY); requestDetails.removeParameter(Constants.PARAM_SUMMARY);
requestDetails.getParameters().remove(Constants.PARAM_ELEMENTS); requestDetails.removeParameter(Constants.PARAM_ELEMENTS);
/* /*
* If nobody handles it, default behaviour is to stream back the OperationOutcome to the client. * If nobody handles it, default behaviour is to stream back the OperationOutcome to the client.

View File

@ -323,10 +323,10 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
force = true; force = true;
} else if (Constants.FORMATS_HTML_XML.equals(formatParam)) { } else if (Constants.FORMATS_HTML_XML.equals(formatParam)) {
force = true; force = true;
theRequestDetails.getParameters().put(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_XML); theRequestDetails.addParameter(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_XML);
} else if (Constants.FORMATS_HTML_JSON.equals(formatParam)) { } else if (Constants.FORMATS_HTML_JSON.equals(formatParam)) {
force = true; force = true;
theRequestDetails.getParameters().put(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_JSON); theRequestDetails.addParameter(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_JSON);
} else { } else {
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse); return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
} }

View File

@ -88,6 +88,11 @@
which automaticaly converts response payloads to a client-specified version which automaticaly converts response payloads to a client-specified version
according to transforms built into FHIR. according to transforms built into FHIR.
</action> </action>
<action type="fix" issue="822">
Searches which were embedded in a Bundle as a transaction or batch operation did
not respect any chained method parameters (e.g. MedicationRequest?medication.code=123).
Thanks to @manjusampath for reporting!
</action>
</release> </release>
<release version="3.2.0" date="2018-01-13"> <release version="3.2.0" date="2018-01-13">
<action type="add"> <action type="add">