Reputation: 57
I would like to know if it is possible to have an ExceptionMapper handle subclasses of Exception and not just subclasses of RuntimeException?
Take the following code as an example. If the ExampleException extends RuntimeException then the test passes with no errors. However if the ExampleException extends Exception then the test throws an error. See below of the error output.
The following is four classes:
Here is the code:
public class ExampleException extends Exception {
public ExampleException(String message) {
super(message);
}
}
@Provider
public class ExampleExceptionMapper implements ExceptionMapper<ExampleException> {
@Override
public Response toResponse(ExampleException ex) {
return Response.ok("Exception!").build();
}
}
@Path("/example")
public class ExampleRest {
@GET
@Path(value = "/throw")
public String throwException() throws ExampleException {
throw new ExampleException("exception");
}
}
@EnableServices(value = "jaxrs")
@RunWith(ApplicationComposer.class)
public class ExampleRestTest {
@Module
public EjbModule module() {
EjbJar ejbJar = new EjbJar("beans");
ejbJar.addEnterpriseBean(new SingletonBean(ExampleRest.class));
final OpenejbJar openejbJar = new OpenejbJar();
openejbJar.addEjbDeployment(new EjbDeployment(ejbJar.getEnterpriseBeans()[0]));
final Properties properties = openejbJar.getEjbDeployment().iterator().next().getProperties();
properties.setProperty("cxf.jaxrs.providers", ExampleExceptionMapper.class.getName());
final EjbModule module = new EjbModule(ejbJar);
module.setOpenejbJar(openejbJar);
return module;
}
@Test
public void testThrowException() {
try {
assertEquals("Exception!", IO.slurp(new URL("http://localhost:4204/ExampleRestTest/example/throw/")));
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
}
Error Stacktrace:
org.apache.cxf.interceptor.Fault: example.ExampleException: exception: exception while invoking public java.lang.String example.ExampleRest.throwException() throws example.ExampleException with params [].
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:167)
at org.apache.openejb.server.cxf.rs.OpenEJBEJBInvoker.invoke(OpenEJBEJBInvoker.java:47)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:236)
at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.onMessage(CxfRsHttpListener.java:79)
at org.apache.openejb.server.httpd.OpenEJBHttpRegistry$ClassLoaderHttpListener.onMessage(OpenEJBHttpRegistry.java:99)
at org.apache.openejb.server.httpd.HttpListenerRegistry.onMessage(HttpListenerRegistry.java:69)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.process(OpenEJBHttpServer.java:246)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.processRequest(OpenEJBHttpServer.java:188)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.service(OpenEJBHttpServer.java:103)
at org.apache.openejb.server.httpd.HttpEjbServer.service(HttpEjbServer.java:63)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServiceStats.service(ServiceStats.java:54)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServiceLogger.service(ServiceLogger.java:92)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServicePool.access$201(ServicePool.java:35)
at org.apache.openejb.server.ServicePool$3.run(ServicePool.java:174)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Upvotes: 2
Views: 789
Reputation: 3277
This is soo weak.
Here is a workaround:
import org.apache.openejb.ApplicationException;
/**
* @FIXME hack for https://issues.apache.org/jira/browse/TOMEE-918
*/
@Provider
public class MyExceptionMapper implements ExceptionMapper<ApplicationException> {
@Override
public Response toResponse(ApplicationException exception) {
final Status status;
final Throwable cause = exception.getCause();
if (cause instanceof javax.ejb.EJBAccessException)
status = Status.FORBIDDEN;
else if (cause instanceof MyException)
status = Status.BAD_REQUEST;
else
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(cause.getMessage()).build();
}
}
Upvotes: 1
Reputation: 3422
that's fixed on trunk (https://issues.apache.org/jira/browse/TOMEE-918)
you can workaround it using ExceptionMapper and ex.getCause()
Upvotes: 1