You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/09/25 22:12:47 UTC

svn commit: r1526284 - in /cxf/trunk: core/src/main/java/org/apache/cxf/logging/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ systests/jaxrs/src/test/java/org/apache/cxf/systest...

Author: sergeyb
Date: Wed Sep 25 20:12:46 2013
New Revision: 1526284

URL: http://svn.apache.org/r1526284
Log:
[CXF-5300] Trying to map exceptions thrown from in or out interceptors to JAX-RS Response

Added:
    cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSDefaultFaultOutInterceptor.java
      - copied, changed from r1526146, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXBDefaultFaultOutInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java   (with props)
Removed:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXBDefaultFaultOutInterceptor.java
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutInterceptor.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java

Added: cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java
URL: http://svn.apache.org/viewvc/cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java?rev=1526284&view=auto
==============================================================================
--- cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java (added)
+++ cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java Wed Sep 25 20:12:46 2013
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cxf.logging;
+
+import org.apache.cxf.message.Message;
+
+/**
+ * Utility FaultListener for blocking the default PhaseInterceptorChain fault logging
+ */
+public class NoOpFaultListener implements FaultListener {
+
+    @Override
+    public boolean faultOccurred(Exception exception, String description, Message message) {
+        return false;
+    }
+
+}

Propchange: cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/core/src/main/java/org/apache/cxf/logging/NoOpFaultListener.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java Wed Sep 25 20:12:46 2013
@@ -31,7 +31,7 @@ import org.apache.cxf.common.injection.N
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.interceptor.StaxOutInterceptor;
-import org.apache.cxf.jaxrs.interceptor.JAXBDefaultFaultOutInterceptor;
+import org.apache.cxf.jaxrs.interceptor.JAXRSDefaultFaultOutInterceptor;
 import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor;
 import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
 import org.apache.cxf.service.Service;
@@ -63,7 +63,7 @@ public class JAXRSBindingFactory extends
         
         binding.getOutInterceptors().add(new JAXRSOutInterceptor());
         
-        binding.getOutFaultInterceptors().add(new JAXBDefaultFaultOutInterceptor());
+        binding.getOutFaultInterceptors().add(new JAXRSDefaultFaultOutInterceptor());
         binding.getOutFaultInterceptors().add(new StaxOutInterceptor());
 
         return binding;

Copied: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSDefaultFaultOutInterceptor.java (from r1526146, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXBDefaultFaultOutInterceptor.java)
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSDefaultFaultOutInterceptor.java?p2=cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSDefaultFaultOutInterceptor.java&p1=cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXBDefaultFaultOutInterceptor.java&r1=1526146&r2=1526284&rev=1526284&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXBDefaultFaultOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSDefaultFaultOutInterceptor.java Wed Sep 25 20:12:46 2013
@@ -34,14 +34,14 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.staxutils.StaxUtils;
 
