Skip to main content

Adding SOAP headers in the JAX-WS RI is easier in 2.1 EA3

Posted by kohsuke on November 20, 2006 at 3:07 PM PST

One of the additions in the JAX-WS RI 2.1 EA3 is a simple way to add SOAP headers for your request.

The official "portable" way of doing this is that you creaate a SOAPHandler and mess with SAAJ. This works, but Vivek though it's just too much work for such a simple thing one day, and we all agreed. So we quickly put together a better way to do this. Here's how to do this:

When you create a proxy or dispatch object, they implement BindingProvider interface. When you use the JAX-WS RI, you can downcast to WSBindingProvider which defines a few more methods provided only by the JAX-WS RI.

This interface lets you set an arbitrary number of Header object, each representing a SOAP header. You can implement it on your own if you want, but most likely you'd use one of the factory methods defined on Headers class to create one.

import com.sun.xml.ws.developer.WSBindingProvider;

HelloPort port = helloService.getHelloPort();  // or something like that...
WSBindingProvider bp = (WSBindingProvider)port;

bp.setOutboundHeader(
  // simple string value as a header, like <simpleHeader>stringValue</simpleHeader>
  Headers.create(new QName("simpleHeader"),"stringValue"),
  // create a header from JAXB object
  Headers.create(jaxbContext,myJaxbObject)
);

Once set, it will take effect on all the successive methods. If you'd like to see more factory methods on Headers, please let us know!

We are also talking about adding a switch to wsimport so that you won't have to downcast.

Related Topics >>

Comments

Hello Kohsuke. Thks for U're post. I'm a beginner on ...

Hello Kohsuke.

Thks for U're post. I'm a beginner on Webservices Development and I'm having some trouble on SOAP headers customization. I need to set wsa:from , replyTo and To tokens on header but I've already seen that JAX-WS does not has a suitable way to do that :/

I was using the code below to connect to my endpoint:
service = new WebServiceService_Service();
proxy = service.getWebServiceServiceSoap(new AddressingFeature(true, false));

Map cxtx = ((BindingProvider)proxy).getRequestContext();
cxtx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
uri);
cxtx.put(JAXWSProperties.CONNECT_TIMEOUT, conf.getCentralManagementTimeout());

I just have control in client side. The Webservice I have to connect was developed by other company.

Can I use WSBindingProvider to set the header customization? How? I've tried this:

WSBindingProvider bp = (WSBindingProvider)proxy;

List myHeadersList = new ArrayList();
myHeadersList.add("http://localhost:8080/poc/helloService/");

bp.setOutboundHeaders(myHeadersList);
bp.setAddress(uri);

... but I got this error:

"javax.xml.ws.WebServiceException: com.sun.istack.XMLStreamException2: javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context."

Is there some way U can help me with this? Sorry about the lack of knowledge about this.

Thanks a lot.

Adding SOAP headers in the

This 2006 example of the Headers.create(jaxbContext, myJaxbObject) assumes the reader already has a reference to a jaxbContext. From what I've read it can be as easy as JAXBContext.newInstance(myJaxbObject) or JAXBContext.newInstance("jaxb.objects.package"), however in 2010 the Headers.create method takes a JAXBRIContext, not a JAXBContext. JAXBRIContext has the same newInstance methods, but there is only one newInstance method signature that returns a JAXBRIContext needed by Headers.create. It looks very long and complicated, and I don't know how to fill it in. In 2010 is there an easy way for developers to add a JAXB object graph into a JAXWS SOAP header? Thanks.

<p>&nbsp;</p> <p><strong>com.sun.xml.bind.api.JAXBRIContext ...

com.sun.xml.bind.api.JAXBRIContext extends javax.xml.bind.JAXBContext, so you can cast it.

Be careful not to mix namespaces, there are homonymous classes with "internal" in the FQCN that should not be used. For example, com.sun.xml.internal.bind.api.JAXBRIContext

Does this solution works with JAX-WS RI 2.1.1?

I tried using your solution and I am getting following error?
java.lang.ClassCastException: $Proxy135
I need to add SOAP headers and I can't find solution. I tried using the Handler and that doesn't work either. For some reason it doesn't invoke the handler I wrote. Is it because of JAX-WS version I m using?

Try this

I have spent a lot of time searching for a quick and neat solution for the same problem but could not find anything. But the following article was useful: http://soalogic.blogspot.com/

It worked for me, but.....

Hello Kohsuke.

I've tried your code and is working for me, but I need to add some attributes to the headers created..... as follows :

< User Type="company" > myusersname < /User >

How can I do that ?

Adding an attribute to a soap header

Hello, I am very new to this, so pardon me if I didn't understand your question correctly. The following works for me inside a message handler.
public boolean handleMessage(SOAPMessageContext messageContext) {
SOAPMessage msg = messageContext.getMessage();
SOAPHeader header = msg.getSOAPHeader();
// get the part
SOAPPart soapPart = msg.getSOAPPart();
// get the envelope from the part
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
// add a header to the envelope
header = soapEnvelope.addHeader();
// add a namespace declaration. headers MUST be "namespace-qualified"
header.addNamespaceDeclaration("hehe", "http://www.hehe.org");
// now add the child element User
SOAPElement soapElement = header.addChildElement(UserName);
// then add an attribute to the child element
soapElement.addAttribute(TypeName, "company");
// and finally add the value
soapElement.addTextNode("myusername");
}
Name UserName = new Name() {
public String getLocalName() {return "LocalNameUser";}
public String getQualifiedName() {return "User";}
public String getPrefix() {return "hehe";}
public String getURI() {return "http://www.hehe.org";}
};
Name TypeName = new Name() {
public String getLocalName() {return "LocalNameType";}
public String getQualifiedName() {return "Type";}
public String getPrefix() {return "hehe";}
public String getURI() {return "http://www.hehe.org";}
};
Hope this helps. I have just create variables of type javax.xml.soap.Name for this exercise. But this is usually generated by xmlbeans or whatever tools you may be using. Since I am new to this stuff, I really have no idea if a message handler is the appropriate place to insert soap headers, etc. I hope someone else can clarify that. BTW, how to add formatted code in my comments? Sorry for editing the message so many times. :( I hope you did not receive an email for each time I modified this message.

How are SOAP headers accessed in a Web service operation?

I have a client application that sets up some SOAP headers to specify a message ID and a callback URL, calls the Web service operation, and the Web service operation is supposed to callback asynchronously on the SOAP header provided URL. I can cheat, by creating a singleton map that maps MessageIDs to URLs, which is populated by the handler chain, and the operation can access this map, but this is not scalable, and it is nasty. The best would be if there were a way to access the SOAP headers inside the operation. In the operation I have access to the WebServiceContext, and so the MessageContext, and so the HTTP Request headers, but I can’t see how to access the SOAP headers. Is there a portable to do this in Metro 1.4?

To answer my own

To answer my own question: Use HeaderList headers = (HeaderList) messageContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);

How to set header in Web service response?

How to set the Header in response with different attribute values in it? followinn sets that in body of the response instead of header.? ABCHeader header = new ABCHeader(); header = this.setJDCHeader(header); response.setHeader(header);

contactasmi wrote:How to set

contactasmi wrote:
How to set the Header in response with different attribute values in it? followinn sets that in body of the response instead of header.? ABCHeader header = new ABCHeader(); header = this.setJDCHeader(header); response.setHeader(header);

The following link solved my issue. simple and clear. Using jaxb context messed up my namespace in the headers.
http://javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-...