Added a hook so subclasses of BaseController can customize error messages. (#691)

This commit is contained in:
Diederik Muylwyk 2017-07-13 14:05:19 -04:00 committed by GitHub
parent 1a6b3ea867
commit d7714c6372
2 changed files with 80 additions and 82 deletions

View File

@ -1,37 +1,5 @@
package ca.uhn.fhir.to; package ca.uhn.fhir.to;
import static org.apache.commons.lang3.StringUtils.defaultString;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.dstu3.model.DecimalType;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.thymeleaf.TemplateEngine;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -49,6 +17,31 @@ import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.to.model.HomeRequest; import ca.uhn.fhir.to.model.HomeRequest;
import ca.uhn.fhir.util.ExtensionConstants; import ca.uhn.fhir.util.ExtensionConstants;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.dstu3.model.DecimalType;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.thymeleaf.TemplateEngine;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.defaultString;
public class BaseController { public class BaseController {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseController.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseController.class);
@ -298,7 +291,7 @@ public class BaseController {
ourLog.warn("Failed to invoke server", e); ourLog.warn("Failed to invoke server", e);
if (e != null) { if (e != null) {
theModel.put("errorMsg", "Error: " + e.getMessage()); theModel.put("errorMsg", toDisplayError("Error: " + e.getMessage(), e));
} }
return returnsResource; return returnsResource;
@ -328,7 +321,7 @@ public class BaseController {
conformance = (Conformance) client.conformance(); conformance = (Conformance) client.conformance();
} catch (Exception e) { } catch (Exception e) {
ourLog.warn("Failed to load conformance statement", e); ourLog.warn("Failed to load conformance statement", e);
theModel.put("errorMsg", "Failed to load conformance statement, error was: " + e.toString()); theModel.put("errorMsg", toDisplayError("Failed to load conformance statement, error was: " + e.toString(), e));
conformance = new Conformance(); conformance = new Conformance();
} }
@ -388,7 +381,7 @@ public class BaseController {
conformance = (ca.uhn.fhir.model.dstu2.resource.Conformance) client.conformance(); conformance = (ca.uhn.fhir.model.dstu2.resource.Conformance) client.conformance();
} catch (Exception e) { } catch (Exception e) {
ourLog.warn("Failed to load conformance statement", e); ourLog.warn("Failed to load conformance statement", e);
theModel.put("errorMsg", "Failed to load conformance statement, error was: " + e.toString()); theModel.put("errorMsg", toDisplayError("Failed to load conformance statement, error was: " + e.toString(), e));
conformance = new ca.uhn.fhir.model.dstu2.resource.Conformance(); conformance = new ca.uhn.fhir.model.dstu2.resource.Conformance();
} }
@ -448,7 +441,7 @@ public class BaseController {
capabilityStatement = client.fetchConformance().ofType(org.hl7.fhir.dstu3.model.CapabilityStatement.class).execute(); capabilityStatement = client.fetchConformance().ofType(org.hl7.fhir.dstu3.model.CapabilityStatement.class).execute();
} catch (Exception ex) { } catch (Exception ex) {
ourLog.warn("Failed to load conformance statement", ex); ourLog.warn("Failed to load conformance statement", ex);
theModel.put("errorMsg", "Failed to load conformance statement, error was: " + ex.toString()); theModel.put("errorMsg", toDisplayError("Failed to load conformance statement, error was: " + ex.toString(), ex));
} }
theModel.put("jsonEncodedConf", getContext(theRequest).newJsonParser().encodeResourceToString(capabilityStatement)); theModel.put("jsonEncodedConf", getContext(theRequest).newJsonParser().encodeResourceToString(capabilityStatement));
@ -676,7 +669,7 @@ public class BaseController {
} catch (Exception e) { } catch (Exception e) {
ourLog.error("Failure during processing", e); ourLog.error("Failure during processing", e);
theModelMap.put("errorMsg", "Error during processing: " + e.getMessage()); theModelMap.put("errorMsg", toDisplayError("Error during processing: " + e.getMessage(), e));
} }
} }
@ -753,4 +746,16 @@ public class BaseController {
BUNDLE, NONE, RESOURCE, TAGLIST BUNDLE, NONE, RESOURCE, TAGLIST
} }
} /**
* A hook to be overridden by subclasses. The overriding method can modify the error message
* based on its content and/or the related exception.
*
* @param theErrorMsg The original error message to be displayed to the user.
* @param theException The exception that occurred. May be null.
* @return The modified error message to be displayed to the user.
*/
protected String toDisplayError(String theErrorMsg, Exception theException) {
return theErrorMsg;
}
}

View File

