SOAP message with javax.xml.soap - namespace error?

29,921

Solution 1

You are binding a namespace uri to a prefix and later try to create an element with the same prefix but with a null namespace uri:

envelope.addNamespaceDeclaration("tem", "http://tempuri.org/");
...
QName bodyName = new QName(null, "setAMRequestData", "tem");

An element is identified by the combination of namespace uri and local name. To solve this problem you have to specify the namespace on each element you create:

QName bodyName = new QName("http://tempuri.org/", "setAMRequestData", "tem");
...
QName n = new QName("http://tempuri.org/", "id", "tem");

Solution 2

Don't get all worked up because the XML coming out of your app doesn't look exactly the same (especially with namespace prefixes) as the request made by SoapUI. Paste your code into a SoapUI request, right-click, re-format, and see if SoapUI understands your stuff (and if you have the pro version, check it in form and outline views). If it looks ok, fire it off and see if you get the same response as the native (soapUI) request. If so, you're good to go. If, however, things are in the wrong place, namespaces are mangled, SoapUI can't render your XML, then you've got some tweaking to do in your code.

Share:
29,921
Less
Author by

Less

Java / .Net / C++ developer, nearly 3 years of working experience

Updated on July 09, 2022

Comments

  • Less
    Less almost 2 years

    The following is a generic sample SOAP request for .NET web service I'm supposed to invoke from my java web app:

    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
     <soap:Body>
      <setAMRequestData xmlns="http://tempuri.org/">
        <id>int</id>
      </setAMRequestData>
     </soap:Body>
    </soap:Envelope>
    

    I am able to generate something similar from java console application using this code segment:

    import javax.xml.XMLConstants;
    import javax.xml.namespace.QName;
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPBodyElement;
    import javax.xml.soap.SOAPConnection;
    import javax.xml.soap.SOAPConnectionFactory;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPMessage;
    ...
    SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
    SOAPConnection connection = sfc.createConnection();
    MessageFactory mf = MessageFactory.newInstance();
    SOAPMessage sm = mf.createMessage();
    
    SOAPHeader sh = sm.getSOAPHeader();
    SOAPBody sb = sm.getSOAPBody();
    sh.detachNode();
    
    QName bodyName = new QName("http://tempuri.org/", "setAMRequestData", XMLConstants.DEFAULT_NS_PREFIX);
    SOAPBodyElement bodyElement = sb.addBodyElement(bodyName);
    QName n = new QName("id");                                          
    SOAPElement quotation = bodyElement.addChildElement(n);
    quotation.addTextNode("121152");
    

    The result is the following XML:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     <SOAP-ENV:Body>
      <setAMRequestData xmlns="http://tempuri.org/">
       <id>121152</id>
      </setAMRequestData>
     </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    

    This invokes the service. Next, I used soapUI to try to invoke this service, and it generated soap message from WSDL like this (it differs from the previous in the namespace declaration in envelope, and prefixes):

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                      xmlns:tem="http://tempuri.org/">
     <soapenv:Header/>
      <soapenv:Body>
       <tem:setAMRequestData>
         <tem:id>?</tem:id>
       </tem:setAMRequestData>
      </soapenv:Body>
     </soapenv:Envelope>
    

    This also works from soapUI. But finally, when I tried to recreate this form of soap message using this code sequence:

    // factories and stuff, like in the example above
    SOAPPart part = sm.getSOAPPart();
    SOAPEnvelope envelope = part.getEnvelope();
    envelope.addNamespaceDeclaration("tem", "http://tempuri.org/");
    
    SOAPHeader sh = sm.getSOAPHeader();
    SOAPBody sb = sm.getSOAPBody();
    sh.detachNode();
    
    QName bodyName = new QName(null, "setAMRequestData", "tem");
    SOAPBodyElement bodyElement = sb.addBodyElement(bodyName);
    QName n = new QName(null, "id", "tem");
    SOAPElement quotation = bodyElement.addChildElement(n);
    quotation.addTextNode("7028");
    

    I got the following exception in line SOAPElement quotation = bodyElement.addChildElement(n);:

    org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.

    No matter what I tried, I simply couldn't set "tem" prefix for the id element... What is going on here?

    Thanks.

  • Less
    Less over 12 years
    Yeah, this solves it. Apparently I ran into some bad example of javax.xml.soap usage... Thanks.
  • Less
    Less over 12 years
    The only difference between XML coming out of my app and the one generated by soapUI is now the envelope prefix (SOAP-ENV vs soapenv), but URI for that prefix is the same in both cases. Based on what I read prefix should be irrelevant as long as URI is the same?
  • Chris Thornton
    Chris Thornton over 12 years
    Correct. As long at the prefixes reference the same URI, you're good.