[ 
https://issues.apache.org/jira/browse/CXF-5573?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13907125#comment-13907125
 ] 

Sergey Beryozkin commented on CXF-5573:
---------------------------------------

Hi, can you please use JAX-RS 2.0 ClientRequestFilter (registered as jaxrs 
provider) for adding the extra headers and CXF 2.7.10 ? 

This should lead to the consistent behavior.

I'm not sure if it is possible to control it otherwise, by keeping the 
interceptors adding the headers at the Marshal stage, there's a number of cases 
when the initial HTTP Message is pushed immediately, which includes the 
headers...Marshal is ultimately about writing the request body, no guarantee 
the headers won't have already been sent...

Dan, is it right ?

Thanks, Sergey

> 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