2

我想知道是否可以让 ExceptionMapper 处理 Exception 的子类而不仅仅是 RuntimeException 的子类?

以下面的代码为例。如果 ExampleException 扩展 RuntimeException 则测试通过且没有错误。但是,如果 ExampleException 扩展了 Exception 则测试会引发错误。请参阅下面的错误输出。

以下是四个类:

  1. 示例异常
  2. 示例异常映射器
  3. 示例休息
  4. 示例RestTest

这是代码:

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();
        }
    }
}

错误堆栈跟踪:

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)
4

2 回答 2

1

这是固定在主干上(https://issues.apache.org/jira/browse/TOMEE-918

您可以使用 ExceptionMapper 和 ex.getCause() 解决它

于 2013-04-27T20:42:47.600 回答
1

这太弱了

这是一种解决方法:

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();
    }
}
于 2013-06-26T15:36:20.117 回答