Fix #207 - Confusing error message parsing invalid contained resources
This commit is contained in:
parent
c2fba2ce21
commit
6941f92090
|
@ -1123,9 +1123,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
JsonObject nextObject = (JsonObject) theJsonVal;
|
||||
boolean preResource = false;
|
||||
if (theState.isPreResource()) {
|
||||
String resType = nextObject.getString("resourceType");
|
||||
String resType = nextObject.getString("resourceType", null);
|
||||
if (isBlank(resType)) {
|
||||
throw new DataFormatException("Missing 'resourceType' from resource");
|
||||
throw new DataFormatException("Missing required element 'resourceType' from JSON resource object, unable to parse");
|
||||
}
|
||||
theState.enteringNewElement(null, resType);
|
||||
preResource = true;
|
||||
|
|
|
@ -328,7 +328,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method (but should also call super.{@link #populateActionRequestDetailsForInterceptor(ActionRequestDetails, Object[])) to provide method specifics to the
|
||||
* Subclasses may override this method (but should also call super.{@link #populateActionRequestDetailsForInterceptor(RequestDetails, ActionRequestDetails, Object[])} to provide method specifics to the
|
||||
* interceptors.
|
||||
*
|
||||
* @param theRequestDetails
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -32,6 +34,18 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
|||
/**
|
||||
* Base class for RESTful client and server exceptions. RESTful client methods will only throw exceptions which are subclasses of this exception type, and RESTful server methods should also only call
|
||||
* subclasses of this exception type.
|
||||
* <p>
|
||||
* HAPI provides a number of subclasses of BaseServerResponseException, and each one corresponds to a specific
|
||||
* HTTP status code. For example, if a {@link IResourceProvider resource provider} method throws
|
||||
* {@link ResourceNotFoundException}, this is a signal to the server that an <code>HTTP 404</code> should
|
||||
* be returned to the client.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>See:</b> A complete list of available exceptions is in the <a href="./package-summary.html">package summary</a>.
|
||||
* If an exception doesn't exist for a condition you want to represent, let us know by filing an
|
||||
* <a href="https://github.com/jamesagnew/hapi-fhir/issues">issue in our tracker</a>. You may also
|
||||
* use {@link UnclassifiedServerFailureException} to represent any error code you want.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class BaseServerResponseException extends RuntimeException {
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ import ca.uhn.fhir.util.ElementUtil;
|
|||
@ResourceDef(name = "DiagnosticReport")
|
||||
public class MyDiagnosticReportWithBoundCodeExtension extends DiagnosticReport {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String SP_IMAGING_STUDY = "ImagingStudy";
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,4 +6,6 @@ import ca.uhn.fhir.model.dstu.resource.Organization;
|
|||
@ResourceDef()
|
||||
public class MyOrganization extends Organization {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
|||
@ResourceDef()
|
||||
public class MyPatient extends Patient {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Child(name = "importantDates", max = Child.MAX_UNLIMITED)
|
||||
@Extension(url = "http://example.com/dontuse#importantDates", definedLocally = false, isModifier = true)
|
||||
@Description(shortDefinition = "Some dates of note for the patient")
|
||||
|
|
|
@ -3,11 +3,7 @@ package ca.uhn.fhir.parser;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -299,7 +295,6 @@ public class JsonParserDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fixing #89
|
||||
*/
|
||||
|
@ -319,7 +314,6 @@ public class JsonParserDstu2Test {
|
|||
//@formatter:on
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* #158
|
||||
*/
|
||||
|
@ -328,10 +322,10 @@ public class JsonParserDstu2Test {
|
|||
TagList tagList = new TagList();
|
||||
tagList.addTag(null, null, null);
|
||||
tagList.addTag(null, null, "Label");
|
||||
|
||||
|
||||
Patient p = new Patient();
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p, tagList);
|
||||
|
||||
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(p);
|
||||
assertThat(encoded, not(containsString("tag")));
|
||||
}
|
||||
|
@ -344,10 +338,10 @@ public class JsonParserDstu2Test {
|
|||
TagList tagList = new TagList();
|
||||
tagList.addTag("scheme", "code", null);
|
||||
tagList.addTag(null, null, "Label");
|
||||
|
||||
|
||||
Patient p = new Patient();
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p, tagList);
|
||||
|
||||
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(p);
|
||||
assertThat(encoded, containsString("tag"));
|
||||
assertThat(encoded, containsString("scheme"));
|
||||
|
@ -415,7 +409,7 @@ public class JsonParserDstu2Test {
|
|||
Patient p = new Patient();
|
||||
p.setId("123");
|
||||
p.addName().addFamily("ABC");
|
||||
|
||||
|
||||
assertThat(ourCtx.newJsonParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC"));
|
||||
assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC"));
|
||||
assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123")));
|
||||
|
@ -444,7 +438,7 @@ public class JsonParserDstu2Test {
|
|||
|
||||
Medication m = (Medication) parsed.getEntries().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertSame(((ResourceReferenceDt)p.getMedication()).getResource(), m);
|
||||
assertSame(((ResourceReferenceDt) p.getMedication()).getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
@ -474,9 +468,9 @@ public class JsonParserDstu2Test {
|
|||
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, content);
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntry().get(0).getResource();
|
||||
assertEquals("#med", ((ResourceReferenceDt)p.getMedication()).getReference().getValue());
|
||||
assertEquals("#med", ((ResourceReferenceDt) p.getMedication()).getReference().getValue());
|
||||
|
||||
Medication m = (Medication) ((ResourceReferenceDt)p.getMedication()).getResource();
|
||||
Medication m = (Medication) ((ResourceReferenceDt) p.getMedication()).getResource();
|
||||
assertNotNull(m);
|
||||
assertEquals("#med", m.getId().getValue());
|
||||
assertEquals(1, p.getContained().getContainedResources().size());
|
||||
|
@ -514,8 +508,8 @@ public class JsonParserDstu2Test {
|
|||
|
||||
Medication m = (Medication) parsed.getEntry().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertEquals("Medication/example", ((ResourceReferenceDt)p.getMedication()).getReference().getValue());
|
||||
assertSame(((ResourceReferenceDt)p.getMedication()).getResource(), m);
|
||||
assertEquals("Medication/example", ((ResourceReferenceDt) p.getMedication()).getReference().getValue());
|
||||
assertSame(((ResourceReferenceDt) p.getMedication()).getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
@ -554,8 +548,8 @@ public class JsonParserDstu2Test {
|
|||
|
||||
Medication m = (Medication) parsed.getEntries().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertEquals("Medication/example", ((ResourceReferenceDt)p.getMedication()).getReference().getValue());
|
||||
assertSame(((ResourceReferenceDt)p.getMedication()).getResource(), m);
|
||||
assertEquals("Medication/example", ((ResourceReferenceDt) p.getMedication()).getReference().getValue());
|
||||
assertSame(((ResourceReferenceDt) p.getMedication()).getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
@ -665,12 +659,12 @@ public class JsonParserDstu2Test {
|
|||
" ]" +
|
||||
"}";
|
||||
//@formatter:on
|
||||
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = ourCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, input);
|
||||
|
||||
|
||||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(encoded);
|
||||
|
||||
|
||||
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getValue());
|
||||
assertEquals("urn:uuid:", parsed.getEntry().get(0).getResource().getId().getBaseUrl());
|
||||
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getIdPart());
|
||||
|
@ -807,6 +801,22 @@ public class JsonParserDstu2Test {
|
|||
assertNull(ResourceMetadataKeyEnum.PROFILES.get(patient));
|
||||
}
|
||||
|
||||
/**
|
||||
* See #207
|
||||
*/
|
||||
@Test
|
||||
public void testParseResourceWithInvalidType() {
|
||||
String input = "{" + "\"resourceType\":\"Patient\"," + "\"contained\":[" + " {" + " \"rezType\":\"Organization\"" + " }" + " ]" + "}";
|
||||
|
||||
IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||
try {
|
||||
jsonParser.parseResource(input);
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Missing required element 'resourceType' from JSON resource object, unable to parse", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See #163
|
||||
*/
|
||||
|
@ -829,10 +839,10 @@ public class JsonParserDstu2Test {
|
|||
|
||||
String bundleText = jsonParser.encodeResourceToString(bundle);
|
||||
ourLog.info(bundleText);
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle reincarnatedBundle = jsonParser.parseResource (ca.uhn.fhir.model.dstu2.resource.Bundle.class, bundleText);
|
||||
Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource();
|
||||
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle reincarnatedBundle = jsonParser.parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, bundleText);
|
||||
Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource();
|
||||
|
||||
assertEquals("Patient", patient.getId().getResourceType());
|
||||
assertEquals("Patient", reincarnatedPatient.getId().getResourceType());
|
||||
}
|
||||
|
|
|
@ -88,6 +88,11 @@
|
|||
of the appropriate error code for the exception being thrown. Thanks to Nagesh Bashyam
|
||||
for reporting!
|
||||
</action>
|
||||
<action type="fix" issue="207">
|
||||
Fix issue in JSON parser where invalid contained resources (missing
|
||||
a resourceType element) fail to parse with a confusing NullPointerException.
|
||||
Thanks to GitHub user @hugosoares for reporting!
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.1" date="2015-07-13">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue