JAX-WS Streaming/MTOM with WSSE UsernameToken WITHOUT using MessageHandler

Hi, Happy Chinese New Year!

A while back I have this post about Data Handler Issue when using MTOM for Streaming SOAP services Issue with Streaming/MTOM with DataHandler. The issue was essentially that any message handler after the will cause load of whole binary content into memory and hence cause Out of Memory issues at the client side if the binary content is too large. I described a solution for the CXF implementation.  Now I have searched and tested a solution when use JAX-WS default implementation, thanks mostly to this post in StackOverflow Link.

import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPFactory;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.Headers;
//Static Strings
private static String SECURITY_NS = “http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”;
private static String PASSWORD_TYPE = “http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText”;
private static String AUTH_PREFIX = “wss”;
// Prepare Service and Port
MyService service = getMySerice();
MyservicePort port = service.getMyServicePort();
BindingProvider bp = (BindingProvider)port;
SOAPBinding soapbinding = (SOAPBinding) bp.getBinding();
soapbinding.setMTOMEnabled(true);
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPElement security = soapFactory.createElement(“Security”, AUTH_PREFIX, SECURITY_NS); SOAPElement uToken = soapFactory.createElement(“UsernameToken”, AUTH_PREFIX, SECURITY_NS);
SOAPElement username = soapFactory.createElement(“Username”, AUTH_PREFIX, SECURITY_NS);
username.addTextNode(this.getUserName().trim());
SOAPElement pass = soapFactory.createElement(“Password”, AUTH_PREFIX, SECURITY_NS); pass.addAttribute(new QName(“Type”), PASSWORD_TYPE); pass.addTextNode(this.getPassword().trim());
uToken.addChildElement(username);
uToken.addChildElement(pass);
security.addChildElement(uToken);
Header header = Headers.create(security);
((WSBindingProvider) port).setOutboundHeaders(header);
port.myOperation();

This way, the Security Header will have the WSSE UsernameToken without disturbing MTOM payload which is being streamed in my operation. If the WSSE header were processed in MessageHandler, any huge binary payload would cause Out of Memory exception very quickly and fail the whole SOAP invocation right off the bat.

Cheers!

-Tony

Advertisements

Attribute “xmlns:ns2” was already specified for element …

Hi, all:

It is surely cold here in northeast right now. January does have its own teeth! 😦

I am posting something I found during a SOAP Webservice invocation, which I hope can help you save some time in your development.

There was an error message when a SOAP client gets and parses a response from a SOAP Webservice and it started to complain about something like:

Attribute “xmlns:ns2” was already specified for element …..

It puzzled me at the first glance because in the actual captured SOAP response, the element the error is complaining about has no prefix “ns2” at all. After a couple days of not knowing what is wrong, I finally noticed that the element in the SOAP response has an empty seemingly benign namespace attribute:

xmlns=””

This one is actually the culprit! The error is actually indicating that the element SHOULD have a namespace based on the WSDL/XSD (in this case it was designed to have namespace of http://www.w3.org/2005/08/addressing).  The empty namespace xmlns=”” triggered the error during parsing!  After fixing at the server side to ensure the SOAP response has the correct namespace designated for the element as http://www.w3.org/2005/08/addressing, the problem went away!

Now, the question remains why the error is complaining about the xmlns:ns2? i.e. where does the ns2 prefix come from? It is actually quite obvious when I look at the whole SOAP response. The ns2 prefix is mapped to the URI http://www.w3.org/2005/08/addressing at the root element of the SOAP response, thus, the error is referring to that prefix throughout the whole document.

Next time when we see similar error message to this, we can easily find out what namespace the element of concern should have and enforce it to be assigned correctly.

Stay warm!

-Tony