3 Replies Latest reply on Jun 18, 2007 4:28 PM by Thomas Diesler

    Duplicate SOAP body/envelope tags in SOAP message

    John Perez Newbie

      I have written two web services that I have tested separately and now I am trying to call one web service from the other. I have a client that is succesfully calling web service A, but when A tries to call web service B I get this message:

      16:08:03,834 ERROR [SOAPFaultExceptionHelper] SOAP request exception
      javax.xml.rpc.soap.SOAPFaultException: Endpoint {http://acxiom.com/greeting/1.0}GetGreetingEjbInterf
      acePort does not contain operation meta data for: {http://schemas.xmlsoap.org/soap/envelope/}Envelope

      This is the SOAP message that is being sent:

      <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:Header/><env:Body><env:Envelope xmlns:enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns0='http://acxiom.com/greeting/1.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><env:Body><ns0:getGreeting xmlns:ns0='http://acxiom.com/greeting/1.0'/></env:Body></env:Envelope></env:Body></env:Envelope>

      Note that there are two env:Envelope and two enb:Body tags. I am not sure what I need to do to get this to work.

      I am using JBOSS 4.0.4, jdk 1.5.0.7 and jwsdp 2.0.

      I use wstools to generate the server artifacts for web service a using this configuration file:


      <java-wsdl>
      <service name="HelloEjbService" style="document" parameter-style="wrapped"
      endpoint="com.acxiom.mypkg.HelloEjbInterface"/>

      <namespaces target-namespace="http://acxiom.com/hello/1.0"
      type-namespace="http://acxiom.com/hello/1.0"/>


      <webservices ejb-link="HelloService"/>
      </java-wsdl>


      Web service A is the client to web service B and I use wscompile to generate the artifacts using this configuration file:





      Web service B uses WSTOOLS and this configuration file:


      <java-wsdl>
      <service name="GreetingEjbService" style="document" parameter-style="wrapped"
      endpoint="com.acxiom.mypkg.GetGreetingEjbInterface"/>

      <namespaces target-namespace="http://acxiom.com/greeting/1.0"
      type-namespace="http://acxiom.com/greeting/1.0"/>


      <webservices ejb-link="GreetingService"/>
      </java-wsdl>


      Any help would be appreciated!

      John

        • 1. Re: Duplicate SOAP body/envelope tags in SOAP message
          John Perez Newbie

          I have determined that the problem is that I need to be able to clear the soap headers before calling the second web service. What's happening is that the second web service is being wrapped in the env/body tags from the first web service, which is why I am geeting multiple tags. I determined this by writing my own code that creates a SOAP message and sends it to the web service. The web service replies correctly.

          Does anyone know how to clear the SOAP headers or in some other way to get this to work?

          • 2. Re: Duplicate SOAP body/envelope tags in SOAP message
            John Perez Newbie

            I succeeded in calling a web service, from a web service. However, I'd really like someone out there who knows what they are doing to show me how to do this correctly. I am sure there is a better way than what I did.

            This is how I got it to work:

            1. Create web service B as a stateless session bean web service using wstools to create artifacts (ejb 2.1). Deployed web service.

            2. Create web service A as a stateless session bean using wscompile to generate web service artifacts. Copied WSDL from web service B and used wscompile to create client artifacts. However, I don't ever use the generated stub/service/serializer classes, because when I do, I get a SOAP message with duplicate body/envelope tags. What I do is create my own SOAP message using a SOAPMessageFactory. Then I added namespacese, attributes and elements to the message so it complies with the WSDL. Next I create a connection and call the web service. When the message returns I parse it, retrieve the return value and pass it back to the client.

            3. Create a web client that calls web service A. Web service A calls web service B, which returns a value to A, which returns a value to the client.

            So, web service A is both a server to the web client and a client to web service B. Web service A recieves the SOAP message from the web client and immediately calls web service B. Here is the code in web service A that calls web service B:

            SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = scf.createConnection();
            MessageFactory msgFactory = MessageFactory.newInstance();

            // Create a message
            SOAPMessage msg = msgFactory.createMessage();

            // Create an envelope in the message
            SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();

            // Bind ns0 namespace
            envelope.addNamespaceDeclaration("ns0","http://aaa/bbb/1.0");

            // Get hold of the the body
            SOAPBody body = envelope.getBody();

            body.addChildElement(envelope.createName("ns0:getGreeting", "", ""))
            .addAttribute(envelope.createName("ns0"), "http://aaa/bbb/1.0");

            URL endpoint = new URL("http://localhost:8082/ws/getGreeting");

            msg.saveChanges();

            // Make call to web service
            SOAPMessage soapMessage = connection.call(msg, "http://localhost:8082/ws/getGreeting");

            soapMessage.writeTo(System.out);

            // The return value is in the grandchild element to the body tag.
            Iterator it = soapMessage.getSOAPBody().getChildElements();
            SOAPElement child = it.next();
            Iterator it2 = child.getChildElements();
            SOAPElement result = it2.next();

            responseMessage = result.getValue();

            As I said, there has to be an easier way to do this. If someone could show me a simpler way to call a web service from a web service, I'd appreciate it.