-public class JAXBDefaultFaultOutInterceptor extends AbstractOutDatabindingInterceptor {
+public class JAXRSDefaultFaultOutInterceptor extends AbstractOutDatabindingInterceptor {
 
-    private static final ResourceBundle BUNDLE = BundleUtils.getBundle(JAXBDefaultFaultOutInterceptor.class);
+    private static final ResourceBundle BUNDLE = BundleUtils.getBundle(JAXRSDefaultFaultOutInterceptor.class);
 
-    public JAXBDefaultFaultOutInterceptor() {
+    public JAXRSDefaultFaultOutInterceptor() {
         super(Phase.MARSHAL);
     }
-    public JAXBDefaultFaultOutInterceptor(String phase) {
+    public JAXRSDefaultFaultOutInterceptor(String phase) {
         super(phase);
     }
 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java Wed Sep 25 20:12:46 2013
@@ -20,6 +20,7 @@
 package org.apache.cxf.jaxrs.interceptor;
 
 import java.io.IOException;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.ResourceBundle;
@@ -37,8 +38,11 @@ import javax.ws.rs.core.Response;
 
 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.interceptor.OutgoingChainInterceptor;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.RequestPreprocessor;
 import org.apache.cxf.jaxrs.impl.UriInfoImpl;
@@ -49,7 +53,11 @@ import org.apache.cxf.jaxrs.model.URITem
 import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
 import org.apache.cxf.jaxrs.utils.HttpUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.logging.FaultListener;
+import org.apache.cxf.logging.NoOpFaultListener;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageContentsList;
+import org.apache.cxf.message.MessageImpl;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
@@ -64,28 +72,6 @@ public class JAXRSInInterceptor extends 
         super(Phase.UNMARSHAL);
     }
 
-    @Override
-    public void handleFault(Message message) {
-        super.handleFault(message);
-        
-        LOG.fine("Cleanup thread local variables");
-        
-        Object rootInstance = message.getExchange().remove(JAXRSUtils.ROOT_INSTANCE);
-        Object rootProvider = message.getExchange().remove(JAXRSUtils.ROOT_PROVIDER);
-        if (rootInstance != null && rootProvider != null) {
-            try {
-                ((ResourceProvider)rootProvider).releaseInstance(message, rootInstance);
-            } catch (Throwable tex) {
-                LOG.warning("Exception occurred during releasing the service instance, " + tex.getMessage());
-            }
-        }
-        ServerProviderFactory.getInstance(message).clearThreadLocalProxies();
-        ClassResourceInfo cri = (ClassResourceInfo)message.getExchange().get(JAXRSUtils.ROOT_RESOURCE_CLASS);
-        if (cri != null) {
-            cri.clearThreadLocalProxies();
-        }
-    }
-    
     public void handleMessage(Message message) {
         
         if (message.getExchange().get(OperationResourceInfo.class) != null) {
@@ -261,4 +247,55 @@ public class JAXRSInInterceptor extends 
             || MessageUtils.isTrue(HttpUtils.getProtocolHeader(message, Message.ONE_WAY_REQUEST, null));
         message.getExchange().setOneWay(oneway);
     }
+    
+    @Override
+    public void handleFault(Message message) {
+        super.handleFault(message);
+        
+        Response r = JAXRSUtils.convertFaultToResponse(message.getContent(Exception.class), 
+                                                       message);
+        if (r != null) {
+            message.removeContent(Exception.class);
+            message.getInterceptorChain().setFaultObserver(null);
+            if (message.getContextualProperty(FaultListener.class.getName()) == null) {
+                message.put(FaultListener.class.getName(), new NoOpFaultListener());
+            }
+            
+            Endpoint e = message.getExchange().get(Endpoint.class);
+            Message mout = new MessageImpl();
+            mout.setContent(List.class, new MessageContentsList(r));
+            mout.setExchange(message.getExchange());
+            mout = e.getBinding().createMessage(mout);
+            mout.setInterceptorChain(OutgoingChainInterceptor.getOutInterceptorChain(message.getExchange()));
+            message.getExchange().setOutMessage(mout);
+            
+            
+            Iterator<Interceptor<? extends Message>> iterator = message.getInterceptorChain().iterator();
+            while (iterator.hasNext()) {
+                Interceptor<? extends Message> inInterceptor = iterator.next();
+                if (inInterceptor.getClass() == OutgoingChainInterceptor.class) {
+                    ((OutgoingChainInterceptor)inInterceptor).handleMessage(message);
+                    return;
+                }
+            }
+        }
+        
+        
+        LOG.fine("Cleanup thread local variables");
+        
+        Object rootInstance = message.getExchange().remove(JAXRSUtils.ROOT_INSTANCE);
+        Object rootProvider = message.getExchange().remove(JAXRSUtils.ROOT_PROVIDER);
+        if (rootInstance != null && rootProvider != null) {
+            try {
+                ((ResourceProvider)rootProvider).releaseInstance(message, rootInstance);
+            } catch (Throwable tex) {
+                LOG.warning("Exception occurred during releasing the service instance, " + tex.getMessage());
+            }
+        }
+        ServerProviderFactory.getInstance(message).clearThreadLocalProxies();
+        ClassResourceInfo cri = (ClassResourceInfo)message.getExchange().get(JAXRSUtils.ROOT_RESOURCE_CLASS);
+        if (cri != null) {
+            cri.clearThreadLocalProxies();
+        }
+    }
 }

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java?rev=1526284&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java Wed Sep 25 20:12:46 2013
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.cxf.jaxrs.interceptor;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.logging.FaultListener;
+import org.apache.cxf.logging.NoOpFaultListener;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageContentsList;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.phase.PhaseManager;
+
+public class JAXRSOutExceptionMapperInterceptor extends AbstractOutDatabindingInterceptor {
+    private static final Logger LOG = LogUtils.getL7dLogger(JAXRSOutExceptionMapperInterceptor.class);
+    
+    public JAXRSOutExceptionMapperInterceptor() {
+        super(Phase.SETUP);
+    }
+    public JAXRSOutExceptionMapperInterceptor(String phase) {
+        super(phase);
+    }
+    @Override
+    public void handleFault(Message message) {
+        if (Boolean.TRUE == message.get("jaxrs.out.fault")) {
+            // Exception comes from JAXRSOutInterceptor or the one which follows it
+            return;
+        }
+        
+        Response r = JAXRSUtils.convertFaultToResponse(message.getContent(Exception.class), 
+                                                       message);
+        if (r != null) {
+            message.removeContent(Exception.class);
+            message.getInterceptorChain().setFaultObserver(null);
+            message.setContent(List.class, new MessageContentsList(r));
+            if (message.getContextualProperty(FaultListener.class.getName()) == null) {
+                message.put(FaultListener.class.getName(), new NoOpFaultListener());
+            }
+            
+            PhaseManager pm = message.getExchange().get(Bus.class).getExtension(PhaseManager.class);
+            PhaseInterceptorChain chain = new PhaseInterceptorChain(pm.getOutPhases());
+            
+            boolean jaxrsOutOrAfter = false;
+            Iterator<Interceptor<? extends Message>> iterator = message.getInterceptorChain().iterator();
+            while (iterator.hasNext()) {
+                Interceptor<? extends Message> outInterceptor = iterator.next();
+                if (outInterceptor.getClass() == JAXRSOutInterceptor.class) {
+                    jaxrsOutOrAfter = true;
+                }
+                if (jaxrsOutOrAfter) {
+                    chain.add(outInterceptor);
+                }
+            }
+            
+            message.setInterceptorChain(chain);
+            message.getInterceptorChain().doInterceptStartingAt(message, JAXRSOutInterceptor.class.getName());
+            return;
+        }
+        
+        
+        LOG.fine("Cleanup thread local variables");
+        
+        Object rootInstance = message.getExchange().remove(JAXRSUtils.ROOT_INSTANCE);
+        Object rootProvider = message.getExchange().remove(JAXRSUtils.ROOT_PROVIDER);
+        if (rootInstance != null && rootProvider != null) {
+            try {
+                ((ResourceProvider)rootProvider).releaseInstance(message, rootInstance);
+            } catch (Throwable tex) {
+                LOG.warning("Exception occurred during releasing the service instance, " + tex.getMessage());
+            }
+        }
+        ServerProviderFactory.getInstance(message).clearThreadLocalProxies();
+        ClassResourceInfo cri = (ClassResourceInfo)message.getExchange().get(JAXRSUtils.ROOT_RESOURCE_CLASS);
+        if (cri != null) {
+            cri.clearThreadLocalProxies();
+        }
+    }
+    @Override
+    public void handleMessage(Message message) throws Fault {
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutExceptionMapperInterceptor.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java Wed Sep 25 20:12:46 2013
@@ -77,11 +77,13 @@ public class JAXRSOutInterceptor extends
     public JAXRSOutInterceptor() {
         super(Phase.MARSHAL);
     }
-
+    
     public void handleMessage(Message message) {
         ServerProviderFactory providerFactory = ServerProviderFactory.getInstance(message);
         try {
             processResponse(providerFactory, message);
+        } catch (Exception ex) {
+            message.put("jaxrs.out.fault", Boolean.TRUE);    
         } finally {
             Object rootInstance = message.getExchange().remove(JAXRSUtils.ROOT_INSTANCE);
             Object rootProvider = message.getExchange().remove(JAXRSUtils.ROOT_PROVIDER);
@@ -481,4 +483,8 @@ public class JAXRSOutInterceptor extends
     private boolean isResponseHeadersCopied(Message message) {
         return MessageUtils.isTrue(message.get(AbstractHTTPDestination.RESPONSE_HEADERS_COPIED));
     }
+    
+    public void handleFault(Message message) {
+        message.put("jaxrs.out.fault", Boolean.TRUE);
+    }
 }

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer.java Wed Sep 25 20:12:46 2013
@@ -37,6 +37,7 @@ import org.apache.cxf.jaxrs.ext.search.Q
 import org.apache.cxf.jaxrs.ext.search.SearchBean;
 import org.apache.cxf.jaxrs.ext.search.SearchContextProvider;
 import org.apache.cxf.jaxrs.ext.search.sql.SQLPrinterVisitor;
+import org.apache.cxf.jaxrs.interceptor.JAXRSOutExceptionMapperInterceptor;
 import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
 import org.apache.cxf.jaxrs.provider.BinaryDataProvider;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
@@ -78,8 +79,12 @@ public class BookServer extends Abstract
         providers.add(new SearchContextProvider());
         providers.add(new QueryContextProvider());
         sf.setProviders(providers);
+        List<Interceptor<? extends Message>> inInts = new ArrayList<Interceptor<? extends Message>>();
+        inInts.add(new CustomInFaultyInterceptor());
+        sf.setInInterceptors(inInts);
         List<Interceptor<? extends Message>> outInts = new ArrayList<Interceptor<? extends Message>>();
         outInts.add(new CustomOutInterceptor());
+        outInts.add(new JAXRSOutExceptionMapperInterceptor());
         sf.setOutInterceptors(outInts);
         List<Interceptor<? extends Message>> outFaultInts = new ArrayList<Interceptor<? extends Message>>();
         outFaultInts.add(new CustomOutFaultInterceptor());

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Wed Sep 25 20:12:46 2013
@@ -496,6 +496,18 @@ public class BookStore {
         return Response.status(401).entity("This is 401").build();
     }
     
+    @GET
+    @Path("infault")
+    public Response infault() throws Exception {
+        throw new RuntimeException();
+    }
+    
+    @GET
+    @Path("outfault")
+    public Response outfault() throws Exception {
+        return Response.ok().build();
+    }
+    
     @POST
     @Path("/collections")
     @Produces({"application/xml", "application/json" })

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutInterceptor.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutInterceptor.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutInterceptor.java Wed Sep 25 20:12:46 2013
@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MultivaluedMap;
 
@@ -42,6 +43,11 @@ public class CustomOutInterceptor extend
     @SuppressWarnings("unchecked")
     public void handleMessage(Message message) throws Fault {
         
+        String requestUri = (String)message.getExchange().getInMessage().get(Message.REQUEST_URI);
+        if (requestUri.endsWith("/outfault")) {
+            throw new WebApplicationException(403);
+        }
+        
         HttpHeaders requestHeaders = new HttpHeadersImpl(message.getExchange().getInMessage());
         if (requestHeaders.getHeaderString("PLAIN-MAP") != null) {
             Map<String, List<String>> headers = (Map<String, List<String>>)

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=1526284&r1=1526283&r2=1526284&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Wed Sep 25 20:12:46 2013
@@ -428,6 +428,27 @@ public class JAXRSClientServerBookTest e
         assertEquals(401, r.getStatus());
         assertEquals("This is 401", getStringFromInputStream((InputStream)r.getEntity()));
     }
+    
+    @Test
+    public void testCapturedServerInFault() throws Exception {
+        
+        String endpointAddress =
+            "http://localhost:" + PORT + "/bookstore/infault"; 
+        WebClient wc = WebClient.create(endpointAddress);
+        Response r = wc.get();
+        assertEquals(401, r.getStatus());
+    }
+    
+    @Test
+    public void testCapturedServerOutFault() throws Exception {
+        
+        String endpointAddress =
+            "http://localhost:" + PORT + "/bookstore/outfault"; 
+        WebClient wc = WebClient.create(endpointAddress);
+        WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(1000000L);
+        Response r = wc.get();
+        assertEquals(403, r.getStatus());
+    }
 
     @Test
     public void testGetCollectionOfBooks() throws Exception {