Hi,

I guess the problem is that in case if chunking is active, onClose() callback 
method is too late to set protocol headers, because part of message is already 
sent to the wire to this moment.

You can either add protocol headers in your business code:

Client proxy = ClientProxy.getClient(serviceClient);
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put(X_TIMESTAMP, Arrays.asList(new String[]> 
{extraHeaderInformation.getTimestamp()}));
proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);

Or in early phase interceptor:

public class MyOutInterceptor extends AbstractSoapInterceptor {

 public MyOutInterceptor() {
        super(Phase.POST_LOGICAL);
 }

 public void handleMessage(SoapMessage message) throws Fault {
 
        Map<String, List<String>> reqHeaders = CastUtils.cast((Map<?, 
?>)message.get(Message.PROTOCOL_HEADERS));
        if (reqHeaders == null) {
              reqHeaders = new HashMap<String, List<String>>();
        }
       headers.put(X_TIMESTAMP, Arrays.asList(new String[]> 
{extraHeaderInformation.getTimestamp()}));            
       message.put(Message.PROTOCOL_HEADERS, reqHeaders);
 ...
 }
}

Regards,
Andrei.


> -----Original Message-----
> From: Fengming.Lou [mailto:[email protected]]
> Sent: Freitag, 28. März 2014 19:16
> To: [email protected]
> Subject: Insert info to WS client request headers when chunking
> 
> Our WS service client inserts additional information to request headers using
> an instance of AbstractOutDatabindingInterceptor.  We are experiencing a
> problem that the additional information is not added to request header when
> chunking happens, but it works when there is no chunking.
> 
> Below is the interceptor code and cxf client configuration.
> 
> How we do it:
> 1. CacheAndWriteOutputStream is used with the interceptor 2. The code for
> writing to header is within the onClose() method of
> CachedOutputStreamCallback which is registered with the above output stream
> 
> What we understand:
> 1. When there is no chunking, the onClose() of the callback is called, and
> additional info is added to headers, when
> MessageSenderInterceptor$MessageSenderEndingInterceptor is invoked. The
> onClose() of the callback is triggered by calling HttpConduit.close() from the
> interceptor’s handleMessage(). This interceptor is the last one in the
> interceptor chain.
> 2. When there is chunking, all chunks but the last one are sent when
> SoapOutInterceptor$SoapOutEndingInterCeptor is invoked. This interceptor is
> after StaxOutInterceptor but before MessageSenderEndingInterceptor
> mentioned above.
> 3. The last chunk is written when when
> MessageSenderInterceptor$MessageSenderEndingInterceptor is handled.
> 
> So the problems appears to be that with chunking, the onClose() of the 
> callback,
> and thus the code inserting to headers, are called after the first chunks 
> being
> sent. We would like to find out what would be a good, or the beast way of
> addressing this issue. Any help would be appreciated.
> 
> Thanks.
> 
> 
> 
> public class MyInterceptor extends AbstractOutDatabindingInterceptor {
>    public MyInterceptor() {
>       super(Phase.PRE_STREAM);
>       addAfter(LoggingOutInterceptor.class.getName());
>       addBefore(StaxOutInterceptor.class.getName());
>    }
> 
>    @Override
>    public void handleMessage(Message message) {
> 
>       try {
>          final OutputStream os = message.getContent(OutputStream.class);
>          final Writer iowriter = message.getContent(Writer.class);
>          if (os == null && iowriter == null) {
>             return;
>          }
>          if (os != null) {
>             final CacheAndWriteOutputStream newOut = new
> CacheAndWriteOutputStream(os);
>             message.setContent(OutputStream.class, newOut);
>             newOut.registerCallback(new MyCallback(message, os));
>          } else {
> //
>          }
> 
>          } catch (Exception ce) {
>             throw new Fault(ce);
>          }
>       }
>    }
> 
>    class MyCallback implements CachedOutputStreamCallback {
> 
>       private final Message message;
>       private final OutputStream origStream;
> 
>       public MyCallback(final Message msg, final OutputStream os) {
>          this.message = msg;
>          this.origStream = os;
>       }
> 
>       @Override
>       public void onFlush(CachedOutputStream cos) {
>          // Nothing to do here
>       }
> 
>       @Override
>       public void onClose(CachedOutputStream cos) {
>          StringBuilder buffer = new StringBuilder(1024);
> 
>          try {
>             String encoding = (String) message.get(Message.ENCODING);
>             Map<String, List&lt;String>> headers = (Map<String,
> List&lt;String>>) message.get(Message.PROTOCOL_HEADERS);
>             ExtraHeaderInformation extraHeaderInformation = // an instance of
> extra header information
>             //Writing to header with extra info
>             headers.put(X_TIMESTAMP, Arrays.asList(new String[]
> {extraHeaderInformation.getTimestamp()}));
>          } catch (Exception ex) {
>             LOGGER.error(ex.getMessage(), ex);
>             throw new Fault(ex);
>          }
> 
>          try {
>             cos.lockOutputStream();
>             cos.resetOut(null, false);
>          } catch (Exception ex) {
>             LOGGER.error(ex.getMessage(), ex);
>             throw new Fault(ex);
>          }
>          message.setContent(OutputStream.class, origStream);
>       }
>    }
> }
> 
> 
> 
>   <http:conduit name="*.http-conduit">
>       <http:client ConnectionTimeout="600000" ReceiveTimeout="600000"
> ChunkingThreshold="4000"/>
>    </http:conduit>
> 
>    <bean id="myInterceptor"
>       class="MyInterceptor">
>    </bean>
> 
>    <jaxws:client id="myClient"
>       serviceClass="MyServicePortType"
>       xmlns:svc="http://myservice/wsdl/v1"; serviceName="svc:MyService"
>       endpointName="svc:MyServicePort" address="${service.url}"
>       wsdlLocation="classpath:myservice.wsdl">
>       <jaxws:properties>
>          <entry key="schema-validation-enabled" value="true" />
>          <entry key="org.apache.cxf.http.no_io_exceptions" value="true" />
>       </jaxws:properties>
>       <jaxws:inInterceptors>
>          <ref bean="httpHeaderInInterceptor" />
>       </jaxws:inInterceptors>
>       <jaxws:outInterceptors>
>          <ref bean="MyInterceptor" />
>       </jaxws:outInterceptors>
>    </jaxws:client>
> 
> 
> 
> 
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Insert-info-to-
> WS-client-request-headers-when-chunking-tp5742109.html
> Sent from the cxf-user mailing list archive at Nabble.com.

Reply via email to