[
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)