Java SOAPResponse to Marshall - Expected elements are <{}request> - java

I want to map object from a SOAPResponse, so that, I'm using Marshall, but there is an error.
Response
<env:Envelope
xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header></env:Header>
<env:Body>
<ns1:cancelShipmentResponse
xmlns:ns1='http://yurticikargo.com.tr/ShippingOrderDispatcherServices'
xmlns:ns2='http://yurticikargo.com.tr/ShippingOrderDispatcherServices'
xmlns:ns3='http://yurticikargo.com.tr/WSExceptions/'>
<ShippingOrderResultVO>
<outFlag>1</outFlag>
<outResult>Yurtiçi Kargo sisteminde kayıtlı TR kullanıcı adlı bir kullanıcı yok!</outResult>
<errCode>1625</errCode>
<count>0</count>
<senderCustId>0</senderCustId>
</ShippingOrderResultVO>
</ns1:cancelShipmentResponse>
</env:Body></env:Envelope>
My Object
#XmlRootElement(name = "cancelShipmentResponse", namespace = "http://yurticikargo.com.tr/ShippingOrderDispatcherServices")#XmlAccessorType(XmlAccessType.FIELD)public class CancelShipmentResponse {#XmlElement(name = "ShippingOrderResultVO")ShipingOrderResultVO shipingOrderResultVO;}
My Codes
JAXBContext jc = JAXBContext.newInstance(CancelShipmentRequest.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
CancelShipmentRequest rc = (CancelShipmentRequest) unmarshaller.unmarshal(soapResponse.getSOAPBody());

Related

Java Unmarshalling issue (jaxb) [duplicate]

I am using JAXB to parse xml elements from the SOAP response. I have defined POJO classes for the xml elements. I have tested pojo classes without namespace and prefix its working fine .Though when i am trying to parse with namespaces and prefix facing the following exception.Requirement is to parse the input from SOAPMessage Object
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
Tried to fix by creating #XMLSchema for the package in package-info.java and located this file in package folder.Can any one guide me to move forward?
Referred this posts but didn help me .
EDITED :XMLSchema
#javax.xml.bind.annotation.XmlSchema (
xmlns = { #javax.xml.bind.annotation.XmlNs(prefix = "env",
namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
#javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
Thanks in advance
This can be done without modifying the generated JAXB code using standard SOAPMessage class. I wrote about this here and here
It's a little fiddly but works correctly.
Marshalling
Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());
Unmarshalling
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());
Here is how you can handle your use cae:
If You Need to Map the Envelope Element
package-info
Typically you would use the #XmlSchema as follows. Using the namespace and elementFormDefault properties like I've done means that all data mapped to XML elements unless otherwise mapped will belong to the http://www.xxxx.com/ncp/oomr/dto/ namespace. The information specified in xmlns is for XML schema generation altough some JAXB implementations use this to determine the preferred prefix for a namespace when marshalling (see: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
#XmlSchema (
namespace="http://www.xxxx.com/ncp/oomr/dto/",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
#XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
import javax.xml.bind.annotation.*;
Envelope
If within the com.one.two you need to map to elements from a namespace other than http://www.xxxx.com/ncp/oomr/dto/ then you need to specify it in the #XmlRootElement and #XmlElement annotations.
package com.one.two;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
#XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
#XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
}
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
If You Just Want to Map the Body
You can use a StAX parser to parse the message and advance to the payload portion and unmarshal from there:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("return")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
xsr.close();
}
}
For More Information
http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
Just wanted to add onto the existing answers -- while unmarshalling if the XML document is not namespace aware you might receive an error: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://some.url";, local:"someOperation")
If this is the case you can simply use a different method on the unmarshaller:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();

How to get the node value in the ValidationEventHandler of JAXB while unmarshalling?

How can I get the node details in the ValidationEventHandler in JAXB when an exception occurs while Unmarshalling?
My code:
JAXBContext jaxbContext = JAXBContext.newInstance("com.piyush");
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new StreamSource(new File("D:/liferay-develop/workspace/cat_test/v1/STD_MP.xsd")));
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
jaxbUnmarshaller.setSchema(schema);
ValidationEventCollector validationCollector= new ValidationEventCollector();
jaxbUnmarshaller.setEventHandler( validationCollector );
STDMP ts = (STDMP)jaxbUnmarshaller.unmarshal(xml_gkuzu);
if(validationCollector.hasEvents())
{
for(ValidationEvent event:validationCollector.getEvents())
{
String msg = event.getMessage();
System.out.println(msg);
// How to get the node details here ? I'm getting null value for node.
}

JAXB Unmarshalling of bad XML does not throw exception

I'm trying to unmarshal an XML string that does not match the JAXB class. I expected this to throw an exception, but instead, a new JAXB object is returned.
xmlStr (Input XML)
<urn1:RgBad
xmlns:urn1="urn:none">
</urn1:RgBad>
Correct XML
<urn:Rg
xmlns:urn="urn:test"
Code
(clazz = Rg.class)
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StreamSource source = new StreamSource(new StringReader(xmlStr));
//Returns an actual Rg object, even though the source root element and namespace are different.
(unmarshaller.unmarshal(source, clazz)).getValue();
You can try to add your schema to verify your xml file when using JAXB
try {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File( "yourSchema.xsd" ));
JAXBContext jc = JAXBContext.newInstance(clazz.getPackage().getName());
Unmarshaller u = jc.createUnmarshaller();
u.setSchema(schema);
u.setEventHandler(ehdler);
obj = u.unmarshal(xml);
} catch (JAXBException e) {
} finally {
}

