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/23 11:39:44 UTC

svn commit: r1525544 - in /cxf/trunk/rt: frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ frontend/jaxrs/src/main/java/org...

Author: sergeyb
Date: Mon Sep 23 09:39:43 2013
New Revision: 1525544

URL: http://svn.apache.org/r1525544
Log:
[CXF-5135] Various fixes related to the use of filters in client api

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractRequestContextImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorContextImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.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/interceptor/Messages.properties
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/Messages.properties
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientRequestContextImpl.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientResponseContextImpl.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractRequestContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractRequestContextImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractRequestContextImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractRequestContextImpl.java Mon Sep 23 09:39:43 2013
@@ -29,6 +29,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 
 public abstract class AbstractRequestContextImpl extends AbstractPropertiesImpl {
@@ -43,7 +44,7 @@ public abstract class AbstractRequestCon
     
     public void abortWith(Response response) {
         checkContext();
-        m.getExchange().put(Response.class, response);
+        m.getExchange().put(Response.class, JAXRSUtils.copyResponseIfNeeded(response));
     }
 
     public List<Locale> getAcceptableLanguages() {

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java Mon Sep 23 09:39:43 2013
@@ -100,7 +100,6 @@ public abstract class AbstractResponseCo
     }
 
     public MediaType getMediaType() {
-        //return r.getEntity() != null ? r.getMediaType() : null;
         return r.getMediaType();
     }
 
@@ -133,7 +132,7 @@ public abstract class AbstractResponseCo
     }
     
     public void setEntity(Object entity) {
-        ((ResponseImpl)r).setEntity(entity, null);
+        ((ResponseImpl)r).setEntity(entity, getResponseEntityAnnotations());
     }
     
     protected Annotation[] getResponseEntityAnnotations() {

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorContextImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorContextImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorContextImpl.java Mon Sep 23 09:39:43 2013
@@ -23,7 +23,6 @@ import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.List;
-import java.util.Map;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
@@ -31,6 +30,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.ReaderInterceptor;
 import javax.ws.rs.ext.ReaderInterceptorContext;
 
+import org.apache.cxf.jaxrs.utils.HttpUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 
@@ -50,11 +50,9 @@ public class ReaderInterceptorContextImp
         this.readers = readers;
     }
     
-    @SuppressWarnings("unchecked")
     @Override
     public MultivaluedMap<String, String> getHeaders() {
-        return new MetadataMap<String, String>(
-            (Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS), false, false, true);
+        return HttpUtils.getModifiableStringHeaders(m);
     }
 
     @Override

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java Mon Sep 23 09:39:43 2013
@@ -19,16 +19,21 @@
 package org.apache.cxf.jaxrs.impl;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 
+import javax.ws.rs.ProcessingException;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.ReaderInterceptor;
 import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.xml.stream.XMLStreamReader;
 
 import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 
 public class ReaderInterceptorMBR implements ReaderInterceptor {
@@ -56,13 +61,15 @@ public class ReaderInterceptorMBR implem
         MediaType entityMt = c.getMediaType();
         Annotation[] entityAnns = c.getAnnotations();
         
-        if (m.get(ProviderFactory.PROVIDER_SELECTION_PROPERTY_CHANGED) == Boolean.TRUE
-            && !reader.isReadable(entityCls, entityType, entityAnns, entityMt)) {
+        if ((reader == null || m.get(ProviderFactory.PROVIDER_SELECTION_PROPERTY_CHANGED) == Boolean.TRUE
+            && !reader.isReadable(entityCls, entityType, entityAnns, entityMt)) 
+            && entityStreamAvailable(c.getInputStream())) {
             reader = ProviderFactory.getInstance(m)
                 .createMessageBodyReader(entityCls, entityType, entityAnns, entityMt, m);
-            if (reader == null) {
-                throw new RuntimeException("No reader available");
-            }
+        }
+        if (reader == null) {
+            String errorMessage = JAXRSUtils.logMessageHandlerProblem("NO_MSG_READER", entityCls, entityMt);
+            throw new ProcessingException(errorMessage);
         }
         
         
@@ -71,4 +78,8 @@ public class ReaderInterceptorMBR implem
                                c.getInputStream());
     }
 
