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 2009/04/14 16:10:00 UTC

svn commit: r764781 - in /cxf/trunk: api/src/main/java/org/apache/cxf/message/ api/src/main/java/org/apache/cxf/phase/ rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/fronte...

Author: sergeyb
Date: Tue Apr 14 14:09:59 2009
New Revision: 764781

URL: http://svn.apache.org/viewvc?rev=764781&view=rev
Log:
JAXRS: support for HttpServletResponse writes, propogating unmapped exceptions to the container as required by JAXRS 

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ServletOutputStreamFilter.java   (with props)
Modified:
    cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
    cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
    cxf/trunk/rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/XMLFaultOutInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.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/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/MessageContextImplTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
    cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java

Modified: cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
URL: http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java (original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java Tue Apr 14 14:09:59 2009
@@ -76,6 +76,7 @@
     String REQUEST_URI = Message.class.getName() + ".REQUEST_URI";
     String QUERY_STRING = Message.class.getName() + ".QUERY_STRING";
 
+    String PROPOGATE_EXCEPTION = Message.class.getName() + ".PROPOGATE_EXCEPTION";
     /**
      * Boolean property specifying in the runtime is configured to process 
      * MTOM attachments.

Modified: cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
URL: http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java (original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java Tue Apr 14 14:09:59 2009
@@ -242,6 +242,7 @@
                     pause();
                     throw ex;
                 } catch (RuntimeException ex) {
+                    
                     if (!faultOccurred) {
      
                         faultOccurred = true;
@@ -357,8 +358,12 @@
             }
             try {
                 currentInterceptor.handleFault(message);
+            } catch (RuntimeException e) {
+                LOG.log(Level.WARNING, "Exception in handleFault on interceptor " + currentInterceptor, e);
+                throw e;
             } catch (Exception e) {
-                LOG.log(Level.WARNING, "Exception in handleFault on interceptor " + currentInterceptor, e); 
+                LOG.log(Level.WARNING, "Exception in handleFault on interceptor " + currentInterceptor, e);
+                throw new RuntimeException(e);
             }
         }
     }

Modified: cxf/trunk/rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/XMLFaultOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/XMLFaultOutInterceptor.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/XMLFaultOutInterceptor.java (original)
+++ cxf/trunk/rt/bindings/xml/src/main/java/org/apache/cxf/binding/xml/interceptor/XMLFaultOutInterceptor.java Tue Apr 14 14:09:59 2009
@@ -48,6 +48,11 @@
     }
 
     public void handleMessage(Message message) throws Fault {
+        
+        if (mustPropogateException(message)) {
+            throw (Fault) message.getContent(Exception.class);
+        }
+        
         message.put(org.apache.cxf.message.Message.RESPONSE_CODE, new Integer(500));
         NSStack nsStack = new NSStack();
         nsStack.push();
@@ -82,4 +87,15 @@
             throw new Fault(new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), xe);
         }
     }
+    
+    @Override
+    public void handleFault(Message message) throws Fault {
+        if (mustPropogateException(message)) {
+            throw (Fault) message.getContent(Exception.class);
+        }
+    }
+    
+    protected boolean mustPropogateException(Message m) {
+        return Boolean.TRUE.equals(m.getExchange().get(Message.PROPOGATE_EXCEPTION));
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java Tue Apr 14 14:09:59 2009
@@ -125,6 +125,7 @@
                 if (criRoot != null) {
                     criRoot.clearThreadLocalProxies();
                 }
+                exchange.put(Message.PROPOGATE_EXCEPTION, Boolean.TRUE);
                 throw ex;
             }
             return new MessageContentsList(excResponse);

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java?rev=764781&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java Tue Apr 14 14:09:59 2009
@@ -0,0 +1,42 @@
+/**
+ * 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.impl;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.apache.cxf.message.Message;
+
+public class HttpServletResponseFilter extends HttpServletResponseWrapper {
+
+    private Message m;
+    public HttpServletResponseFilter(HttpServletResponse response, Message message) {
+        super(response);
+        m = message;
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        return new ServletOutputStreamFilter(super.getOutputStream(), m);
+    }
+    
+}

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

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

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ServletOutputStreamFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ServletOutputStreamFilter.java?rev=764781&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ServletOutputStreamFilter.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ServletOutputStreamFilter.java Tue Apr 14 14:09:59 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.impl;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
+
+public class ServletOutputStreamFilter extends ServletOutputStream {
+
+    private Message m;
+    private ServletOutputStream os; 
+    
+    public ServletOutputStreamFilter(ServletOutputStream os, Message m) {
+        this.os = os;
+        this.m = m;
+    }
+    
+    @Override
+    public void write(int b) throws IOException {
+        m.getExchange().put(AbstractHTTPDestination.RESPONSE_COMMITED, Boolean.TRUE);
+        os.write(b);
+    }
+
+}

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

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

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=764781&r1=764780&r2=764781&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 Tue Apr 14 14:09:59 2009
@@ -67,6 +67,7 @@
             Response excResponse = JAXRSUtils.convertFaultToResponse(ex, message);
             if (excResponse == null) {
                 ProviderFactory.getInstance(message).clearThreadLocalProxies();
+                message.getExchange().put(Message.PROPOGATE_EXCEPTION, Boolean.TRUE);
                 throw ex;
             }
             message.getExchange().put(Response.class, excResponse);

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=764781&r1=764780&r2=764781&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 Tue Apr 14 14:09:59 2009
@@ -59,6 +59,7 @@
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.staxutils.CachingXmlEventWriter;
 import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
 
 public class JAXRSOutInterceptor extends AbstractOutDatabindingInterceptor {
     private static final Logger LOG = LogUtils.getL7dLogger(JAXRSOutInterceptor.class);
@@ -86,6 +87,10 @@
     
     private void processResponse(Message message) {
         
+        if (isResponseAlreadyCommited(message)) {
+            return;
+        }
+        
         MessageContentsList objs = MessageContentsList.getContentsList(message);
         if (objs == null || objs.size() == 0) {
             return;
@@ -365,4 +370,8 @@
         SimpleDateFormat format = HttpUtils.getHttpDateFormat();
         headers.putSingle(HttpHeaders.DATE, format.format(new Date()));
     }
+    
+    private boolean isResponseAlreadyCommited(Message m) {
+        return Boolean.TRUE.equals(m.getExchange().get(AbstractHTTPDestination.RESPONSE_COMMITED));
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Tue Apr 14 14:09:59 2009
@@ -77,6 +77,7 @@
 import org.apache.cxf.jaxrs.ext.MessageContextImpl;
 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
+import org.apache.cxf.jaxrs.impl.HttpServletResponseFilter;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
 import org.apache.cxf.jaxrs.impl.ProvidersImpl;
@@ -706,7 +707,8 @@
             value = m.get(AbstractHTTPDestination.HTTP_REQUEST);
         }
         if (HttpServletResponse.class.isAssignableFrom(clazz)) {
-            value = m.get(AbstractHTTPDestination.HTTP_RESPONSE);
+            value = new HttpServletResponseFilter(
+                            (HttpServletResponse)m.get(AbstractHTTPDestination.HTTP_RESPONSE), m);
         }
         if (ServletContext.class.isAssignableFrom(clazz)) {
             value = m.get(AbstractHTTPDestination.HTTP_CONTEXT);

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/MessageContextImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/MessageContextImplTest.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/MessageContextImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/MessageContextImplTest.java Tue Apr 14 14:09:59 2009
@@ -30,6 +30,7 @@
 import javax.ws.rs.ext.Providers;
 
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
+import org.apache.cxf.jaxrs.impl.HttpServletResponseFilter;
 import org.apache.cxf.jaxrs.impl.ProvidersImpl;
 import org.apache.cxf.jaxrs.impl.RequestImpl;
 import org.apache.cxf.jaxrs.impl.SecurityContextImpl;
@@ -38,6 +39,7 @@
 import org.apache.cxf.message.MessageImpl;
 import org.apache.cxf.transport.http.AbstractHTTPDestination;
 import org.easymock.classextension.EasyMock;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -103,8 +105,10 @@
         MessageContext mc = new MessageContextImpl(m);
         HttpServletResponse request = EasyMock.createMock(HttpServletResponse.class);
         m.put(AbstractHTTPDestination.HTTP_RESPONSE, request);
-        assertSame(request.getClass(), mc.getHttpServletResponse().getClass());
-        assertSame(request.getClass(), mc.getContext(HttpServletResponse.class).getClass());
+        HttpServletResponseFilter filter = (HttpServletResponseFilter)mc.getHttpServletResponse();
+        assertSame(request.getClass(), filter.getResponse().getClass());
+        filter = (HttpServletResponseFilter)mc.getContext(HttpServletResponse.class);
+        assertSame(request.getClass(), filter.getResponse().getClass());
     }
     
     @Test

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Tue Apr 14 14:09:59 2009
@@ -53,6 +53,7 @@
 import org.apache.cxf.jaxrs.JAXRSServiceImpl;
 import org.apache.cxf.jaxrs.SimpleFactory;
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
+import org.apache.cxf.jaxrs.impl.HttpServletResponseFilter;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
 import org.apache.cxf.jaxrs.impl.ProvidersImpl;
@@ -1033,12 +1034,12 @@
                 cri);
         ori.setHttpMethod("GET");
         HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
-        HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
+        HttpServletResponse response = new HttpServletResponseFilter(
+                                           EasyMock.createMock(HttpServletResponse.class), null);
         ServletContext context = EasyMock.createMock(ServletContext.class);
         ServletConfig config = EasyMock.createMock(ServletConfig.class);        
         
         EasyMock.replay(request);
-        EasyMock.replay(response);
         EasyMock.replay(context);
         EasyMock.replay(config);
         
@@ -1069,6 +1070,8 @@
         
         Message m = createMessage();
         m.put(Message.PROTOCOL_HEADERS, new HashMap<String, List<String>>());
+        HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
+        m.put(AbstractHTTPDestination.HTTP_RESPONSE, response);
         
         InjectionUtils.injectContextFields(c, ori.getClassResourceInfo(), m);
         assertSame(UriInfoImpl.class, c.getUriInfo2().getClass());
@@ -1092,7 +1095,7 @@
         m.put(AbstractHTTPDestination.HTTP_CONTEXT, servletContextMock);
         HttpServletRequest httpRequest = EasyMock.createNiceMock(HttpServletRequest.class);
         m.put(AbstractHTTPDestination.HTTP_REQUEST, httpRequest);
-        HttpServletResponse httpResponse = EasyMock.createNiceMock(HttpServletResponse.class);
+        HttpServletResponse httpResponse = EasyMock.createMock(HttpServletResponse.class);
         m.put(AbstractHTTPDestination.HTTP_RESPONSE, httpResponse);
         
         InjectionUtils.injectContextProxies(cri, cri.getResourceProvider().getInstance(null));
@@ -1119,8 +1122,9 @@
         
         assertSame(httpRequest, 
                    ((ThreadLocalProxy)c.getServletRequest()).get());
-        assertSame(httpResponse, 
-                   ((ThreadLocalProxy)c.getServletResponse()).get());
+        HttpServletResponseFilter filter = (
+            HttpServletResponseFilter)((ThreadLocalProxy)c.getServletResponse()).get();
+        assertSame(httpResponse, filter.getResponse());
     }
     
     @Test
@@ -1135,7 +1139,7 @@
         m.put(AbstractHTTPDestination.HTTP_CONTEXT, servletContextMock);
         HttpServletRequest httpRequest = EasyMock.createNiceMock(HttpServletRequest.class);
         m.put(AbstractHTTPDestination.HTTP_REQUEST, httpRequest);
-        HttpServletResponse httpResponse = EasyMock.createNiceMock(HttpServletResponse.class);
+        HttpServletResponse httpResponse = EasyMock.createMock(HttpServletResponse.class);
         m.put(AbstractHTTPDestination.HTTP_RESPONSE, httpResponse);
         InjectionUtils.injectContextProxies(cri, cri.getResourceProvider().getInstance(null));
         InjectionUtils.injectResourceFields(c, cri, m);
@@ -1143,8 +1147,9 @@
                    ((ThreadLocalProxy)c.getServletContextResource()).get());
         assertSame(httpRequest, 
                    ((ThreadLocalProxy)c.getServletRequestResource()).get());
-        assertSame(httpResponse, 
-                   ((ThreadLocalProxy)c.getServletResponseResource()).get());
+        HttpServletResponseFilter filter = (
+            HttpServletResponseFilter)((ThreadLocalProxy)c.getServletResponseResource()).get();
+        assertSame(httpResponse, filter.getResponse());
     }
     
     @Test
@@ -1224,6 +1229,8 @@
         OperationResourceInfo ori = new OperationResourceInfo(null, cri);
         
         Message m = createMessage();
+        HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
+        m.put(AbstractHTTPDestination.HTTP_RESPONSE, response);
         Customer c = new Customer();
         ContextResolver<JAXBContext> cr = new JAXBContextProvider();
         ProviderFactory.getInstance(m).registerUserProvider(cr);
@@ -1257,7 +1264,8 @@
         
         InjectionUtils.injectResourceFields(c, ori.getClassResourceInfo(), m);
         assertSame(request.getClass(), c.getServletRequestResource().getClass());
-        assertSame(response.getClass(), c.getServletResponseResource().getClass());
+        HttpServletResponseFilter filter = (HttpServletResponseFilter)c.getServletResponseResource();
+        assertSame(response.getClass(), filter.getResponse().getClass());
         assertSame(context.getClass(), c.getServletContextResource().getClass());
         assertNull(c.getServletRequest());
         assertNull(c.getServletResponse());
@@ -1269,7 +1277,8 @@
         assertNull(c.getServletResponseResource());
         assertNull(c.getServletContextResource());
         assertSame(request.getClass(), c.getServletRequest().getClass());
-        assertSame(response.getClass(), c.getServletResponse().getClass());
+        filter = (HttpServletResponseFilter)c.getServletResponse();
+        assertSame(response.getClass(), filter.getResponse().getClass());
         assertSame(context.getClass(), c.getServletContext().getClass());
     }
     

Modified: cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java (original)
+++ cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java Tue Apr 14 14:09:59 2009
@@ -304,6 +304,13 @@
             baseRequest.setHandled(true);
         } catch (SuspendedInvocationException ex) {
             throw ex.getRuntimeException();
+        } catch (Fault ex) {
+            Throwable cause = ex.getCause();
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException)cause;
+            } else {
+                throw ex;
+            }
         } catch (RuntimeException ex) {
             throw ex;
         } finally {

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java Tue Apr 14 14:09:59 2009
@@ -82,6 +82,8 @@
         
     public static final String PARTIAL_RESPONSE = AbstractMultiplexDestination.class.getName()
         + ".partial.response";
+    public static final String RESPONSE_COMMITED = "http.response.done";
+    
     private static final Logger LOG = LogUtils.getL7dLogger(AbstractHTTPDestination.class);
     
     private static final long serialVersionUID = 1L;

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java Tue Apr 14 14:09:59 2009
@@ -40,6 +40,7 @@
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.common.util.UrlUtils;
 import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.service.model.EndpointInfo;
 import org.apache.cxf.service.model.OperationInfo;
 import org.apache.cxf.transports.http.QueryHandler;
@@ -181,9 +182,15 @@
                 
                 invokeDestination(request, res, d);
             }
+        } catch (Fault ex) {
+            if (ex.getCause() instanceof RuntimeException) {
+                throw (RuntimeException)ex.getCause(); 
+            } else {
+                throw new ServletException(ex.getCause());
+            }
         } catch (IOException e) {
             throw new ServletException(e);
-        }
+        } 
     }
     
     private ServletDestination checkRestfulRequest(HttpServletRequest request) throws IOException {        

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Tue Apr 14 14:09:59 2009
@@ -90,6 +90,13 @@
     }
     
     @GET
+    @Path("propogateexception")
+    public Book propogateException() throws BookNotFoundFault {
+        throw new BookNotFoundFault("Book Exception");
+    }
+    
+    
+    @GET
     @Path("books/check/{id}")
     @Produces("text/plain")
     public boolean checkBook(@PathParam("id") Long id) {

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java Tue Apr 14 14:09:59 2009
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.systest.jaxrs;
 
+import java.io.OutputStream;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,6 +29,8 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
 import javax.xml.ws.WebServiceContext;
 
 import org.apache.cxf.jaxrs.client.WebClient;
@@ -59,7 +62,21 @@
     }
     
     public Book getBook(Long id) throws BookNotFoundFault {
+        
         if (books.get(id) == null) {
+            if (id == 0) {
+                try {
+                    OutputStream os = jaxrsContext.getHttpServletResponse().getOutputStream();
+                    JAXBContext c = JAXBContext.newInstance(new Class[]{Book.class});
+                    Marshaller m = c.createMarshaller();
+                    m.marshal(books.get(123L), os);
+                    os.flush();
+                    return null;
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                    throw new RuntimeException();
+                }
+            }
             Response r = Response.status(404).header("BOOK-HEADER", 
                 "No Book with id " + id + " is available").build();
             throw new WebApplicationException(r);

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Tue Apr 14 14:09:59 2009
@@ -53,6 +53,13 @@
                    launchServer(BookServer.class));
     }
     
+    
+    @Test
+    public void testPropogateException() throws Exception {
+        getAndCompare("http://localhost:9080/bookstore/propogateexception",
+                      "", "application/xml", 500);
+    }
+    
     @Test
     public void testWebApplicationException() throws Exception {
         getAndCompare("http://localhost:9080/bookstore/webappexception",

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java?rev=764781&r1=764780&r2=764781&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java Tue Apr 14 14:09:59 2009
@@ -70,6 +70,15 @@
     }
     
     @Test
+    public void testGetBook123ServletResponse() throws Exception {
+        
+        InputStream in = getHttpInputStream("http://localhost:9092/test/services/rest/bookstore/0");
+        InputStream expected = getClass().getResourceAsStream("resources/expected_get_book123.txt");
+        assertEquals(getStringFromInputStream(expected), getStringFromInputStream(in));
+                
+    }
+    
+    @Test
     public void testGetBook123() throws Exception {
         
         InputStream in = getHttpInputStream("http://localhost:9092/test/services/rest/bookstore/123");