Skip to main content

com.sun.xml.ws.message.saaj.SAAJHeader cannot be cast to com.sun.xml.ws.security. opt.impl.outgoing.SecurityHeader

No replies
bgottlieb
Offline
Joined: 2012-01-11
Points: 0

I'm trying to access a third party web service that requires me to create a security header passing in time information, user name, and password. I've scoured the web for working examples and have tried numerous ways. I'm trying to do this with just what's built into Java 6. I'm not sure what I'm doing wrong. After generating my web service client classes from the WSDL, I created the Handler below.

import java.util.Set;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.Text;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class MyHeaderHandler implements SOAPHandler<SOAPMessageContext>
{
  public boolean handleMessage(SOAPMessageContext context)
  {
    String prefixUri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-";
    String uri = prefixUri + "wssecurity-secext-1.0.xsd";
    String uta = prefixUri + "wssecurity-utility-1.0.xsd";
    String ta = prefixUri + "username-token-profile-1.0#PasswordText";
    Boolean isRequest = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if(isRequest)
    {
      try
      {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:dd.SSS'Z'");
        formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
        java.util.Date created = new java.util.Date();
        java.util.Date expires = new java.util.Date(created.getTime() + (5l * 60l * 1000l));
        SOAPMessage soapMsg = context.getMessage();
        SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
        SOAPHeader soapHeader = soapEnv.getHeader();
        if (soapHeader == null)
          soapHeader = soapEnv.addHeader();
        SOAPFactory factory = SOAPFactory.newInstance();
        SOAPElement securityElem = factory.createElement("Security", "o", uri);
        securityElem.addAttribute(QName.valueOf("s:mustUnderstand"), "0");
        SOAPElement timestampElem = factory.createElement("Timestamp", "u", uta);
        timestampElem.addAttribute(QName.valueOf("xmlns:u"), uta);
        timestampElem.addAttribute(QName.valueOf("Id"), "_0");
        SOAPElement elem = factory.createElement("Created", "u", uta);
        elem.addTextNode(formatter.format(created));
        timestampElem.addChildElement(elem);
        elem = factory.createElement("Expires", "u", uta);
        elem.addTextNode(formatter.format(expires));
        timestampElem.addChildElement(elem);
        securityElem.addChildElement(timestampElem);
        SOAPElement usernameElem = factory.createElement("UsernameToken", "o", uri);
        elem = factory.createElement("Username", "o", uri);
        elem.addTextNode("xxxxx");
        usernameElem.addChildElement(elem);
        elem = factory.createElement("Password", "o", uri);
        elem.addTextNode("xxxxx");
        elem.addAttribute(QName.valueOf("Type"), ta);
        usernameElem.addChildElement(elem);
        securityElem.addChildElement(usernameElem);
        soapHeader.addChildElement(securityElem);
      }
      catch(Exception e)
      {
        System.out.println("Handler error!!!! - " + e);
      }
    }
    return true;
  }

<p style="margin-right: 10px;">public boolean handleFault(SOAPMessageContext context) <br />  {<br />    return true;<br />  }</p><p style="margin-right: 10px;">public void close(MessageContext context)<br />  {<br />  }</p><p style="margin-right: 10px;">public Set&lt;QName&gt; getHeaders() <br />  {<br />    return null;<br />  }<br />}<br /> </p>

Next, I coded my test program to attach the handler and try calling the web service.

import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import org.tempuri.ServiceName;
import org.tempuri.IServiceName;
<p style="margin-right: 10px;">public class test<br />{<br /><span class="Apple-tab-span"> </span>public static void main(String[] args)<br /><span class="Apple-tab-span"> </span>throws Exception<br /><span class="Apple-tab-span"> </span>{<br />  <span class="Apple-tab-span"> </span>ServiceName service = new ServiceName(new URL(&quot;https://url.to.service/services/ServiceName.svc?wsdl&quot;), new QName(&quot;http://org.tempuri/&quot;, &quot;ServiceName&quot;));<br /><span class="Apple-tab-span"> </span>  service.setHandlerResolver(new HandlerResolver() <br />  <span class="Apple-tab-span"> </span>{<br />     public List&lt;Handler&gt; getHandlerChain(PortInfo portInfo) <br />     {<br />       List&lt;Handler&gt; handlerList = new ArrayList&lt;Handler&gt;();<br />       handlerList.add(new MyHeaderHandler());<br />       return handlerList;<br /><span class="Apple-tab-span"> </span>    }<br /><span class="Apple-tab-span"> </span>  });<br /><span class="Apple-tab-span"> </span>  IServiceName binding = service.getBasicHttpBindingIServiceName();<br />   ArrayLiist results = binding.getMyData(&quot;my parm&quot;);<br />   System.out.println(&quot;Size: &quot; + results.size());<br /><span class="Apple-tab-span"> </span>}<br />}</p>

When I run this, I get the following error at the line where i do binding.getMyData():

Exception in thread &quot;main&quot; java.lang.ClassCastException: com.sun.xml.ws.message.saaj.SAAJHeader cannot be cast to com.sun.xml.ws.security.opt.impl.outgoing.SecurityHeader
at com.sun.xml.ws.security.opt.impl.JAXBFilterProcessingContext.setJAXWSMessage(JAXBFilterProcessingContext.java:140)
<span class="Apple-tab-span"> </span>at com.sun.xml.wss.jaxws.impl.SecurityPipeBase.secureOutboundMessage(SecurityPipeBase.java:389)
<span class="Apple-tab-span"> </span>at com.sun.xml.wss.jaxws.impl.SecurityClientPipe.process(SecurityClientPipe.java:196)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:115)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.client.Stub.process(Stub.java:248)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
<span class="Apple-tab-span"> </span>at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
<span class="Apple-tab-span"> </span>at $Proxy40.getM(Unknown Source)
<span class="Apple-tab-span"> </span>at test.main(test.java:30)

Every approach I try ends up at the same point. How do I get around this? I can't figure out how to create the SecurityHeader to place into the header. Any help would be greatly appreciated. A working example would be great.

Thanks!