[ 
https://issues.apache.org/jira/browse/CXF-5573?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sergey Beryozkin resolved CXF-5573.
-----------------------------------

    Resolution: Not A Problem

> http-request is sent before PhaseInterceptorChain gets to send-phase if 
> http-request is chunked (because its too long)
> ----------------------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-5573
>                 URL: https://issues.apache.org/jira/browse/CXF-5573
>             Project: CXF
>          Issue Type: Bug
>          Components: Bus, Core, JAX-RS, Transports
>    Affects Versions: 2.7.5
>         Environment: Spring
> Windows 7
> Tomcat 7.0.50
> JDK 1.7_51
>            Reporter: Michael Svoboda
>            Priority: Minor
>
> While I wrote some REST-Webservices that communicate among each other I came 
> across some surprising behaviour during the PhaseInterceptor invocations. 
> I wrote a PhaseInterceptor for the phase "MARSHAL" that attaches a custom 
> HTTP header to each outgoing message. But it seemed that in some cases (in 
> most others it worked fine) he failed to attach this header to outgoing 
> HTTP-requests. After some investigating I saw that only HTTP messages which 
> where chunked (because the body was too long) seemed to be missing the custom 
> header. On HTTP messages that were not chunked (i.e. simply had a 
> content-length header) everything worked as expected.
> Then I had a look at the cxf debug log messages and saw the problem.
> {code:title=Log}
> DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Chain 
> org.apache.cxf.phase.PhaseInterceptorChain@4d184e was modified. Current flow:
>   prepare-send [MessageSenderInterceptor]
>   >>>write [ClientRequestFilterInterceptor, BodyWriter]
>   >>>marshal [MyInterceptor]
>   prepare-send-ending [MessageSenderEndingInterceptor]
> DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on 
> interceptor 
> org.apache.cxf.jaxrs.client.spec.ClientRequestFilterInterceptor@14c8a89
> >>>DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage 
> >>>on interceptor 
> >>>org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter@11fdaab
> DEBUG org.apache.cxf.transport.http.Headers - Accept: text/plain
> DEBUG org.apache.cxf.transport.http.Headers - Connection: Keep-Alive
> DEBUG org.apache.cxf.transport.http.Headers - Content-Type: text/plain
> DEBUG org.apache.cxf.transport.http.HTTPConduit - No Trust Decider for 
> Conduit '{http://<myRestService>.http-conduit'. An afirmative Trust Decision 
> is assumed.
> >>>DEBUG org.apache.cxf.transport.http.HTTPConduit - Sending POST Message 
> >>>with Headers to http://localhost:8080/<mypath>/test/something Conduit 
> >>>:{http://<myRestService>.http-conduit
> >>>DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage 
> >>>on interceptor mypackage.MyInterceptor@d5940e
> DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on 
> interceptor 
> org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor@176e488
> {code}
> For some reason the HTTP message was sent before my Interceptor got the 
> chance to attach the custom header. The PhaseInterceptorChain only invoked my 
> Interceptor after it was sent and added the custom header too late.
> I simply worked around this problem by setting the phase of the interceptor 
> to "PRE_PROTOCOL" which is before the "WRITE" phase (where the HTTP message 
> seems to be sent).
> While you can rather easily work around this problem, it is still something 
> that should be fixed, so the next developer doesn't end up spending hours 
> searching for the problem like I did.
> My Spring configuration contains something like this:
> {code:title=Spring config}
> <jaxrs:server address="/myservices">
>     <jaxrs:serviceBeans>
>       <bean class="mypackage.TestRestServiceImpl" />
>     </jaxrs:serviceBeans>
> </jaxrs:server>
> ...
> <http-conf:conduit name=".*">
>     <http-conf:client ConnectionTimeout="0" ReceiveTimeout="0" />
> </http-conf:conduit>
> <bean id="myInterceptor" class="mypackage.MyInterceptor" />
> <cxf:bus>
>     <cxf:outInterceptors>
>       <ref bean="myInterceptor" />
>     </cxf:outInterceptors>
> </cxf:bus>
> {code}
> Example code that shows the basics of my REST-Service
> {code:title=MyInterceptor.java}
> public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
>   @Inject
>   private MyContext myContext;
>   public MyInterceptor() {
>     super(Phase.MARSHAL);
>   }
>   @Override
>   public void handleMessage(Message m) throws Fault {
>     @SuppressWarnings("unchecked")
>     MultivaluedMap<String, Object> headers = (MultivaluedMap<String, Object>) 
> m.get(Message.PROTOCOL_HEADERS);
>     if (headers == null) {
>       headers = new MetadataMap<String, Object>();
>       m.put(Message.PROTOCOL_HEADERS, headers);
>     }
>     headers.putSingle("X-myheader", myContext.generateHeader());
>     m.put(Message.PROTOCOL_HEADERS, headers);
>   }
> }
> {code}
> {code:title=TestRestService.java}
> @Path("/test")
> @Consumes(MediaType.TEXT_PLAIN)
> public interface TestRestService {
>   @Produces(value = MediaType.TEXT_PLAIN)
>   @POST
>   @Path("/something")
>   public String doSomething(String order);
> }
> {code}
> {code:title=TestRestServiceImpl.java}
> public class TestRestServiceImpl implements TestRestService {
>   @Override
>   public String doSomething(String msg) {
>     return "i got your message '"+msg+"', thanks.";
>   }
> }
> And here an example of how I send the HTTP request:
> {code}
> {code:title=ClientTest.java}
> public class ClientTest {  
>   public static void main(String [] args){
>     TestRestService client = 
> JAXRSClientFactory.create("http://localhost:8080/<mypath>/test/something", 
> TestRestService.class);
>     StringBuilder sb= new StringBuilder(1024*16);
>     
>     for(int i=1; i <= 16; i++){            
>       sb.append(StringUtils.repeat("X", 1024));      
>     }
>     
>     try{
>       client.doSomething(sb.toString());
>     }catch(Exception e){
>       //just need to send it
>     }
>   }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)

Reply via email to