Axis security header

yurl picture yurl · Jul 1, 2010 · Viewed 19.5k times · Source

Hi trying to generate a security header in a Java Axis2 Client program in the format of.

<soapenv:Header>
 <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext>
  <wsse:UsernameToken>
   <wsse:Username>myUsername</wsse:Username>
   <wsse:Password>myPassword</wsse:Password>
  </wsse:UsernameToken>
 </wsse:Security>
</soapenv:Header>

using the following code

SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName("http://schemas.xmlsoap.org/ws/2002/04/secext","Security", "wsse"));
MessageElement usernameToken = new MessageElement("", "wsse:UsernameToken");
MessageElement username = new MessageElement("", "wsse:Username");
MessageElement password = new MessageElement("", "wsse:Password");
username.setObjectValue(myProps.getProperty("username"));
usernameToken.addChild(username);
password.setObjectValue(myProps.getProperty("password"));
usernameToken.addChild(password);
wsseSecurity.addChild(usernameToken);

BookingPort bp = bsl.getBooking();
((Stub) bp).setHeader(wsseSecurity);

Unfortunately its not generating quite what I wanted and I get.

<soapenv:Header>
 <wsse:Security soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
  <wsse:UsernameToken xmlns:wsse="">
   <wsse:Username xmlns:wsse="">myUsername</wsse:Username>
   <wsse:Password xmlns:wsse="">myPassword</wsse:Password>
  </wsse:UsernameToken>
 </wsse:Security>
</soapenv:Header>

The service on the other end doesn't seem to handle the extra bits, resulting in an error

faultDetail:
        {http://xml.apache.org/axis/}stackTrace:com.ctc.wstx.exc.WstxParsingException: Non-default namespace can not map to empty URI (as per Namespace 1.0 # 2) in XML 1.0 documents
 at [row,col {unknown-source}]: [1,450]

How do I generate the SOAPHeader to not print out all the extra empty bits? Cheers

Answer

Justin Garrick picture Justin Garrick · Jul 27, 2010

You're passing an empty string as the first argument to MessageElement, and you need to pass null. Note that null and the empty string ("") are not the same thing in Java. Also, you are really cheating by passing the namespace prefix to the local name (second) parameter of the MessageElement constructor...this is not what it is designed for. That being said, you can fix the problem by passing null as the namespace (first) parameter. If you try to pass it directly, you'll likely get an ambiguous constructor error, so do something like the following:

SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName("http://schemas.xmlsoap.org/ws/2002/04/secext","Security", "wsse"));
String nullString = null;
MessageElement usernameToken = new MessageElement(nullString, "wsse:UsernameToken");
MessageElement username = new MessageElement(nullString, "wsse:Username");
MessageElement password = new MessageElement(nullString, "wsse:Password");
username.setObjectValue(myProps.getProperty("username"));
usernameToken.addChild(username);
password.setObjectValue(myProps.getProperty("password"));
usernameToken.addChild(password);
wsseSecurity.addChild(usernameToken);

BookingPort bp = bsl.getBooking();
((Stub) bp).setHeader(wsseSecurity);

I'd also recommend you use a different web service engine (not Axis2) if you have any choice in the matter.