Fix crash in JPA server if numeric search parameter has no value
This commit is contained in:
parent
c2e5fa3f18
commit
a50a86d9af
|
@ -76,13 +76,6 @@ import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.IDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
|
||||||
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
|
|
||||||
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
|
||||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
||||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||||
|
@ -1102,7 +1095,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
if (!isBlank(unitsValue)) {
|
if (!isBlank(unitsValue)) {
|
||||||
code = theBuilder.equal(theFrom.get("myUnits"), unitsValue);
|
code = theBuilder.equal(theFrom.get("myUnits"), unitsValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmpValue = ObjectUtils.defaultIfNull(cmpValue, ParamPrefixEnum.EQUAL);
|
cmpValue = ObjectUtils.defaultIfNull(cmpValue, ParamPrefixEnum.EQUAL);
|
||||||
final Expression<BigDecimal> path = theFrom.get("myValue");
|
final Expression<BigDecimal> path = theFrom.get("myValue");
|
||||||
String invalidMessageName = "invalidQuantityPrefix";
|
String invalidMessageName = "invalidQuantityPrefix";
|
||||||
|
@ -1768,6 +1761,39 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchForIdsWithAndOr(String theResourceName, String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams) {
|
private void searchForIdsWithAndOr(String theResourceName, String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams) {
|
||||||
|
|
||||||
|
for (int andListIdx = 0; andListIdx < theAndOrParams.size(); andListIdx++) {
|
||||||
|
List<? extends IQueryParameterType> nextOrList = theAndOrParams.get(andListIdx);
|
||||||
|
|
||||||
|
for (int orListIdx = 0; orListIdx < nextOrList.size(); orListIdx++) {
|
||||||
|
IQueryParameterType nextOr = nextOrList.get(orListIdx);
|
||||||
|
boolean hasNoValue = false;
|
||||||
|
if (nextOr.getMissing() != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nextOr instanceof QuantityParam) {
|
||||||
|
if (isBlank(((QuantityParam) nextOr).getValueAsString())) {
|
||||||
|
hasNoValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasNoValue) {
|
||||||
|
ourLog.debug("Ignoring empty parameter: {}", theParamName);
|
||||||
|
nextOrList.remove(orListIdx);
|
||||||
|
orListIdx--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextOrList.isEmpty()) {
|
||||||
|
theAndOrParams.remove(andListIdx);
|
||||||
|
andListIdx--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theAndOrParams.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (theParamName.equals(BaseResource.SP_RES_ID)) {
|
if (theParamName.equals(BaseResource.SP_RES_ID)) {
|
||||||
|
|
||||||
addPredicateResourceId(theAndOrParams);
|
addPredicateResourceId(theAndOrParams);
|
||||||
|
|
|
@ -178,14 +178,41 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
myDaoConfig.setAllowMultipleDelete(true);
|
myDaoConfig.setAllowMultipleDelete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithEmptyParameter() throws Exception {
|
||||||
|
Observation obs= new Observation();
|
||||||
|
obs.setStatus(ObservationStatus.FINAL);
|
||||||
|
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||||
|
ourClient.create().resource(obs).execute();
|
||||||
|
|
||||||
|
testSearchWithEmptyParameter("/Observation?value-quantity=");
|
||||||
|
testSearchWithEmptyParameter("/Observation?code=bar&value-quantity=");
|
||||||
|
testSearchWithEmptyParameter("/Observation?value-date=");
|
||||||
|
testSearchWithEmptyParameter("/Observation?code=bar&value-date=");
|
||||||
|
testSearchWithEmptyParameter("/Observation?value-concept=");
|
||||||
|
testSearchWithEmptyParameter("/Observation?code=bar&value-concept=");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testSearchWithEmptyParameter(String url) throws IOException, ClientProtocolException {
|
||||||
|
HttpGet get = new HttpGet(ourServerBase + url);
|
||||||
|
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
||||||
|
try {
|
||||||
|
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||||
|
String respString = IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8);
|
||||||
|
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, respString);
|
||||||
|
assertEquals(1, bundle.getEntry().size());
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMissingDate2() throws Exception {
|
public void testSearchWithMissingDate2() throws Exception {
|
||||||
MedicationRequest mr1 = new MedicationRequest();
|
MedicationRequest mr1 = new MedicationRequest();
|
||||||
mr1.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
|
mr1.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
|
||||||
mr1.addDosageInstruction().getTiming().addEventElement().setValueAsString("2017-01-01");
|
mr1.addDosageInstruction().getTiming().addEventElement().setValueAsString("2017-01-01");
|
||||||
IIdType id1 = myMedicationRequestDao.create(mr1).getId().toUnqualifiedVersionless();
|
IIdType id1 = myMedicationRequestDao.create(mr1).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
MedicationRequest mr2 = new MedicationRequest();
|
MedicationRequest mr2 = new MedicationRequest();
|
||||||
mr2.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
|
mr2.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
|
||||||
IIdType id2 = myMedicationRequestDao.create(mr2).getId().toUnqualifiedVersionless();
|
IIdType id2 = myMedicationRequestDao.create(mr2).getId().toUnqualifiedVersionless();
|
||||||
|
@ -195,38 +222,34 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
try {
|
try {
|
||||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||||
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8));
|
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8));
|
||||||
|
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(bundle);
|
List<String> ids = toUnqualifiedVersionlessIdValues(bundle);
|
||||||
assertThat(ids, contains(id1.getValue()));
|
assertThat(ids, contains(id1.getValue()));
|
||||||
} finally {
|
} finally {
|
||||||
IOUtils.closeQuietly(resp);
|
IOUtils.closeQuietly(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingWithOnlyPatient() {
|
public void testEverythingWithOnlyPatient() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
myFhirCtx.getRestfulClientFactory().setSocketTimeout(300 * 1000);
|
myFhirCtx.getRestfulClientFactory().setSocketTimeout(300 * 1000);
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = ourClient
|
||||||
.operation()
|
.operation()
|
||||||
.onInstance(id)
|
.onInstance(id)
|
||||||
.named("everything")
|
.named("everything")
|
||||||
.withNoParameters(Parameters.class)
|
.withNoParameters(Parameters.class)
|
||||||
.returnResourceType(Bundle.class)
|
.returnResourceType(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
assertEquals(1, response.getEntry().size());
|
assertEquals(1, response.getEntry().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSaveAndRetrieveResourceWithExtension() {
|
public void testSaveAndRetrieveResourceWithExtension() {
|
||||||
Patient nextPatient = new Patient();
|
Patient nextPatient = new Patient();
|
||||||
|
@ -239,7 +262,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
ourClient.update().resource(nextPatient).execute();
|
ourClient.update().resource(nextPatient).execute();
|
||||||
|
|
||||||
Patient p = ourClient.read().resource(Patient.class).withId("B").execute();
|
Patient p = ourClient.read().resource(Patient.class).withId("B").execute();
|
||||||
|
|
||||||
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
looked like before the update. This change was made to support the change above, but
|
looked like before the update. This change was made to support the change above, but
|
||||||
seems like a useful feature all around.
|
seems like a useful feature all around.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Fix HTTP 500 error in JPA server if a numeric search parameter was supplied with no value, e.g.
|
||||||
|
<![CDATA[<code>GET /Observation?value-quantity=</code>]]>
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="2.5" date="2017-06-08">
|
<release version="2.5" date="2017-06-08">
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
|
|
Loading…
Reference in New Issue