Fix exception handling

This commit is contained in:
Sebastien Riviere 2016-05-13 15:34:55 +02:00
parent 462ae8cb1f
commit 6e1b848ea6
2 changed files with 308 additions and 292 deletions

View File

@ -10,7 +10,7 @@ package ca.uhn.fhir.jaxrs.server;
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -22,8 +22,6 @@ package ca.uhn.fhir.jaxrs.server;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Collections;
import java.util.List;
import javax.interceptor.Interceptors; import javax.interceptor.Interceptors;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -41,7 +39,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor; import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
import ca.uhn.fhir.jaxrs.server.util.JaxRsMethodBindings; import ca.uhn.fhir.jaxrs.server.util.JaxRsMethodBindings;
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest; import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder; import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
@ -60,47 +57,45 @@ import ca.uhn.fhir.rest.server.IRestfulServer;
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
*/ */
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN }) @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, @Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
Constants.CT_FHIR_XML })
@Interceptors(JaxRsExceptionInterceptor.class) @Interceptors(JaxRsExceptionInterceptor.class)
public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> extends AbstractJaxRsProvider public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> extends AbstractJaxRsProvider
implements IRestfulServer<JaxRsRequest>, IResourceProvider { implements IRestfulServer<JaxRsRequest>, IResourceProvider {
/** the method bindings for this class */ /** the method bindings for this class */
private final JaxRsMethodBindings theBindings; private final JaxRsMethodBindings theBindings;
/** /**
* The default constructor. The method bindings are retrieved from the class * The default constructor. The method bindings are retrieved from the class
* being constructed. * being constructed.
*/ */
protected AbstractJaxRsResourceProvider() { protected AbstractJaxRsResourceProvider() {
super(); super();
theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass()); theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass());
} }
/** /**
* Provides the ability to specify the {@link FhirContext}. * Provides the ability to specify the {@link FhirContext}.
* @param ctx the {@link FhirContext} instance. * @param ctx the {@link FhirContext} instance.
*/ */
protected AbstractJaxRsResourceProvider(FhirContext ctx) { protected AbstractJaxRsResourceProvider(final FhirContext ctx) {
super(ctx); super(ctx);
theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass()); theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass());
} }
/**
/** * This constructor takes in an explicit interface class. This subclass
* This constructor takes in an explicit interface class. This subclass * should be identical to the class being constructed but is given
* should be identical to the class being constructed but is given * explicitly in order to avoid issues with proxy classes in a jee
* explicitly in order to avoid issues with proxy classes in a jee * environment.
* environment. *
* * @param theProviderClass the interface of the class
* @param theProviderClass the interface of the class */
*/ protected AbstractJaxRsResourceProvider(final Class<? extends AbstractJaxRsProvider> theProviderClass) {
protected AbstractJaxRsResourceProvider(Class<? extends AbstractJaxRsProvider> theProviderClass) { super();
super(); theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass);
theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass); }
}
/** /**
* This constructor takes in an explicit interface class. This subclass * This constructor takes in an explicit interface class. This subclass
@ -111,62 +106,66 @@ public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> ext
* @param ctx the {@link FhirContext} instance. * @param ctx the {@link FhirContext} instance.
* @param theProviderClass the interface of the class * @param theProviderClass the interface of the class
*/ */
protected AbstractJaxRsResourceProvider(FhirContext ctx, Class<? extends AbstractJaxRsProvider> theProviderClass) { protected AbstractJaxRsResourceProvider(final FhirContext ctx, final Class<? extends AbstractJaxRsProvider> theProviderClass) {
super(ctx); super(ctx);
theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass); theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass);
} }
/** /**
* The base for request for a resource provider has the following form:</br> * The base for request for a resource provider has the following form:</br>
* {@link AbstractJaxRsResourceProvider#getBaseForServer() * {@link AbstractJaxRsResourceProvider#getBaseForServer()
* getBaseForServer()} + "/" + * getBaseForServer()} + "/" +
* {@link AbstractJaxRsResourceProvider#getResourceType() getResourceType()} * {@link AbstractJaxRsResourceProvider#getResourceType() getResourceType()}
* .{@link java.lang.Class#getSimpleName() getSimpleName()} * .{@link java.lang.Class#getSimpleName() getSimpleName()}
*/ */
@Override @Override
public String getBaseForRequest() { public String getBaseForRequest() {
try { try {
return new URL(getUriInfo().getBaseUri().toURL(), getResourceType().getSimpleName()).toExternalForm(); return new URL(getUriInfo().getBaseUri().toURL(), getResourceType().getSimpleName()).toExternalForm();
} catch (Exception e) { }
// cannot happen catch (final Exception e) {
return null; // cannot happen
} return null;
} }
}
/** /**
* Create a new resource with a server assigned id * Create a new resource with a server assigned id
* *
* @param resource the body of the post method containing resource being created in a xml/json form * @param resource the body of the post method containing resource being created in a xml/json form
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#create">https://www.hl7. org/fhir/http.html#create</a> * @see <a href="https://www.hl7.org/fhir/http.html#create">https://www.hl7. org/fhir/http.html#create</a>
*/ */
@POST @POST
public Response create(final String resource) throws IOException { public Response create(final String resource)
return execute(getResourceRequest(RequestTypeEnum.POST, RestOperationTypeEnum.CREATE).resource(resource)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.POST, RestOperationTypeEnum.CREATE).resource(resource));
}
/** /**
* Search the resource type based on some filter criteria * Search the resource type based on some filter criteria
* *
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a> * @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a>
*/ */
@POST @POST
@Path("/_search") @Path("/_search")
public Response searchWithPost() throws IOException { public Response searchWithPost()
return execute(getResourceRequest(RequestTypeEnum.POST, RestOperationTypeEnum.SEARCH_TYPE)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.POST, RestOperationTypeEnum.SEARCH_TYPE));
}
/** /**
* Search the resource type based on some filter criteria * Search the resource type based on some filter criteria
* *
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a> * @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a>
*/ */
@GET @GET
public Response search() throws IOException { public Response search()
return execute(getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.SEARCH_TYPE)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.SEARCH_TYPE));
}
/** /**
* Update an existing resource based on the given condition * Update an existing resource based on the given condition
@ -175,23 +174,25 @@ public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> ext
* @see <a href="https://www.hl7.org/fhir/http.html#update">https://www.hl7.org/fhir/http.html#update</a> * @see <a href="https://www.hl7.org/fhir/http.html#update">https://www.hl7.org/fhir/http.html#update</a>
*/ */
@PUT @PUT
public Response conditionalUpdate(final String resource) throws IOException { public Response conditionalUpdate(final String resource)
throws IOException {
return execute(getResourceRequest(RequestTypeEnum.PUT, RestOperationTypeEnum.UPDATE).resource(resource)); return execute(getResourceRequest(RequestTypeEnum.PUT, RestOperationTypeEnum.UPDATE).resource(resource));
} }
/** /**
* Update an existing resource by its id (or create it if it is new) * Update an existing resource by its id (or create it if it is new)
* *
* @param id the id of the resource * @param id the id of the resource
* @param resource the body contents for the put method * @param resource the body contents for the put method
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#update">https://www.hl7.org/fhir/http.html#update</a> * @see <a href="https://www.hl7.org/fhir/http.html#update">https://www.hl7.org/fhir/http.html#update</a>
*/ */
@PUT @PUT
@Path("/{id}") @Path("/{id}")
public Response update(@PathParam("id") final String id, final String resource) throws IOException { public Response update(@PathParam("id") final String id, final String resource)
return execute(getResourceRequest(RequestTypeEnum.PUT, RestOperationTypeEnum.UPDATE).id(id).resource(resource)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.PUT, RestOperationTypeEnum.UPDATE).id(id).resource(resource));
}
/** /**
* Delete a resource based on the given condition * Delete a resource based on the given condition
@ -200,157 +201,163 @@ public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> ext
* @see <a href="https://www.hl7.org/fhir/http.html#delete">https://www.hl7.org/fhir/http.html#delete</a> * @see <a href="https://www.hl7.org/fhir/http.html#delete">https://www.hl7.org/fhir/http.html#delete</a>
*/ */
@DELETE @DELETE
public Response delete() throws IOException { public Response delete()
throws IOException {
return execute(getResourceRequest(RequestTypeEnum.DELETE, RestOperationTypeEnum.DELETE)); return execute(getResourceRequest(RequestTypeEnum.DELETE, RestOperationTypeEnum.DELETE));
} }
/** /**
* Delete a resource * Delete a resource
* *
* @param id the id of the resource to delete * @param id the id of the resource to delete
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#delete">https://www.hl7.org/fhir/http.html#delete</a> * @see <a href="https://www.hl7.org/fhir/http.html#delete">https://www.hl7.org/fhir/http.html#delete</a>
*/ */
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
public Response delete(@PathParam("id") final String id) throws IOException { public Response delete(@PathParam("id") final String id)
return execute(getResourceRequest(RequestTypeEnum.DELETE, RestOperationTypeEnum.DELETE).id(id)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.DELETE, RestOperationTypeEnum.DELETE).id(id));
}
/** /**
* Read the current state of the resource * Read the current state of the resource
* *
* @param id the id of the resource to read * @param id the id of the resource to read
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#read">https://www.hl7.org/fhir/http.html#read</a> * @see <a href="https://www.hl7.org/fhir/http.html#read">https://www.hl7.org/fhir/http.html#read</a>
*/ */
@GET @GET
@Path("/{id}") @Path("/{id}")
public Response find(@PathParam("id") final String id) throws IOException { public Response find(@PathParam("id") final String id)
return execute(getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.READ).id(id)); throws IOException {
} return execute(getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.READ).id(id));
}
/** /**
* Execute a custom operation * Execute a custom operation
* *
* @param resource the resource to create * @param resource the resource to create
* @param requestType the type of request * @param requestType the type of request
* @param id the id of the resource on which to perform the operation * @param id the id of the resource on which to perform the operation
* @param operationName the name of the operation to execute * @param operationName the name of the operation to execute
* @param operationType the rest operation type * @param operationType the rest operation type
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/operations.html">https://www.hl7.org/fhir/operations.html</a> * @see <a href="https://www.hl7.org/fhir/operations.html">https://www.hl7.org/fhir/operations.html</a>
*/ */
protected Response customOperation(final String resource, RequestTypeEnum requestType, String id, protected Response customOperation(final String resource, final RequestTypeEnum requestType, final String id,
String operationName, RestOperationTypeEnum operationType) throws IOException { final String operationName, final RestOperationTypeEnum operationType)
Builder request = getResourceRequest(requestType, operationType).resource(resource).id(id); throws IOException {
return execute(request, operationName); final Builder request = getResourceRequest(requestType, operationType).resource(resource).id(id);
} return execute(request, operationName);
}
/** /**
* Retrieve the update history for a particular resource * Retrieve the update history for a particular resource
* *
* @param id the id of the resource * @param id the id of the resource
* @param version the version of the resource * @param version the version of the resource
* @return the response * @return the response
* @see <a href="https://www.hl7.org/fhir/http.html#history">https://www.hl7.org/fhir/http.html#history</a> * @see <a href="https://www.hl7.org/fhir/http.html#history">https://www.hl7.org/fhir/http.html#history</a>
*/ */
@GET @GET
@Path("/{id}/_history/{version}") @Path("/{id}/_history/{version}")
public Response findHistory(@PathParam("id") final String id, @PathParam("version") final String version) public Response findHistory(@PathParam("id") final String id, @PathParam("version") final String version)
throws IOException { throws IOException {
Builder theRequest = getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.VREAD).id(id) final Builder theRequest = getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.VREAD).id(id).version(version);
.version(version); return execute(theRequest);
return execute(theRequest); }
}
/** /**
* Compartment Based Access * Compartment Based Access
* *
* @param id the resource to which the compartment belongs * @param id the resource to which the compartment belongs
* @param compartment the compartment * @param compartment the compartment
* @return the repsonse * @return the repsonse
* @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a> * @see <a href="https://www.hl7.org/fhir/http.html#search">https://www.hl7.org/fhir/http.html#search</a>
* @see <a href="https://www.hl7.org/fhir/compartments.html#compartment">https://www.hl7.org/fhir/compartments.html#compartment</a> * @see <a href="https://www.hl7.org/fhir/compartments.html#compartment">https://www.hl7.org/fhir/compartments.html#compartment</a>
*/ */
@GET @GET
@Path("/{id}/{compartment}") @Path("/{id}/{compartment}")
public Response findCompartment(@PathParam("id") final String id, public Response findCompartment(@PathParam("id") final String id, @PathParam("compartment") final String compartment)
@PathParam("compartment") final String compartment) throws IOException { throws IOException {
Builder theRequest = getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.SEARCH_TYPE).id(id) final Builder theRequest = getResourceRequest(RequestTypeEnum.GET, RestOperationTypeEnum.SEARCH_TYPE).id(id).compartment(
.compartment(compartment); compartment);
return execute(theRequest, compartment); return execute(theRequest, compartment);
} }
/** /**
* Execute the method described by the requestBuilder and methodKey * Execute the method described by the requestBuilder and methodKey
* *
* @param theRequestBuilder the requestBuilder that contains the information about the request * @param theRequestBuilder the requestBuilder that contains the information about the request
* @param methodKey the key determining the method to be executed * @param methodKey the key determining the method to be executed
* @return the response * @return the response
*/ */
private Response execute(Builder theRequestBuilder, String methodKey) throws IOException { private Response execute(final Builder theRequestBuilder, final String methodKey)
JaxRsRequest theRequest = theRequestBuilder.build(); throws IOException {
BaseMethodBinding<?> method = getBinding(theRequest.getRestOperationType(), methodKey); final JaxRsRequest theRequest = theRequestBuilder.build();
try { final BaseMethodBinding<?> method = getBinding(theRequest.getRestOperationType(), methodKey);
return (Response) method.invokeServer(this, theRequest); try {
} catch (JaxRsResponseException theException) { return (Response) method.invokeServer(this, theRequest);
return new JaxRsExceptionInterceptor().convertExceptionIntoResponse(theRequest, theException); }
} catch (final Throwable theException) {
} return handleException(theRequest, theException);
}
}
/** /**
* Execute the method described by the requestBuilder * Execute the method described by the requestBuilder
* *
* @param theRequestBuilder the requestBuilder that contains the information about the request * @param theRequestBuilder the requestBuilder that contains the information about the request
* @return the response * @return the response
*/ */
private Response execute(Builder theRequestBuilder) throws IOException { private Response execute(final Builder theRequestBuilder)
return execute(theRequestBuilder, JaxRsMethodBindings.DEFAULT_METHOD_KEY); throws IOException {
} return execute(theRequestBuilder, JaxRsMethodBindings.DEFAULT_METHOD_KEY);
}
/** /**
* Return the method binding for the given rest operation * Return the method binding for the given rest operation
* *
* @param restOperation the rest operation to retrieve * @param restOperation the rest operation to retrieve
* @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation) * @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation)
* @return * @return
*/ */
protected BaseMethodBinding<?> getBinding(RestOperationTypeEnum restOperation, String theBindingKey) { protected BaseMethodBinding<?> getBinding(final RestOperationTypeEnum restOperation, final String theBindingKey) {
return getBindings().getBinding(restOperation, theBindingKey); return getBindings().getBinding(restOperation, theBindingKey);
} }
/** /**
* Default: no paging provider * Default: no paging provider
*/ */
@Override @Override
public IPagingProvider getPagingProvider() { public IPagingProvider getPagingProvider() {
return null; return null;
} }
/** /**
* Default: BundleInclusionRule.BASED_ON_INCLUDES * Default: BundleInclusionRule.BASED_ON_INCLUDES
*/ */
@Override @Override
public BundleInclusionRule getBundleInclusionRule() { public BundleInclusionRule getBundleInclusionRule() {
return BundleInclusionRule.BASED_ON_INCLUDES; return BundleInclusionRule.BASED_ON_INCLUDES;
} }
/** /**
* The resource type should return conform to the generic resource included * The resource type should return conform to the generic resource included
* in the topic * in the topic
*/ */
@Override @Override
public abstract Class<R> getResourceType(); public abstract Class<R> getResourceType();
/** /**
* Return the bindings defined in this resource provider * Return the bindings defined in this resource provider
* *
* @return the jax-rs method bindings * @return the jax-rs method bindings
*/ */
public JaxRsMethodBindings getBindings() { public JaxRsMethodBindings getBindings() {
return theBindings; return theBindings;
} }
/** /**
* Return the request builder based on the resource name for the server * Return the request builder based on the resource name for the server

View File

@ -10,7 +10,7 @@ package ca.uhn.fhir.jaxrs.server.interceptor;
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -41,36 +41,38 @@ import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
public class JaxRsExceptionInterceptor { public class JaxRsExceptionInterceptor {
/** the existing exception handler which is able to convert exception into responses*/ /** the existing exception handler which is able to convert exception into responses*/
private ExceptionHandlingInterceptor exceptionHandler; private final ExceptionHandlingInterceptor exceptionHandler;
/** /**
* The default constructor * The default constructor
*/ */
public JaxRsExceptionInterceptor() { public JaxRsExceptionInterceptor() {
this.exceptionHandler = new ExceptionHandlingInterceptor(); this.exceptionHandler = new ExceptionHandlingInterceptor();
} }
/** /**
* A utility constructor for unit testing * A utility constructor for unit testing
* @param exceptionHandler the handler for the exception conversion * @param exceptionHandler the handler for the exception conversion
*/ */
JaxRsExceptionInterceptor(ExceptionHandlingInterceptor exceptionHandler) { JaxRsExceptionInterceptor(final ExceptionHandlingInterceptor exceptionHandler) {
this.exceptionHandler = exceptionHandler; this.exceptionHandler = exceptionHandler;
} }
/** /**
* This interceptor will catch all exception and convert them using the exceptionhandler * This interceptor will catch all exception and convert them using the exceptionhandler
* @param ctx the invocation context * @param ctx the invocation context
* @return the result * @return the result
* @throws JaxRsResponseException an exception that can be handled by a jee container * @throws JaxRsResponseException an exception that can be handled by a jee container
*/ */
@AroundInvoke @AroundInvoke
public Object intercept(final InvocationContext ctx) throws JaxRsResponseException { public Object intercept(final InvocationContext ctx)
throws JaxRsResponseException {
try { try {
return ctx.proceed(); return ctx.proceed();
} catch(final Exception theException) { }
AbstractJaxRsProvider theServer = (AbstractJaxRsProvider) ctx.getTarget(); catch (final Exception theException) {
throw convertException(theServer, theException); final AbstractJaxRsProvider theServer = (AbstractJaxRsProvider) ctx.getTarget();
throw convertException(theServer, theException);
} }
} }
@ -80,41 +82,48 @@ public class JaxRsExceptionInterceptor {
* @param theException the exception to convert * @param theException the exception to convert
* @return JaxRsResponseException * @return JaxRsResponseException
*/ */
public JaxRsResponseException convertException(final AbstractJaxRsProvider theServer, final Throwable theException) { public JaxRsResponseException convertException(final AbstractJaxRsProvider theServer, final Throwable theException) {
if (theServer.withStackTrace()) { if (theServer.withStackTrace()) {
exceptionHandler.setReturnStackTracesForExceptionTypes(Throwable.class); exceptionHandler.setReturnStackTracesForExceptionTypes(Throwable.class);
} }
JaxRsRequest requestDetails = theServer.getRequest(null, null).build(); final JaxRsRequest requestDetails = theServer.getRequest(null, null).build();
BaseServerResponseException convertedException = preprocessException(theException, requestDetails); final BaseServerResponseException convertedException = preprocessException(theException, requestDetails);
return new JaxRsResponseException(convertedException); return new JaxRsResponseException(convertedException);
} }
/** /**
* This method converts an exception into a response * This method converts an exception into a response
* @param theRequest the request * @param theRequest the request
* @param theException the thrown exception * @param theException the thrown exception
* @return the response describing the error * @return the response describing the error
* @throws IOException * @throws IOException
*/ */
public Response convertExceptionIntoResponse(JaxRsRequest theRequest, JaxRsResponseException theException) public Response convertExceptionIntoResponse(final JaxRsRequest theRequest, final JaxRsResponseException theException)
throws IOException { throws IOException {
return handleExceptionWithoutServletError(theRequest, theException); return handleExceptionWithoutServletError(theRequest, theException);
} }
private BaseServerResponseException preprocessException(final Throwable theException, JaxRsRequest requestDetails) { private BaseServerResponseException preprocessException(final Throwable theException, final JaxRsRequest requestDetails) {
try { try {
return exceptionHandler.preProcessOutgoingException(requestDetails, theException, null); Throwable theExceptionToConvert = theException;
} catch(ServletException e) { if (!(theException instanceof BaseServerResponseException) && (theException.getCause() instanceof BaseServerResponseException)) {
return new InternalErrorException(e); theExceptionToConvert = theException.getCause();
} }
} return exceptionHandler.preProcessOutgoingException(requestDetails, theExceptionToConvert, null);
}
catch (final ServletException e) {
return new InternalErrorException(e);
}
}
private Response handleExceptionWithoutServletError(JaxRsRequest theRequest, BaseServerResponseException theException) throws IOException { private Response handleExceptionWithoutServletError(final JaxRsRequest theRequest, final BaseServerResponseException theException)
try { throws IOException {
return (Response) exceptionHandler.handleException(theRequest, theException); try {
} catch (ServletException e) { return (Response) exceptionHandler.handleException(theRequest, theException);
BaseServerResponseException newException = preprocessException(new InternalErrorException(e), theRequest); }
return handleExceptionWithoutServletError(theRequest, newException); catch (final ServletException e) {
} final BaseServerResponseException newException = preprocessException(new InternalErrorException(e), theRequest);
} return handleExceptionWithoutServletError(theRequest, newException);
}
}
} }