I migrated a webservice client from jdk1.6 jax-ws (v1 ? An old one - 2005) to jdk1.7 jax-ws 2.2.10. The old one was functional, but I have a problem with the new one : The service (from another society, php server) responds to me : http 406 error, not acceptable.
The accept header I send is :
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
With the old version, I had :
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-type: text/xml;charset="utf-8"
So I tried to modify the http header like this (inside a new handler in my binding handler chain):
In my client :
javax.xml.ws.Binding binding = ((BindingProvider) ServiceXXX).getBinding();
List<Handler> hchain = binding.getHandlerChain();
if (hchain == null) {hchain = new ArrayList<Handler>();}
hchain.add(new HTTPUserAgentHandler());
binding.setHandlerChain(hchain);
In my new handler :
Map<String, List<String>> headers = (Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS);
if (null == headers) {headers = new HashMap<String, List<String>>();}
headers.put("Accept", Arrays.asList("text/xml", "multipart/related", "*/*"));
context.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
My http header is now correct but in HttpTransportPipe class, it's overwritten :
reqHeaders.put("Content-Type", Collections.singletonList(ct.getContentType()));
if (ct.getAcceptHeader() != null) {
reqHeaders.put("Accept", Collections.singletonList(ct.getAcceptHeader()));
}
if (binding instanceof SOAPBinding) {
writeSOAPAction(reqHeaders, ct.getSOAPActionHeader());
}
The server, apparently 1.1, needs I send an accept with "*/*"
Any Idea of how I can do this ?
I think I found a way, it's not the perfect solution ... (If someone has better ..)
So :
I added a file named com.sun.xml.ws.api.pipe.TransportTubeFactory
in ./src/META-INF/services
in which there is:
com.YYY.XXX.MonHttpTransportTubeFactory
I added this class:
package com.YYY.XXX;
import com.sun.xml.ws.api.pipe.ClientTubeAssemblerContext;
import com.sun.xml.ws.api.pipe.TransportTubeFactory;
import com.sun.xml.ws.api.pipe.Tube;
import com.sun.xml.ws.transport.http.client.HttpTransportPipe;
public class MonHttpTransportTubeFactory extends TransportTubeFactory{
@Override
public Tube doCreate(ClientTubeAssemblerContext context) {
context.setCodec(new MonSOAPBindingCodec(context.getBinding().getFeatures()));
return new HttpTransportPipe(context.getCodec(), context.getBinding());
}
}
and this one : (copy of existing SOAPBidingCodec
jaxws-ri src) :
public class MonSOAPBindingCodec extends MonMimeCodec implements com.sun.xml.ws.api.pipe.SOAPBindingCodec {
...
public MonSOAPBindingCodec(WSFeatureList features, StreamSOAPCodec xmlSoapCodec) {
super(getSoapVersion(features), features);
this.xmlSoapCodec = xmlSoapCodec;
xmlMimeType = xmlSoapCodec.getMimeType();
String clientAcceptedContentTypes = xmlSoapCodec.getMimeType() + ", */*";
WebServiceFeature fi = features.get(FastInfosetFeature.class);
...
So the service call my HttpTransportTubeFactory
and includes my custom SOAP codec.
It's not very beautiful, but it works ..