UnmarshalException: unexpected element on XML just been Marshaller

I get an UnmarshalException (unexpected element) when unmarshallering XML, which i have just run through marshaller. I looks like the marshalling process generates XML, which cannot be unmarshalled.
ObjectFactory objectFactory = new ObjectFactory();
EjendomSoegType type = objectFactory.createEjendomSoegType();
EjendomSoegningKriterierType krit = new EjendomSoegningKriterierType();
{
krit.setBy("Skovlunde");
}
type.setEjendomSoegningKriterier(krit);
JAXBElement<EjendomSoegType> soeg = objectFactory.createEjendomSoeg(type);
// create JAXBContext which will be used to update writer
JAXBContext context = JAXBContext.newInstance(EjendomSoegType.class);
// marshall or convert jaxbElement containing element to xml format
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(soeg, writer);
String xml = writer.toString();
System.out.println( xml );
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xml);
soeg = (JAXBElement<EjendomSoegType>) unmarshaller.unmarshal(reader);
The following UnmarshalException is thrown by the last line of the code unmarshaller.unmarshal(reader):
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://rep.oio.dk/tinglysning.dk/service/message/elektroniskakt/1/", local:"EjendomSoeg"). Expected elements are (none)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:609)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:244)
The generated XML looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns8:EjendomSoeg xmlns:ns2="http://rep.oio.dk/tinglysning.dk/schema/model/1/"
xmlns:ns4="http://rep.oio.dk/cpr.dk/xml/schemas/core/2005/03/18/"
xmlns:ns3="http://rep.oio.dk/kms.dk/xml/schemas/2005/03/11/"
xmlns:ns5="http://rep.oio.dk/bbr.dk/xml/schemas/2005/03/11/"
xmlns:ns6="http://rep.oio.dk/bbr.dk/xml/schemas/2005/12/15/"
xmlns:ns7="http://rep.oio.dk/tinglysning.dk/schema/elektroniskakt/1/"
xmlns:ns8="http://rep.oio.dk/tinglysning.dk/service/message/elektroniskakt/1/">
<ns7:EjendomSoegningKriterier>
<By>Skovlunde</By>
</ns7:EjendomSoegningKriterier>
</ns8:EjendomSoeg>
Why is the UnmarshalException thrown?
ADDITIONAL INFORMATION ADDED LATER: The createEjendomSoeg method in ObjectFactory has the #XmlElementDecl tag.
/**
* Create an instance of {#link JAXBElement }{#code <}{#link EjendomSoegType }{#code >}}
*
*/
#XmlElementDecl(namespace = "http://rep.oio.dk/tinglysning.dk/service/message/elektroniskakt/1/", name = "EjendomSoeg")
public JAXBElement<EjendomSoegType> createEjendomSoeg(EjendomSoegType value) {
return new JAXBElement<EjendomSoegType>(_EjendomSoeg_QNAME, EjendomSoegType.class, null, value);
}
The #XmlElementDecl annotations on the ObjectFactory are not being picked up. To have ObjectFactory processesed you need to create the JAXBContext on this class, or on the package of your generated model.
JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
If there isn't an #XmlRootElement or #XmlElementDecl corresponding to the element you are trying to unmarshal then you will need to use an unmarshal method that takes a Class parameter.
soeg = unmarshaller.unmarshal(new StreamSource(reader), EjendomSoegType.class);

ClassCastException when unmarshalling JSON

I have the following xml entity:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class DocumentDossier {
private XdsJsonSubmissionSet submissionSet;
private XdsJsonDocument documentEntry;
private List<XdsJsonFolder> folder;
private List<XdsJsonAssociation> association;
...
And I'm trying to unmarshall a JSON file in the following way:
String content = IOUtils.toString(is);
JSONObject obj = new JSONObject(content);
Configuration config = new Configuration();
MappedNamespaceConvention con = new MappedNamespaceConvention(config);
XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con);
JAXBContext jc = JAXBContext.newInstance(DocumentDossier.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
DocumentDossier result = (DocumentDossier) unmarshaller.unmarshal(xmlStreamReader);
But the JSON I need to unmarshall doesn't have a root node, and that's the way it's supposed to be. Here's the JSON in question:
{
"submissionSet": {...},
"documentEntry": {...},
"association": {...}
}
Using this code, I get the following error:
java.lang.ClassCastException: XdsJsonSubmissionSet cannot be cast to DocumentDossier
What's wrong?
I think you need to add #XmlElement to each field.
Also don't forget to add #XmlRootElement to XdsJsonSubmissionSet, and #XmlElement to its fields.

Categories