Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unmarshall SOAP XML to Java Object [duplicate]

Tags:

java

soap

xml

jaxb

while trying to unmarshall my soap XML to JAXB object am getting the following error.

We are getting error that expected element is none. Should anything specific be done while unmarshalling the SOAP XML.

javax.xml.bind.JAXBContext jaxbContext = (javax.xml.bind.JAXBContext) JAXBContext.newInstance(Class.forName(requestName));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(SoapXmlString);          
reqInfo = unmarshaller.unmarshal(reader);

Am getting the following error :

 javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are (none)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement

and here is the sample XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://example.com/v2">
       <soapenv:Header/>
       <soapenv:Body>
          <v2:createSession>
             <v2:client>
                <!--Optional:-->
                <v2:name>?</v2:name>
                <!--Optional:-->
                <v2:clientId>?</v2:clientId>
                <!--Optional:-->
                <v2:requestId>?</v2:requestId>
             </v2:client>
             <!--Optional:-->
             <v2:oldSessionId>?</v2:oldSessionId>
             <!--Optional:-->
             <v2:clientIp>?</v2:clientIp>
             <!--Optional:-->
             <v2:clientIpStatus>?</v2:clientIpStatus>
             <!--Optional:-->
             <v2:superBYOBFlow>?</v2:superBYOBFlow>
             <!--Optional:-->
             <v2:FlowParams>?</v2:FlowParams>
             <!--Optional:-->
             <v2:deviceInfo>?</v2:deviceInfo>
          </v2:createSession>
       </soapenv:Body>
    </soapenv:Envelope>

Please do help .

like image 909
srinath Avatar asked Sep 29 '14 10:09

srinath


People also ask

How to read XML file in Java using Jaxb?

To read XML, first get the JAXBContext . It is entry point to the JAXB API and provides methods to unmarshal, marshal and validate operations. Now get the Unmarshaller instance from JAXBContext . It's unmarshal() method unmarshal XML data from the specified XML and return the resulting content tree.

How do I create a SOAP request in Java?

To make SOAP requests to the SOAP API endpoint, use the "Content-Type: application/soap+xml" request header, which tells the server that the request body contains a SOAP envelope. The server informs the client that it has returned a SOAP envelope with a "Content-Type: application/soap+xml" response header.


1 Answers

I don't think you're taking the SOAP envelope into account... Your generated JAXB Unmarshaller won't know anything about the Body or Envelope tags, it will be expecting your createSession to be the root element hence the "unexpected element" error.

You need to extract the content from the Envelope first, you can do this with message.getSOAPBody().extractContentAsDocument() if you create a SOAPMessage object from your content first.

It's quite fiddly to do, here's a working example from my blog

String example =
        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
        new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());

It seems that if you don't declare your namespace in your schema .xsd file then you'll see the error you have.

I created a dummy schema with a root element createSession and by adding the targetNamespace attribute and regenerating the JAXB classes the error disappeared

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://example.com/v2"> <!-- targetNamespace essential for JAXB to work-->
    <xs:element name="createSession">  
        <xs:complexType>
            <xs:attribute name="foo" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>
like image 192
Adam Avatar answered Oct 05 '22 22:10

Adam