2013-04-27 50 views
2

我想知道是否有可能有ExceptionMapper處理Exception的子類而不只是RuntimeException的子類?ExceptionMapper(Java EE 6)可以處理NON RuntimeException嗎?

以下面的代碼爲例。如果ExampleException擴展了RuntimeException,那麼測試通過時沒有錯誤。但是,如果ExampleException擴展了Exception,那麼測試會引發一個錯誤。請參閱下面的錯誤輸出。

以下是四類:

  1. ExampleException
  2. ExampleExceptionMapper
  3. ExampleRest
  4. ExampleRestTest

下面是代碼:

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) 

回答

1

這是固定不變的主幹(https://issues.apache.org/jira/browse/TOMEE-918

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

+0

感謝羅曼!計劃何時發佈1.6.0?你能否詳細說明解決方法? – 2013-04-27 21:09:04

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