Improve error messages in JPA server
This commit is contained in:
parent
2fc0d4c7a2
commit
3bdf846a3d
|
@ -52,3 +52,5 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedId=C
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidParameterChain=Invalid parameter chain: {0}
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidParameterChain=Invalid parameter chain: {0}
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||||
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.successfulCreate=Successfully created resource "{0}" in {1}ms
|
||||||
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.successfulUpdate=Successfully updated resource "{0}" in {1}ms
|
||||||
|
|
|
@ -293,6 +293,36 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return new HashSet<Long>(q.getResultList());
|
return new HashSet<Long>(q.getResultList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates,
|
||||||
|
IQueryParameterType nextOr) {
|
||||||
|
boolean missingFalse = false;
|
||||||
|
if (nextOr.getMissing() != null) {
|
||||||
|
if (nextOr.getMissing().booleanValue() == true) {
|
||||||
|
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||||
|
}
|
||||||
|
Predicate singleCode = from.get("myId").isNotNull();
|
||||||
|
Predicate name = theBuilder.equal(from.get("myParamName"), theParamName);
|
||||||
|
codePredicates.add(theBuilder.and(name, singleCode));
|
||||||
|
missingFalse = true;
|
||||||
|
}
|
||||||
|
return missingFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates,
|
||||||
|
IQueryParameterType nextOr) {
|
||||||
|
boolean missingFalse = false;
|
||||||
|
if (nextOr.getMissing() != null) {
|
||||||
|
if (nextOr.getMissing().booleanValue() == true) {
|
||||||
|
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||||
|
}
|
||||||
|
Predicate singleCode = from.get("mySourceResource").isNotNull();
|
||||||
|
Predicate name = createResourceLinkPathPredicate(theParamName, theBuilder, from);
|
||||||
|
codePredicates.add(theBuilder.and(name, singleCode));
|
||||||
|
missingFalse = true;
|
||||||
|
}
|
||||||
|
return missingFalse;
|
||||||
|
}
|
||||||
|
|
||||||
private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||||
if (theList == null || theList.isEmpty()) {
|
if (theList == null || theList.isEmpty()) {
|
||||||
return thePids;
|
return thePids;
|
||||||
|
@ -680,13 +710,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return new HashSet<Long>(q.getResultList());
|
return new HashSet<Long>(q.getResultList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Predicate createResourceLinkPathPredicate(String theParamName, CriteriaBuilder builder, Root<? extends ResourceLink> from) {
|
|
||||||
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
|
||||||
List<String> path = param.getPathsSplit();
|
|
||||||
Predicate type = from.get("mySourcePath").in(path);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<Long> addPredicateString(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
private Set<Long> addPredicateString(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||||
if (theList == null || theList.isEmpty()) {
|
if (theList == null || theList.isEmpty()) {
|
||||||
return thePids;
|
return thePids;
|
||||||
|
@ -727,36 +750,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return new HashSet<Long>(q.getResultList());
|
return new HashSet<Long>(q.getResultList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates,
|
|
||||||
IQueryParameterType nextOr) {
|
|
||||||
boolean missingFalse = false;
|
|
||||||
if (nextOr.getMissing() != null) {
|
|
||||||
if (nextOr.getMissing().booleanValue() == true) {
|
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
|
||||||
}
|
|
||||||
Predicate singleCode = from.get("myId").isNotNull();
|
|
||||||
Predicate name = theBuilder.equal(from.get("myParamName"), theParamName);
|
|
||||||
codePredicates.add(theBuilder.and(name, singleCode));
|
|
||||||
missingFalse = true;
|
|
||||||
}
|
|
||||||
return missingFalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates,
|
|
||||||
IQueryParameterType nextOr) {
|
|
||||||
boolean missingFalse = false;
|
|
||||||
if (nextOr.getMissing() != null) {
|
|
||||||
if (nextOr.getMissing().booleanValue() == true) {
|
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
|
||||||
}
|
|
||||||
Predicate singleCode = from.get("mySourceResource").isNotNull();
|
|
||||||
Predicate name = createResourceLinkPathPredicate(theParamName, theBuilder, from);
|
|
||||||
codePredicates.add(theBuilder.and(name, singleCode));
|
|
||||||
missingFalse = true;
|
|
||||||
}
|
|
||||||
return missingFalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||||
if (theList == null || theList.isEmpty()) {
|
if (theList == null || theList.isEmpty()) {
|
||||||
return thePids;
|
return thePids;
|
||||||
|
@ -871,12 +864,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
|
|
||||||
return createOperationOutcome("error", theMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage);
|
|
||||||
|
|
||||||
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
||||||
Predicate retVal = null;
|
Predicate retVal = null;
|
||||||
switch (left.getParamType()) {
|
switch (left.getParamType()) {
|
||||||
|
@ -904,6 +891,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
|
||||||
|
return createOperationOutcome(IssueSeverityEnum.ERROR.getCode(), theMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
|
||||||
|
return createOperationOutcome(IssueSeverityEnum.INFORMATION.getCode(), theMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage);
|
||||||
|
|
||||||
private Predicate createPredicateDate(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, IQueryParameterType theParam) {
|
private Predicate createPredicateDate(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, IQueryParameterType theParam) {
|
||||||
Predicate p;
|
Predicate p;
|
||||||
if (theParam instanceof DateParam) {
|
if (theParam instanceof DateParam) {
|
||||||
|
@ -1046,6 +1043,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
return singleCode;
|
return singleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Predicate createResourceLinkPathPredicate(String theParamName, CriteriaBuilder builder, Root<? extends ResourceLink> from) {
|
||||||
|
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
||||||
|
List<String> path = param.getPathsSplit();
|
||||||
|
Predicate type = from.get("mySourcePath").in(path);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders) {
|
private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders) {
|
||||||
if (theSort == null || isBlank(theSort.getParamName())) {
|
if (theSort == null || isBlank(theSort.getParamName())) {
|
||||||
return;
|
return;
|
||||||
|
@ -1186,18 +1190,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
||||||
|
|
||||||
notifyWriteCompleted();
|
notifyWriteCompleted();
|
||||||
ourLog.info("Processed create on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
|
||||||
return outcome;
|
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||||
}
|
outcome.setOperationOutcome(createInfoOperationOutcome(msg));
|
||||||
|
|
||||||
/**
|
ourLog.info(msg);
|
||||||
* May
|
return outcome;
|
||||||
*
|
|
||||||
* @param theResource
|
|
||||||
* The resource that is about to be stored
|
|
||||||
*/
|
|
||||||
protected void preProcessResourceForStorage(T theResource) {
|
|
||||||
// nothing by default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1537,6 +1535,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* May be implemented by subclasses to validate resources prior to storage
|
||||||
|
*
|
||||||
|
* @param theResource
|
||||||
|
* The resource that is about to be stored
|
||||||
|
*/
|
||||||
|
protected void preProcessResourceForStorage(T theResource) {
|
||||||
|
// nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T read(IIdType theId) {
|
public T read(IIdType theId) {
|
||||||
validateResourceTypeAndThrowIllegalArgumentException(theId);
|
validateResourceTypeAndThrowIllegalArgumentException(theId);
|
||||||
|
@ -2121,8 +2129,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
ResourceTable savedEntity = updateEntity(theResource, entity, true, null, thePerformIndexing, true);
|
ResourceTable savedEntity = updateEntity(theResource, entity, true, null, thePerformIndexing, true);
|
||||||
|
|
||||||
notifyWriteCompleted();
|
notifyWriteCompleted();
|
||||||
ourLog.info("Processed update on {} in {}ms", resourceId, w.getMillisAndRestart());
|
|
||||||
return toMethodOutcome(savedEntity, theResource).setCreated(false);
|
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
|
||||||
|
|
||||||
|
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||||
|
outcome.setOperationOutcome(createInfoOperationOutcome(msg));
|
||||||
|
|
||||||
|
ourLog.info(msg);
|
||||||
|
return outcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateGivenIdIsAppropriateToRetrieveResource(IIdType theId, BaseHasResource entity) {
|
private void validateGivenIdIsAppropriateToRetrieveResource(IIdType theId, BaseHasResource entity) {
|
||||||
|
|
|
@ -294,12 +294,35 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||||
String respString = IOUtils.toString(response.getEntity().getContent());
|
String respString = IOUtils.toString(response.getEntity().getContent());
|
||||||
ourLog.info(respString);
|
ourLog.info(respString);
|
||||||
|
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
|
||||||
|
assertThat(respString, containsString("Can not create resource with ID[2], ID must not be supplied on a create (POST) operation"));
|
||||||
} finally {
|
} finally {
|
||||||
response.getEntity().getContent().close();
|
response.getEntity().getContent().close();
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException {
|
||||||
|
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||||
|
|
||||||
|
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||||
|
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
|
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||||
|
try {
|
||||||
|
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||||
|
String respString = IOUtils.toString(response.getEntity().getContent());
|
||||||
|
ourLog.info(response.toString());
|
||||||
|
ourLog.info(respString);
|
||||||
|
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
|
||||||
|
} finally {
|
||||||
|
response.getEntity().getContent().close();
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeepChaining() {
|
public void testDeepChaining() {
|
||||||
delete("Location", Location.SP_NAME, "testDeepChainingL1");
|
delete("Location", Location.SP_NAME, "testDeepChainingL1");
|
||||||
|
|
|
@ -76,6 +76,22 @@ public class ExceptionTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceNotFound() throws Exception {
|
||||||
|
ourExceptionType = ResourceNotFoundException.class;
|
||||||
|
ourGenerateOperationOutcome = false;
|
||||||
|
{
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123");
|
||||||
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||||
|
OperationOutcome oo = (OperationOutcome) servlet.getFhirContext().newXmlParser().parseResource(responseContent);
|
||||||
|
assertThat(oo.getIssueFirstRep().getDetails().getValue(), StringContains.containsString("Resource Patient/123 is not known"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInternalErrorFormatted() throws Exception {
|
public void testInternalErrorFormatted() throws Exception {
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue