This commit is contained in:
James Agnew 2015-04-15 10:57:15 -04:00
parent 1f51c69126
commit ddd68b8d57
3 changed files with 7 additions and 172 deletions

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ Servers/
*.log* *.log*
nohup.out nohup.out
.DS_Store .DS_Store
*.orig
# Vagrant stuff. # Vagrant stuff.
.vagrant .vagrant

View File

@ -1,172 +0,0 @@
package ca.uhn.fhir.rest.server.interceptor;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.exception.ExceptionUtils;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
import ca.uhn.fhir.rest.method.Request;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.RestfulServer.NarrativeModeEnum;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public class ExceptionHandlingInterceptor extends InterceptorAdapter {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionHandlingInterceptor.class);
private Class<?>[] myReturnStackTracesForExceptionTypes;
/**
* If any server methods throw an exception which extends any of the given exception types, the exception
* stack trace will be returned to the user. This can be useful for helping to diagnose issues, but may
* not be desirable for production situations.
*
* @param theExceptionTypes The exception types for which to return the stack trace to the user.
* @return Returns an instance of this interceptor, to allow for easy method chaining.
*/
public ExceptionHandlingInterceptor setReturnStackTracesForExceptionTypes(Class<?>... theExceptionTypes) {
myReturnStackTracesForExceptionTypes = theExceptionTypes;
return this;
}
@Override
<<<<<<< HEAD
public boolean handleException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
=======
public boolean handleException(RestfulServer theRestfulServer, RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
ourLog.error("AA", theException);
>>>>>>> 5956ab75fd9186ccc8b9836b60bc421b19d3d288
BaseOperationOutcome oo = null;
int statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR;
FhirContext ctx = theRestfulServer.getFhirContext();
if (theException instanceof BaseServerResponseException) {
oo = ((BaseServerResponseException) theException).getOperationOutcome();
statusCode = ((BaseServerResponseException) theException).getStatusCode();
}
/*
* Generate an OperationOutcome to return, unless the exception throw by the resource provider had one
*/
if (oo == null) {
try {
oo = (BaseOperationOutcome) ctx.getResourceDefinition("OperationOutcome").getImplementingClass().newInstance();
} catch (Exception e1) {
ourLog.error("Failed to instantiate OperationOutcome resource instance", e1);
throw new ServletException("Failed to instantiate OperationOutcome resource instance", e1);
}
BaseIssue issue = oo.addIssue();
issue.getSeverityElement().setValue("error");
if (theException instanceof InternalErrorException) {
ourLog.error("Failure during REST processing", theException);
populateDetails(theException, issue);
} else if (theException instanceof BaseServerResponseException) {
ourLog.warn("Failure during REST processing: {}", theException);
BaseServerResponseException baseServerResponseException = (BaseServerResponseException) theException;
statusCode = baseServerResponseException.getStatusCode();
populateDetails(theException, issue);
if (baseServerResponseException.getAdditionalMessages() != null) {
for (String next : baseServerResponseException.getAdditionalMessages()) {
BaseIssue issue2 = oo.addIssue();
issue2.getSeverityElement().setValue("error");
issue2.setDetails(next);
}
}
} else {
ourLog.error("Failure during REST processing: " + theException.toString(), theException);
populateDetails(theException, issue);
statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR;
}
} else {
ourLog.error("Unknown error during processing", theException);
}
// Add headers associated with the specific error code
if (theException instanceof BaseServerResponseException) {
Map<String, String[]> additional = ((BaseServerResponseException) theException).getAssociatedHeaders();
if (additional != null) {
for (Entry<String, String[]> next : additional.entrySet()) {
if (isNotBlank(next.getKey()) && next.getValue() != null) {
String nextKey = next.getKey();
for (String nextValue : next.getValue()) {
theResponse.addHeader(nextKey, nextValue);
}
}
}
}
}
boolean requestIsBrowser = RestfulServer.requestIsBrowser(theRequest);
String fhirServerBase = theRestfulServer.getServerBaseForRequest(theRequest);
RestfulServerUtils.streamResponseAsResource(theRestfulServer, theResponse, oo, RestfulServerUtils.determineResponseEncodingNoDefault(theRequest), true, requestIsBrowser,
NarrativeModeEnum.NORMAL, statusCode, false, fhirServerBase);
<<<<<<< HEAD
// theResponse.setStatus(statusCode);
// theRequestDetails.getServer().addHeadersToResponse(theResponse);
// theResponse.setContentType("text/plain");
// theResponse.setCharacterEncoding("UTF-8");
// theResponse.getWriter().append(theException.getMessage());
// theResponse.getWriter().close();
=======
theResponse.setStatus(statusCode);
theRestfulServer.addHeadersToResponse(theResponse);
theResponse.setContentType("text/plain");
theResponse.setCharacterEncoding("UTF-8");
theResponse.getWriter().append(theException.getMessage());
theResponse.getWriter().close();
>>>>>>> 5956ab75fd9186ccc8b9836b60bc421b19d3d288
return false;
}
private void populateDetails(Throwable theException, BaseIssue issue) {
if (myReturnStackTracesForExceptionTypes != null) {
for (Class<?> next : myReturnStackTracesForExceptionTypes) {
if (next.isAssignableFrom(theException.getClass())) {
issue.getDetailsElement().setValue(theException.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(theException));
return;
}
}
}
issue.getDetailsElement().setValue(theException.getMessage());
}
}

View File

@ -130,6 +130,12 @@
JPA server failed to index resources containing ContactPointDt elements with JPA server failed to index resources containing ContactPointDt elements with
populated values (e.g. Patient.telecom). Thanks to Mohammad Jafari for reporting! populated values (e.g. Patient.telecom). Thanks to Mohammad Jafari for reporting!
</action> </action>
<action type="fix" issue="155" dev="wdebeau1">
Terser's IModelVisitor now supplies to the path to the element. This is
an API change, but I don't think there are many users of the IModelVisitor yet.
Please let us know if this is a big hardship and we can find an alternate way
of making this change.
</action>
</release> </release>
<release version="0.9" date="2015-Mar-14"> <release version="0.9" date="2015-Mar-14">
<action type="add"> <action type="add">