+    private boolean entityStreamAvailable(InputStream entity) {
+        return entity != null || m.getContent(XMLStreamReader.class) != null
+            || m.getContent(Reader.class) != null;
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java Mon Sep 23 09:39:43 2013
@@ -237,9 +237,11 @@ public final class ResponseBuilderImpl e
     
     private ResponseBuilder addHeader(String name, Object... values) {
         if (values != null && values.length >= 1 && values[0] != null) {
+            boolean isAllowHeader = HttpHeaders.ALLOW.equals(name);
             for (Object value : values) {
-                if (!valueExists(name, value)) {
-                    metadata.add(name, value);
+                Object thevalue = isAllowHeader ? value.toString().toUpperCase() : value; 
+                if (!valueExists(name, thevalue)) {
+                    metadata.add(name, thevalue);
                 }
             }
         } else {

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java Mon Sep 23 09:39:43 2013
@@ -19,8 +19,10 @@
 
 package org.apache.cxf.jaxrs.impl;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.net.URI;
@@ -47,8 +49,8 @@ import javax.ws.rs.core.NewCookie;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status.Family;
 import javax.ws.rs.ext.ReaderInterceptor;
-import javax.ws.rs.ext.RuntimeDelegate;
 import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+import javax.xml.stream.XMLStreamReader;
 
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.provider.ProviderFactory;
@@ -59,12 +61,13 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 
 public final class ResponseImpl extends Response {
+    
     private int status;
     private Object entity;
     private Annotation[] entityAnnotations; 
     private MultivaluedMap<String, Object> metadata;
     
-    private Message responseMessage;
+    private Message outMessage;
     private boolean entityClosed;    
     private boolean entityBufferred;
     private Object lastEntity;
@@ -78,7 +81,7 @@ public final class ResponseImpl extends 
         this.entity = e;
     }
     
-    void addMetadata(MultivaluedMap<String, Object> meta) { 
+    public void addMetadata(MultivaluedMap<String, Object> meta) { 
         this.metadata = meta;
     }
     
@@ -99,12 +102,12 @@ public final class ResponseImpl extends 
         return entityAnnotations;
     }
 
-    //TODO: This method is needed because on the client side the
-    // Response processing is done after the chain completes, thus
-    // PhaseInterceptorChain.getCurrentMessage() returns null.
-    // The refactoring will be required
-    public void setMessage(Message message) {
-        this.responseMessage = message;
+    public void setOutMessage(Message message) {
+        this.outMessage = message;
+    }
+    
+    public Message getOutMessage() {
+        return this.outMessage;
     }
     
     public int getStatus() {
@@ -171,10 +174,7 @@ public final class ResponseImpl extends 
             return null; 
         } else {
             List<String> stringValues = new ArrayList<String>(values.size());
-            RuntimeDelegate rd = RuntimeDelegate.getInstance();
-            @SuppressWarnings("unchecked")
-            HeaderDelegate<Object> hd = rd == null || values.isEmpty() 
-                ? null : (HeaderDelegate<Object>)rd.createHeaderDelegate(values.get(0).getClass());
+            HeaderDelegate<Object> hd = HttpUtils.getHeaderDelegate(values.get(0));
             for (Object value : values) {
                 String actualValue = hd == null ? value.toString() : hd.toString(value); 
                 stringValues.add(actualValue);
@@ -296,8 +296,7 @@ public final class ResponseImpl extends 
             for (Object o : linkValues) {
                 Link link = o instanceof Link ? (Link)o : Link.valueOf(o.toString());
                 if (!link.getUri().isAbsolute()) {
-                    URI requestURI = URI.create((String)responseMessage.getExchange().getOutMessage()
-                        .get(Message.REQUEST_URI));
+                    URI requestURI = URI.create((String)outMessage.get(Message.REQUEST_URI));
                     link = Link.fromLink(link).baseUri(requestURI).build();
                 }
                 links.put(link.getRel(), link);
@@ -337,54 +336,105 @@ public final class ResponseImpl extends 
             return cls.cast(lastEntity);
         } 
         
-        if (entity instanceof InputStream) {
-            
-            MediaType mediaType = getMediaType();
-            if (mediaType == null) {
-                mediaType = MediaType.WILDCARD_TYPE;
-            }
-            
-            List<ReaderInterceptor> readers = ProviderFactory.getInstance(responseMessage)
-                .createMessageBodyReaderInterceptor(cls, t, anns, mediaType, 
-                                                    responseMessage.getExchange().getOutMessage(), 
-                                                    null);
-            if (readers != null) {
-                try {
-                    if (entityBufferred) {
-                        InputStream.class.cast(entity).reset();
-                    }
-                    
-                    responseMessage.put(Message.PROTOCOL_HEADERS, this.getMetadata());
-                    lastEntity = JAXRSUtils.readFromMessageBodyReader(readers, cls, t, 
-                                                                           anns, 
-                                                                           InputStream.class.cast(entity), 
-                                                                           mediaType, 
-                                                                           responseMessage);
-                    if (!entityBufferred && responseStreamCanBeClosed(cls)) {
-                        InputStream.class.cast(entity).close();
-                        entity = null;
-                    } 
-                    
-                    return cls.cast(lastEntity);
-                } catch (Exception ex) {
-                    throw new ResponseProcessingException(this, ex.getMessage(), ex);    
+        MediaType mediaType = getMediaType();
+        if (mediaType == null) {
+            mediaType = MediaType.WILDCARD_TYPE;
+        }
+        
+        // the stream is available if entity is IS or 
+        // message contains XMLStreamReader or Reader
+        boolean entityStreamAvailable = entityStreamAvailable();
+        InputStream entityStream = null;
+        if (!entityStreamAvailable) {
+            // try create a stream if the entity is String or Number
+            entityStream = convertEntityToStreamIfPossible();
+            entityStreamAvailable = entityStream != null;
+        } else if (entity instanceof InputStream) {
+            entityStream = InputStream.class.cast(entity);
+        }
+        
+        // we need to check for readers even if no IS is set - the readers may still do it
+        List<ReaderInterceptor> readers = ProviderFactory.getInstance(outMessage)
+            .createMessageBodyReaderInterceptor(cls, t, anns, mediaType, outMessage, entityStreamAvailable, null);
+        
+        if (readers != null) {
+            try {
+                if (entityBufferred) {
+                    InputStream.class.cast(entity).reset();
                 }
-            } else {
-                throw new ResponseProcessingException(this, "No message body reader for class: " + cls, null);
+                
+                Message responseMessage = getResponseMessage();
+                responseMessage.put(Message.PROTOCOL_HEADERS, getHeaders());
+                
+                lastEntity = JAXRSUtils.readFromMessageBodyReader(readers, cls, t, 
+                                                                       anns, 
+                                                                       entityStream, 
+                                                                       mediaType, 
+                                                                       responseMessage);
+                if (!entityBufferred && responseStreamCanBeClosed(cls)) {
+                    InputStream.class.cast(entity).close();
+                    entity = null;
+                } 
+                
+                return cls.cast(lastEntity);
+            } catch (Exception ex) {
+                reportMessageHandlerProblem("MSG_READER_PROBLEM", cls, mediaType, ex);
             }
         } else if (entity != null && cls.isAssignableFrom(entity.getClass())) {
             lastEntity = entity;
             return cls.cast(lastEntity);
-        }
+        } else if (entityStreamAvailable) {
+            reportMessageHandlerProblem("NO_MSG_READER", cls, mediaType, null);
+        } 
         
         throw new IllegalStateException("The entity is not backed by an input stream, entity class is : "
             + entity != null ? entity.getClass().getName() : null);
         
     }
     
+    public InputStream convertEntityToStreamIfPossible() {
+        String stringEntity = null;
+        if (entity instanceof String || entity instanceof Number) {
+            stringEntity = entity.toString();
+        }
+        if (stringEntity != null) {
+            try {
+                return new ByteArrayInputStream(stringEntity.getBytes("UTF-8"));
+            } catch (Exception ex) {
+                throw new ProcessingException(ex);
+            }
+        } else {
+            return null;
+        }
+    }
+    
+    private boolean entityStreamAvailable() {
+        if (entity == null) {
+            Message inMessage = getResponseMessage();    
+            return inMessage != null && (inMessage.getContent(XMLStreamReader.class) != null
+                || inMessage.getContent(Reader.class) != null);
+        } else {
+            return entity instanceof InputStream;
+        }
+    }
+    
+    private Message getResponseMessage() {
+        Message responseMessage = outMessage.getExchange().getInMessage();
+        if (responseMessage == null) {
+            responseMessage = outMessage.getExchange().getInFaultMessage();    
+        }
+        return responseMessage;
+    }
+    
+    private void reportMessageHandlerProblem(String name, Class<?> cls, MediaType ct, Throwable cause) {
+        String errorMessage = JAXRSUtils.logMessageHandlerProblem(name, cls, ct);
+        throw new ResponseProcessingException(this, errorMessage, cause);
+    }
+    
     protected boolean responseStreamCanBeClosed(Class<?> cls) {
         return cls != InputStream.class
-            && MessageUtils.isTrue(responseMessage.getContextualProperty("response.stream.auto.close"));
+            && entity instanceof InputStream
+            && MessageUtils.isTrue(outMessage.getContextualProperty("response.stream.auto.close"));
     }
     
     public boolean bufferEntity() throws ProcessingException {

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=1525544&r1=1525543&r2=1525544&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 Mon Sep 23 09:39:43 2013
@@ -224,7 +224,7 @@ public class JAXRSOutInterceptor extends
                 responseHeaders.remove(HttpHeaders.CONTENT_TYPE);
                 message.remove(Message.CONTENT_TYPE);
             }
-            HttpUtils.convertHeaderValuesToStringIfNeeded(responseHeaders);
+            HttpUtils.convertHeaderValuesToString(responseHeaders, true);
             return;
         }
         
@@ -253,7 +253,7 @@ public class JAXRSOutInterceptor extends
         if (writers == null || writers.isEmpty()) {
             message.put(Message.CONTENT_TYPE, "text/plain");
             message.put(Message.RESPONSE_CODE, 500);
-            writeResponseErrorMessage(outOriginal, "NO_MSG_WRITER", targetType.getSimpleName());
+            writeResponseErrorMessage(outOriginal, "NO_MSG_WRITER", targetType, responseMediaType);
             return;
         }
         responseMediaType = checkFinalContentType(responseMediaType, writers);
@@ -289,8 +289,10 @@ public class JAXRSOutInterceptor extends
             }
             
         } catch (IOException ex) {
+            logWriteError(firstTry, targetType, responseMediaType);
             handleWriteException(providerFactory, message, ex, firstTry);
         } catch (Throwable ex) {
+            logWriteError(firstTry, targetType, responseMediaType);
             handleWriteException(providerFactory, message, ex, firstTry);
         }
     }
@@ -372,6 +374,11 @@ public class JAXRSOutInterceptor extends
         }
     }
     
+    private void logWriteError(boolean firstTry, Class<?> cls, MediaType ct) {
+        if (firstTry) {
+            JAXRSUtils.logMessageHandlerProblem("MSG_WRITER_PROBLEM", cls, ct);    
+        }
+    }
     
     private void handleWriteException(ServerProviderFactory pf,
                                       Message message, 
@@ -391,16 +398,11 @@ public class JAXRSOutInterceptor extends
     }
     
     
-    private void writeResponseErrorMessage(OutputStream out, String errorString, 
-                                           String parameter) {
+    private void writeResponseErrorMessage(OutputStream out, String name, Class<?> cls, MediaType ct) {
         try {
-            org.apache.cxf.common.i18n.Message message = 
-                new org.apache.cxf.common.i18n.Message(errorString,
-                                                   BUNDLE,
-                                                   parameter);
-            LOG.warning(message.toString());
+            String errorMessage = JAXRSUtils.logMessageHandlerProblem(name, cls, ct);
             if (out != null) {
-                out.write(message.toString().getBytes("UTF-8"));
+                out.write(errorMessage.getBytes("UTF-8"));
             }
         } catch (IOException another) {
             // ignore

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/Messages.properties
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/Messages.properties?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/Messages.properties (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/Messages.properties Mon Sep 23 09:39:43 2013
@@ -18,7 +18,5 @@
 #    under the License.
 #
 #
-SERIALIZE_ERROR = Error serializing the response, please check the server logs, response class : {0}.
-NO_MSG_WRITER = No message body writer has been found for response class {0}.
 NO_ROOT_EXC = No root resource matching request path {0} has been found, Relative Path: {1}. Please enable FINE/TRACE log level for more details.
 HEAD_WITHOUT_ENTITY = Entity body returned by GET-supporting resource method will be dropped as HEAD was the actual http request method 
\ No newline at end of file

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java Mon Sep 23 09:39:43 2013
@@ -350,16 +350,17 @@ public abstract class ProviderFactory {
                                                             Annotation[] parameterAnnotations,
                                                             MediaType mediaType,
                                                             Message m,
+                                                            boolean checkMbrNow,
                                                             Set<String> names) {
-        MessageBodyReader<T> mr = createMessageBodyReader(bodyType,
+        MessageBodyReader<T> mr = !checkMbrNow ? null : createMessageBodyReader(bodyType,
                                                       parameterType,
                                                       parameterAnnotations,
                                                       mediaType,
                                                       m);
-        if (mr != null) {
+        int size = readerInterceptors.size();
+        if (mr != null || size > 0) {
             ReaderInterceptor mbrReader = new ReaderInterceptorMBR(mr, m.getExchange().getInMessage());
             
-            int size = readerInterceptors.size();
             List<ReaderInterceptor> interceptors = null;
             if (size > 0) {
                 interceptors = new ArrayList<ReaderInterceptor>(size + 1);
@@ -391,14 +392,14 @@ public abstract class ProviderFactory {
                                                       parameterAnnotations,
                                                       mediaType,
                                                       m);
-        if (mw != null) {
+        int size = writerInterceptors.size();
+        if (mw != null || size > 0) {
             
             @SuppressWarnings({
                 "unchecked", "rawtypes"
             })
             WriterInterceptor mbwWriter = new WriterInterceptorMBW((MessageBodyWriter)mw, m);
               
-            int size = writerInterceptors.size();
             List<WriterInterceptor> interceptors = null;
             if (size > 0) {
                 interceptors = new ArrayList<WriterInterceptor>(size + 1);

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java Mon Sep 23 09:39:43 2013
@@ -25,6 +25,7 @@ import java.net.URISyntaxException;
 import java.net.URLEncoder;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
@@ -48,7 +49,9 @@ import org.apache.cxf.common.i18n.Bundle
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.common.util.UrlUtils;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
 import org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl;
 import org.apache.cxf.jaxrs.model.ParameterType;
@@ -192,23 +195,68 @@ public final class HttpUtils {
         return Headers.toHttpDate(date);
     }
     
-    public static void convertHeaderValuesToStringIfNeeded(Map<String, List<Object>> headers) {
-        // In theory there could be custom RuntimeDelegates with custom header handlers
-        RuntimeDelegate rd = RuntimeDelegate.getInstance();
-        if (rd instanceof RuntimeDelegateImpl || rd == null) {
+    public static RuntimeDelegate getOtherRuntimeDelegate() {
+        try {
+            RuntimeDelegate rd = RuntimeDelegate.getInstance();
+            return rd instanceof RuntimeDelegateImpl ? null : rd;
+        } catch (Throwable t) {
+            return null;
+        }
+    }
+    
+    public static HeaderDelegate<Object> getHeaderDelegate(Object o) {
+        return getHeaderDelegate(getOtherRuntimeDelegate(), o);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static HeaderDelegate<Object> getHeaderDelegate(RuntimeDelegate rd, Object o) {
+        return rd == null ? null : (HeaderDelegate<Object>)rd.createHeaderDelegate(o.getClass());
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static <T> MultivaluedMap<String, T> getModifiableStringHeaders(Message m) {
+        MultivaluedMap<String, Object> headers = getModifiableHeaders(m);
+        convertHeaderValuesToString(headers, false);
+        return (MultivaluedMap<String, T>)headers;
+    }
+    
+    public static MultivaluedMap<String, Object> getModifiableHeaders(Message m) {
+        Map<String, List<Object>> headers = CastUtils.cast((Map<?, ?>)m.get(Message.PROTOCOL_HEADERS));
+        return new MetadataMap<String, Object>(headers, false, false, true);
+    }
+    
+    public static void convertHeaderValuesToString(Map<String, List<Object>> headers, boolean delegateOnly) {
+        RuntimeDelegate rd = getOtherRuntimeDelegate();
+        if (rd == null && delegateOnly) {
             return;
         }
         for (Map.Entry<String, List<Object>> entry : headers.entrySet()) {
             List<Object> values = entry.getValue();
-            if (!values.isEmpty()) {
-                @SuppressWarnings("unchecked")
-                HeaderDelegate<Object> hd = 
-                    (HeaderDelegate<Object>)rd.createHeaderDelegate(values.get(0).getClass());
-                if (hd != null) {
-                    for (int i = 0; i < values.size(); i++) {
-                        values.set(i, hd.toString(values.get(i)));
+            for (int i = 0; i < values.size(); i++) {
+                Object value = values.get(i);
+                
+                if (value != null && !(value instanceof String)) {
+                
+                    HeaderDelegate<Object> hd = getHeaderDelegate(rd, value);
+                    
+                    if (hd != null) {
+                        value = hd.toString(value); 
+                    } else if (!delegateOnly) {
+                        value = value.toString();
+                    }
+                    
+                    try {
+                        values.set(i, value);
+                    } catch (UnsupportedOperationException ex) {
+                        // this may happen if an unmodifiable List was set via Map put
+                        List<Object> newList = new ArrayList<Object>(values);
+                        newList.set(i, value);
+                        // Won't help if the map is unmodifiable in which case it is a bug anyway 
+                        headers.put(entry.getKey(), newList);
                     }
+                
                 }
+                
             }
         }
         

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=1525544&r1=1525543&r2=1525544&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 Mon Sep 23 09:39:43 2013
@@ -1282,6 +1282,7 @@ public final class JAXRSUtils {
                                          parameterAnnotations,
                                          type,
                                          m,
+                                         true,
                                          ori.getNameBindings());
             if (readers != null) {
                 try {
@@ -1304,11 +1305,7 @@ public final class JAXRSUtils {
             }
         }
 
-        String errorMessage = new org.apache.cxf.common.i18n.Message("NO_MSG_READER",
-                                                                     BUNDLE,
-                                                                     targetTypeClass.getSimpleName(),
-                                                                     mediaTypeToString(contentType)).toString();
-        LOG.warning(errorMessage);
+        logMessageHandlerProblem("NO_MSG_READER", targetTypeClass, contentType);
         throw new WebApplicationException(Response.Status.UNSUPPORTED_MEDIA_TYPE);
     }
     
@@ -1373,7 +1370,7 @@ public final class JAXRSUtils {
                     httpHeaders.putSingle(HttpHeaders.CONTENT_LENGTH, Long.toString(size));
                 }
             }
-            HttpUtils.convertHeaderValuesToStringIfNeeded(httpHeaders);
+            HttpUtils.convertHeaderValuesToString(httpHeaders, true);
             writer.writeTo(entity, type, genericType, annotations, mediaType,
                            httpHeaders, 
                            entityStream);
@@ -1837,4 +1834,13 @@ public final class JAXRSUtils {
         Class<?> realClass = ori.getClassResourceInfo().getServiceClass();
         stack.push(new MethodInvocationInfo(ori, realClass, values));
     }
+    
+    public static String logMessageHandlerProblem(String name, Class<?> cls, MediaType ct) {
+        org.apache.cxf.common.i18n.Message errorMsg = 
+            new org.apache.cxf.common.i18n.Message(name, BUNDLE, cls.getName(), mediaTypeToString(ct));
+        String errorMessage = errorMsg.toString();
+        LOG.severe(errorMessage);
+        return errorMessage;
+    }
+    
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/Messages.properties
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/Messages.properties?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/Messages.properties (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/Messages.properties Mon Sep 23 09:39:43 2013
@@ -30,7 +30,10 @@ CLASS_ACCESS_FAILURE=Class {0} can not b
 CLASS_CONSTRUCTOR_FAILURE=Class {0} can not be instantiated using a constructor with a single String argument
 CLASS_VALUE_OF_FAILURE=Instance of class {0} can not be created using static valueOf(String) or fromString(String) methods
 WRONG_PARAMETER_TYPE=Parameter Class {0} has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
-NO_MSG_READER=No message body reader has been found for request class {0}, ContentType : {1}.
+NO_MSG_READER=No message body reader has been found for class {0}, ContentType: {1}
+MSG_READER_PROBLEM=Problem with reading the data, class {0}, ContentType: {1}.
+NO_MSG_WRITER =No message body writer has been found for class {0}, ContentType: {1}
+MSG_WRITER_PROBLEM =Problem with writing the data, class {0}, ContentType: {1}
 NO_SUBRESOURCE_METHOD_FOUND=No operation matching request path "{0}" is found on subresource, Relative Path: {1}, HTTP Method: {2}, ContentType: {3}, Accept: {4}. Please enable FINE/TRACE log level for more details.
 NO_OP_EXC=No operation matching request path "{0}" is found, Relative Path: {1}, HTTP Method: {2}, ContentType: {3}, Accept: {4}. Please enable FINE/TRACE log level for more details.
 START_OPER_MATCH=Trying to select a resource operation on the resource class {0}

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java Mon Sep 23 09:39:43 2013
@@ -98,7 +98,7 @@ public class ResponseImplTest extends As
         headers.putSingle("Content-Type", "text/xml");
         r.addMetadata(headers);
         r.setEntity(new ByteArrayInputStream(content.getBytes()), null);
-        r.setMessage(createMessage());
+        r.setOutMessage(createMessage());
         r.bufferEntity();
         return r.readEntity(Source.class);
     }

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java Mon Sep 23 09:39:43 2013
@@ -606,7 +606,9 @@ public class ClientProxyImpl extends Abs
         
         Message outMessage = createMessage(body, ori.getHttpMethod(), headers, uri, 
                                            exchange, invocationContext, true);
-        
+        if (bodyIndex != -1) {
+            outMessage.put(Type.class, ori.getMethodToInvoke().getGenericParameterTypes()[bodyIndex]);
+        }
         outMessage.getExchange().setOneWay(ori.isOneway());
         outMessage.setContent(OperationResourceInfo.class, ori);
         setPlainOperationNameProperty(outMessage, ori.getMethodToInvoke().getName());
@@ -664,12 +666,12 @@ public class ClientProxyImpl extends Abs
         throws Throwable {
         try {
             Response r = setResponseBuilder(outMessage, outMessage.getExchange()).build();
-            ((ResponseImpl)r).setMessage(outMessage);
+            ((ResponseImpl)r).setOutMessage(outMessage);
             getState().setResponse(r);
             
             Method method = outMessage.getExchange().get(Method.class);
             checkResponse(method, r, outMessage);
-            if (method.getReturnType() == Void.class) { 
+            if (method.getReturnType() == Void.class || method.getReturnType() == void.class) { 
                 return null;
             }
             if (method.getReturnType() == Response.class

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java Mon Sep 23 09:39:43 2013
@@ -76,6 +76,7 @@ import org.apache.cxf.phase.Phase;
 public class WebClient extends AbstractClient {
     private static final String REQUEST_CLASS = "request.class";
     private static final String REQUEST_TYPE = "request.type";
+    private static final String REQUEST_ANNS = "request.annotations";
     private static final String RESPONSE_CLASS = "response.class";
     private static final String RESPONSE_TYPE = "response.type";
     
@@ -831,12 +832,7 @@ public class WebClient extends AbstractC
             responseClass, outGenericType);
     }
     
-    private static Type getGenericEntityType(GenericEntity<?> genericEntity, Type inGenericType) {
-        if (inGenericType != null && genericEntity.getType() != inGenericType) {
-            throw new IllegalArgumentException("Illegal type");    
-        }
-        return genericEntity.getType();
-    }
+    
     
     protected Response doInvoke(String httpMethod, 
                                 Object body, 
@@ -844,16 +840,25 @@ public class WebClient extends AbstractC
                                 Type inGenericType,
                                 Class<?> responseClass, 
                                 Type outGenericType) {
+        Annotation[] inAnns = null;
+        if (body instanceof Entity) {
+            Entity<?> entity = (Entity<?>)body;
+            setEntityHeaders(entity);
+            body = entity.getEntity();
+            requestClass = body.getClass();
+            inGenericType = body.getClass();
+            inAnns = entity.getAnnotations();
+        }
         if (body instanceof GenericEntity) {
             GenericEntity<?> genericEntity = (GenericEntity<?>)body;
             body = genericEntity.getEntity();
             requestClass = genericEntity.getRawType();
-            inGenericType = getGenericEntityType(genericEntity, inGenericType);
+            inGenericType = genericEntity.getType();
         }
         MultivaluedMap<String, String> headers = prepareHeaders(responseClass, body);
         resetResponse();
         Response r = doChainedInvocation(httpMethod, headers, body, requestClass, inGenericType, 
-                                         responseClass, outGenericType, null, null);
+                                         inAnns, responseClass, outGenericType, null, null);
         if (r.getStatus() >= 300 && responseClass != Response.class) {
             throw convertToWebApplicationException(r);
         }
@@ -911,19 +916,28 @@ public class WebClient extends AbstractC
                                           Class<?> respClass,
                                           Type outType,
                                           InvocationCallback<T> callback) {
+        Annotation[] inAnns = null;
+        if (body instanceof Entity) {
+            Entity<?> entity = (Entity<?>)body;
+            setEntityHeaders(entity);
+            body = entity.getEntity();
+            requestClass = body.getClass();
+            inType = body.getClass();
+            inAnns = entity.getAnnotations();
+        }
         
         if (body instanceof GenericEntity) {
             GenericEntity<?> genericEntity = (GenericEntity<?>)body;
             body = genericEntity.getEntity();
             requestClass = genericEntity.getRawType();
-            inType = getGenericEntityType(genericEntity, inType);
+            inType = genericEntity.getType();
         }
         
         MultivaluedMap<String, String> headers = prepareHeaders(respClass, body);
         resetResponse();
 
         Message m = finalizeMessage(httpMethod, headers, body, requestClass, inType, 
-                                    respClass, outType, null, null);
+                                    inAnns, respClass, outType, null, null);
         
         m.getExchange().setSynchronous(false);
         JaxrsClientCallback<T> cb = new JaxrsClientCallback<T>(callback, respClass, outType);
@@ -1020,10 +1034,11 @@ public class WebClient extends AbstractC
         String httpMethod = (String)reqContext.get(Message.HTTP_REQUEST_METHOD);
         Class<?> requestClass = (Class<?>)reqContext.get(REQUEST_CLASS);
         Type inType = (Type)reqContext.get(REQUEST_TYPE);
+        Annotation[] inAnns = (Annotation[])reqContext.get(REQUEST_ANNS);
         Class<?> respClass = (Class<?>)reqContext.get(RESPONSE_CLASS);
         Type outType = (Type)reqContext.get(RESPONSE_TYPE);
         return doChainedInvocation(httpMethod, headers, body, requestClass, inType, 
-                                   respClass, outType, exchange, invContext);
+                                   inAnns, respClass, outType, exchange, invContext);
     }
     //CHECKSTYLE:OFF
     protected Response doChainedInvocation(String httpMethod, 
@@ -1031,13 +1046,14 @@ public class WebClient extends AbstractC
                                            Object body, 
                                            Class<?> requestClass,
                                            Type inType,
+                                           Annotation[] inAnns,
                                            Class<?> respClass, 
                                            Type outType,
                                            Exchange exchange,
                                            Map<String, Object> invContext) {
     //CHECKSTYLE:ON    
         Message m = finalizeMessage(httpMethod, headers, body, requestClass, inType, 
-                                    respClass, outType, exchange, invContext);
+                                    inAnns, respClass, outType, exchange, invContext);
         doRunInterceptorChain(m);
         return doResponse(m, respClass, outType);
     }
@@ -1048,6 +1064,7 @@ public class WebClient extends AbstractC
                                    Object body, 
                                    Class<?> requestClass,
                                    Type inGenericType,
+                                   Annotation[] inAnns,
                                    Class<?> responseClass, 
                                    Type outGenericType,
                                    Exchange exchange,
@@ -1056,15 +1073,19 @@ public class WebClient extends AbstractC
         URI uri = getCurrentURI();
         Message m = createMessage(body, httpMethod, headers, uri, exchange, 
                 invContext, false);
-        
+        if (inAnns != null) {
+            m.put(Annotation.class.getName(), inAnns);
+        }
         Map<String, Object> reqContext = getRequestContext(m);
         reqContext.put(Message.HTTP_REQUEST_METHOD, httpMethod);
         reqContext.put(REQUEST_CLASS, requestClass);
         reqContext.put(REQUEST_TYPE, inGenericType);
+        reqContext.put(REQUEST_ANNS, inAnns);
         reqContext.put(RESPONSE_CLASS, responseClass);
         reqContext.put(RESPONSE_TYPE, outGenericType);
         
         if (body != null) {
+            m.put(Type.class, inGenericType);
             m.getInterceptorChain().add(new BodyWriter());
         }
         setPlainOperationNameProperty(m, httpMethod + ":" + uri.toString());
@@ -1104,6 +1125,7 @@ public class WebClient extends AbstractC
         try {
             ResponseBuilder rb = setResponseBuilder(outMessage, outMessage.getExchange());
             Response currentResponse = rb.clone().build();
+            ((ResponseImpl)currentResponse).setOutMessage(outMessage);
             
             Object entity = readBody(currentResponse, outMessage, responseClass, genericType,
                                      new Annotation[]{});
@@ -1120,10 +1142,8 @@ public class WebClient extends AbstractC
                       ? ((Response)entity).getEntity() : entity);
             
             Response r = rb.build();
-            ((ResponseImpl)r).setMessage(outMessage);
-            
             getState().setResponse(r);
-            
+            ((ResponseImpl)r).setOutMessage(outMessage);
             return r;
         } catch (Throwable ex) {
             throw (ex instanceof ProcessingException) ? (ProcessingException)ex
@@ -1251,14 +1271,12 @@ public class WebClient extends AbstractC
     }
     
     private void setEntityHeaders(Entity<?> entity) {
-        if (entity != null) {
-            type(entity.getMediaType());
-            if (entity.getLanguage() != null) {
-                language(entity.getLanguage().toString());
-            }
-            if (entity.getEncoding() != null) {
-                encoding(entity.getEncoding());
-            }
+        type(entity.getMediaType());
+        if (entity.getLanguage() != null) {
+            language(entity.getLanguage().toString());
+        }
+        if (entity.getEncoding() != null) {
+            encoding(entity.getEncoding());
         }
     }
     
@@ -1422,28 +1440,25 @@ public class WebClient extends AbstractC
 
         @Override
         public <T> Future<T> method(String name, Entity<?> entity, Class<T> responseType) {
-            WebClient.this.setEntityHeaders(entity);
             return doInvokeAsync(name, 
-                                 entity == null ? null : entity.getEntity(), 
-                                 entity == null ? null : entity.getEntity().getClass(), 
+                                 entity, 
+                                 null, 
                                  null, responseType, responseType, null);
         }
 
         @Override
         public <T> Future<T> method(String name, Entity<?> entity, GenericType<T> responseType) {
-            WebClient.this.setEntityHeaders(entity);
             return doInvokeAsync(name, 
-                                 entity == null ? null : entity.getEntity(), 
-                                 entity == null ? null : entity.getEntity().getClass(), 
+                                 entity, 
+                                 null, 
                                  null, responseType.getRawType(), responseType.getType(), null);
         }
 
         @Override
         public <T> Future<T> method(String name, Entity<?> entity, InvocationCallback<T> callback) {
-            WebClient.this.setEntityHeaders(entity);
             return doInvokeAsyncCallback(name, 
-                                         entity == null ? null : entity.getEntity(), 
-                                         entity == null ? null : entity.getEntity().getClass(),
+                                         entity, 
+                                         null,
                                          null, 
                                          callback);
         }
@@ -1570,18 +1585,12 @@ public class WebClient extends AbstractC
 
         @Override
         public <T> T method(String method, Entity<?> entity, Class<T> cls) {
-            WebClient.this.setEntityHeaders(entity);
-            return invoke(method, 
-                          entity == null ? null : entity.getEntity(), 
-                          cls);
+            return invoke(method, entity, cls);
         }
 
         @Override
         public <T> T method(String method, Entity<?> entity, GenericType<T> genericType) {
-            WebClient.this.setEntityHeaders(entity);
-            return invoke(method, 
-                          entity == null ? null : entity.getEntity(), 
-                          genericType);
+            return invoke(method, entity, genericType);
         }
     }
 }

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientRequestContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientRequestContextImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientRequestContextImpl.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientRequestContextImpl.java Mon Sep 23 09:39:43 2013
@@ -23,7 +23,6 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.net.URI;
 import java.util.List;
-import java.util.Map;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientRequestContext;
@@ -35,8 +34,9 @@ import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.jaxrs.client.ClientProviderFactory;
 import org.apache.cxf.jaxrs.impl.AbstractRequestContextImpl;
-import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.utils.HttpUtils;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageContentsList;
 
@@ -50,6 +50,15 @@ public class ClientRequestContextImpl ex
     }
     
     @Override
+    public MediaType getMediaType() {
+        if (!hasEntity()) {
+            return null;
+        }
+        Object mt = HttpUtils.getModifiableHeaders(m).getFirst(HttpHeaders.CONTENT_TYPE);
+        return mt instanceof MediaType ? (MediaType)mt : JAXRSUtils.toMediaType(mt.toString());
+    }
+    
+    @Override
     public Client getClient() {
         return (Client)m.getContextualProperty(Client.class.getName());
     }
@@ -155,18 +164,16 @@ public class ClientRequestContextImpl ex
 
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public MultivaluedMap<String, Object> getHeaders() {
         h = null;
-        return new MetadataMap<String, Object>(
-            (Map<String, List<Object>>)m.get(Message.PROTOCOL_HEADERS), false, false, true);    
-
+        return HttpUtils.getModifiableHeaders(m);
     }
 
     @Override
     public MultivaluedMap<String, String> getStringHeaders() {
-        return h.getRequestHeaders();
+        h = null;
+        return HttpUtils.getModifiableStringHeaders(m);
     }
 
 }

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientResponseContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientResponseContextImpl.java?rev=1525544&r1=1525543&r2=1525544&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientResponseContextImpl.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientResponseContextImpl.java Mon Sep 23 09:39:43 2013
@@ -19,15 +19,13 @@
 package org.apache.cxf.jaxrs.client.spec;
 
 import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
 
 import javax.ws.rs.client.ClientResponseContext;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.jaxrs.impl.AbstractResponseContextImpl;
-import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.ResponseImpl;
+import org.apache.cxf.jaxrs.utils.HttpUtils;
 import org.apache.cxf.message.Message;
 
 public class ClientResponseContextImpl extends AbstractResponseContextImpl 
@@ -39,23 +37,28 @@ public class ClientResponseContextImpl e
     }
     
     public InputStream getEntityStream() {
-        return m.getContent(InputStream.class);
+        InputStream is = m.getContent(InputStream.class);
+        if (is == null) {
+            is = ((ResponseImpl)r).convertEntityToStreamIfPossible();
+        }
+        return is;
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public MultivaluedMap<String, String> getHeaders() {
-        Object headers = m.get(Message.PROTOCOL_HEADERS);
-        if (headers != null) {
-            return new MetadataMap<String, String>((Map<String, List<String>>)headers, false, false, true);
-        }
-        return (MultivaluedMap<String, String>)(MultivaluedMap<?, ?>)r.getHeaders();
+        return HttpUtils.getModifiableStringHeaders(m);
     }
 
     
     @Override
     public void setEntityStream(InputStream is) {
         m.setContent(InputStream.class, is);
+        r.setEntity(is, r.getEntityAnnotations());
 
     }
+    
+    @Override
+    public boolean hasEntity() { 
+        return getEntityStream() != null;
+    }
 }