@ -1,36 +1,5 @@
package ca.uhn.fhir.to; package ca.uhn.fhir.to;
import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import com.google.gson.stream.JsonWriter;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -58,6 +27,30 @@ import ca.uhn.fhir.to.model.HomeRequest;
import ca.uhn.fhir.to.model.ResourceRequest; import ca.uhn.fhir.to.model.ResourceRequest;
import ca.uhn.fhir.to.model.TransactionRequest; import ca.uhn.fhir.to.model.TransactionRequest;
import ca.uhn.fhir.util.ExtensionConstants; import ca.uhn.fhir.util.ExtensionConstants;
import com.google.gson.stream.JsonWriter;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import static org.apache.commons.lang3.StringUtils.*;
@org.springframework.stereotype.Controller() @org.springframework.stereotype.Controller()
public class Controller extends BaseController { public class Controller extends BaseController {
@ -128,13 +121,13 @@ public class Controller extends BaseController {
try { try {
def = getResourceType(theRequest, theReq); def = getResourceType(theRequest, theReq);
} catch (ServletException e) { } catch (ServletException e) {
theModel.put("errorMsg", e.toString()); theModel.put("errorMsg", toDisplayError(e.toString(), e));
return "resource"; return "resource";
} }
String id = StringUtils.defaultString(theReq.getParameter("resource-delete-id")); String id = StringUtils.defaultString(theReq.getParameter("resource-delete-id"));
if (StringUtils.isBlank(id)) { if (StringUtils.isBlank(id)) {
theModel.put("errorMsg", "No ID specified"); theModel.put("errorMsg", toDisplayError("No ID specified", null));
return "resource"; return "resource";
} }
@ -173,7 +166,7 @@ public class Controller extends BaseController {
try { try {
def = getResourceType(theRequest, theReq); def = getResourceType(theRequest, theReq);
} catch (ServletException e) { } catch (ServletException e) {
theModel.put("errorMsg", e.toString()); theModel.put("errorMsg", toDisplayError(e.toString(), e));
return "resource"; return "resource";
} }
@ -237,7 +230,7 @@ public class Controller extends BaseController {
if (myConfig.isRefuseToFetchThirdPartyUrls()) { if (myConfig.isRefuseToFetchThirdPartyUrls()) {
if (!url.startsWith(theModel.get("base").toString())) { if (!url.startsWith(theModel.get("base").toString())) {
ourLog.warn(logPrefix(theModel) + "Refusing to load page URL: {}", url); ourLog.warn(logPrefix(theModel) + "Refusing to load page URL: {}", url);
theModel.put("errorMsg", "Invalid page URL: " + url); theModel.put("errorMsg", toDisplayError("Invalid page URL: " + url, null));
return "result"; return "result";
} }
} }
@ -279,12 +272,12 @@ public class Controller extends BaseController {
try { try {
def = getResourceType(theRequest, theReq); def = getResourceType(theRequest, theReq);
} catch (ServletException e) { } catch (ServletException e) {
theModel.put("errorMsg", e.toString()); theModel.put("errorMsg", toDisplayError(e.toString(), e));
return "resource"; return "resource";
} }
String id = StringUtils.defaultString(theReq.getParameter("id")); String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) { if (StringUtils.isBlank(id)) {
theModel.put("errorMsg", "No ID specified"); theModel.put("errorMsg", toDisplayError("No ID specified", null));
return "resource"; return "resource";
} }
ResultType returnsResource = ResultType.RESOURCE; ResultType returnsResource = ResultType.RESOURCE;
@ -391,7 +384,7 @@ public class Controller extends BaseController {
try { try {
query = search.forResource((Class<? extends IBaseResource>) getResourceType(theRequest, theReq).getImplementingClass()); query = search.forResource((Class<? extends IBaseResource>) getResourceType(theRequest, theReq).getImplementingClass());
} catch (ServletException e) { } catch (ServletException e) {
theModel.put("errorMsg", e.toString()); theModel.put("errorMsg", toDisplayError(e.toString(), e));
return "resource"; return "resource";
} }
clientCodeJsonWriter.name("resource"); clientCodeJsonWriter.name("resource");
@ -463,7 +456,7 @@ public class Controller extends BaseController {
String limit = theReq.getParameter("resource-search-limit"); String limit = theReq.getParameter("resource-search-limit");
if (isNotBlank(limit)) { if (isNotBlank(limit)) {
if (!limit.matches("[0-9]+")) { if (!limit.matches("[0-9]+")) {
theModel.put("errorMsg", "Search limit must be a numeric value."); theModel.put("errorMsg", toDisplayError("Search limit must be a numeric value.", null));
return "resource"; return "resource";
} }
int limitInt = Integer.parseInt(limit); int limitInt = Integer.parseInt(limit);
@ -534,12 +527,12 @@ public class Controller extends BaseController {
} else if (body.startsWith("<")) { } else if (body.startsWith("<")) {
// XML content // XML content
} else { } else {
theModel.put("errorMsg", "Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding)."); theModel.put("errorMsg", toDisplayError("Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding).", null));
return "home"; return "home";
} }
} catch (DataFormatException e) { } catch (DataFormatException e) {
ourLog.warn("Failed to parse bundle", e); ourLog.warn("Failed to parse bundle", e);
theModel.put("errorMsg", "Failed to parse transaction bundle body. Error was: " + e.getMessage()); theModel.put("errorMsg", toDisplayError("Failed to parse transaction bundle body. Error was: " + e.getMessage(), e));
return "home"; return "home";
} }
@ -587,7 +580,7 @@ public class Controller extends BaseController {
String body = validate ? theReq.getParameter("resource-validate-body") : theReq.getParameter("resource-create-body"); String body = validate ? theReq.getParameter("resource-validate-body") : theReq.getParameter("resource-create-body");
if (isBlank(body)) { if (isBlank(body)) {
theModel.put("errorMsg", "No message body specified"); theModel.put("errorMsg", toDisplayError("No message body specified", null));
return; return;
} }
@ -602,12 +595,12 @@ public class Controller extends BaseController {
resource = getContext(theRequest).newXmlParser().parseResource(type, body); resource = getContext(theRequest).newXmlParser().parseResource(type, body);
client.setEncoding(EncodingEnum.XML); client.setEncoding(EncodingEnum.XML);
} else { } else {
theModel.put("errorMsg", "Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding)."); theModel.put("errorMsg", toDisplayError("Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding).", null));
return; return;
} }
} catch (DataFormatException e) { } catch (DataFormatException e) {
ourLog.warn("Failed to parse resource", e); ourLog.warn("Failed to parse resource", e);
theModel.put("errorMsg", "Failed to parse message body. Error was: " + e.getMessage()); theModel.put("errorMsg", toDisplayError("Failed to parse message body. Error was: " + e.getMessage(), e));
return; return;
} }