Hi

I am trying to create a simple handler which alters the content of the
SOPABody of an incoming SOAP message.

The web service I am using is a simple "echo" web service with a single
method called echo. The methods takes a string and just returns it.

The code for the handler is as follows:

package com.trifork.eas.test.webservices.echoservice;

import java.io.*;
import java.io.InputStream;
import java.util.*;
import java.util.Iterator;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.*;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.*;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.stream.*;

/**
 * Created: Jan 20, 2003
 *
 * @author Claus Nyhus Christensen <[EMAIL PROTECTED]>
 */
public class EchoServiceServerHandler implements Handler {

  public boolean handleRequest(MessageContext messageContext) {

    try {
      SOAPMessageContext soapMsgCtx = (SOAPMessageContext)
messageContext;
      SOAPMessage soapMsg = soapMsgCtx.getMessage();
      SOAPPart soapPart = soapMsg.getSOAPPart();
      SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
      soapEnvelope.getBody().detachNode();
      SOAPBody soapBody = soapEnvelope.addBody();
      SOAPBodyElement echoElement =
soapBody.addBodyElement(soapEnvelope.createName("echo", "ns1",
"http://soapinterop.org/";));
      SOAPElement argElement = echoElement.addChildElement("arg0");
      argElement =
argElement.addAttribute(soapEnvelope.createName("type", "xsi",
"http://www.w3.org/2001/XMLSchema-instance";), "xsd:string");
                        argElement.addTextNode("a new string");
                        soapMsg.saveChanges();

    } catch (Exception e) {
      e.printStackTrace();
    }

    return true;
  }

...

}

Now, when my client tries to call the web service, I get the following
exception:

AxisFault
 faultCode:
{http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode: 
 faultString: java.lang.Exception: No deserialization context to use in
MessageElement.getValueAsType()!
 faultActor: null
 faultNode: null
 faultDetail: 
        stackTrace: java.lang.Exception: No deserialization context to
use in
MessageElement.getValueAsType()!
        at
org.apache.axis.message.MessageElement.getValueAsType(MessageElement.java:544)
        at
org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:150)
        at
org.apache.axis.providers.java.JavaProvider.invoke(JavaProvider.java:332)
        at
org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:71)
        at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:156)
        at org.apache.axis.SimpleChain.invoke(SimpleChain.java:126)
        at
org.apache.axis.handlers.soap.SOAPService.invoke(SOAPService.java:469)
        at org.apache.axis.server.AxisServer.invoke(AxisServer.java:326)
        at
org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:782)
....

I have been looking into the code, and it seems that the way the
original SOAPBody is build is different from the way it is done when you
use the JAXM methods on the SOAPBody class.

I have tried the same example using the JAXRPC/SAAJ reference
implementations and it works just fine there.

To me it seems that:

1. I am doing something completely wrong in my handler
or
2. The addBodyElement on the SOAPBody class is not working as is should

If you agree with me that number 2 is the case, I would like to help
create a fix. But I cannot figure out how I am going to be able to get a
DeserializationContext in the SOAPBody class.

A related problem occur if you use the addChildElement on SOAPBody
instead of addBodyElement. When you do this a new MessageElement is
added to the SOAPBody. However, this will result in a ClassCastException
in the processMessage of the RPCProvider class. Line 141 and 142 gives
the problem:
if (!(bodies.get(bNum) instanceof RPCElement)) {
SOAPBodyElement bodyEl = (SOAPBodyElement)bodies.get(bNum);

Since the MessageElement is not an instance of RPCElement, it is cast to
a SOAPBodyElement. This will result in the ClassCastException. This case
also works fine on the JAXRPC/SAAJ reference implementation.

The fix seems to be to overwrite the addChildElement methods in SOAPBody
(which it inherits from MessageElement) to make sure that
SOAPBodyElements (or maybe RPCElement) are always added. However, this
fix will have the same problem with the DeserializationContext as stated
above.


I hope this mail was not to long, and was posted to the right
mailinglist :)

Cheers

-- 
Claus Nyhus Christensen
Software Engineer, M. Sc. CS.

Trifork, Margrethepladsen 3, DK-8000 ?rhus C, Denmark
Phone: +45 8732 8787 / Fax: +45 8732 8788 / http://www.trifork.com


Reply via email to