Write pojo class for this xml file - java

I'm getting null value when unmarshelling the xml file to java class. But the xml file as values corresponding to the its attributes. Is there any mistake in my pojo class or unmarshelling?
Please help
This is my pojo
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "")
#XmlRootElement(name = "CardUpdateResponse",namespace="http://www.samople.com/Prepaid")
public class FVCardUpdateResponse {
#XmlElement(name = "AccountNumber")
private String AccountNumber;
#XmlElement(name = "ResCode")
private String ResCode;
#XmlElement(name = "ResErrorCode")
private String ResErrorCode;
#XmlElement(name = "ResErrorMsg")
private String ResErrorMsg;
//Setters and Getters
}
This is my xml file
<?xml version="1.0" encoding="UTF-8"?>
<CardUpdateResponse xmlns="http://www.samople.com/Prepaid">
<CARDUPDATE_RET>
<ResErrorMsg>ID Issue Date must be equal or less than present date</ResErrorMsg>
<ResErrorCode>ErrIsud01</ResErrorCode>
<ResCode>0</ResCode>
<ACCOUNTNUMBER>2000000003918246</ACCOUNTNUMBER>
</CARDUPDATE_RET>
</CardUpdateResponse>
this is code for unmarshelling
public class XmlUnmarshelling {
public void unmarshell()
{
try
{
System.out.println("xml unmarshelling class");
File file = new File("D:/var/lib/tomcat7/webapps/tmpFiles/1.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(FVCardUpdateResponse.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
FVCardUpdateResponse CARDUPDATE_ret = (FVCardUpdateResponse) jaxbUnmarshaller.unmarshal(file);
System.out.println("xml unmarshelled = "+CARDUPDATE_ret.getResErrorMsg());//Getting null value as response.
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

Your POJO doesn't have the same structure as your XML. CardUpdateResponse doesn't directly contain the properties in your POJO, it contains CARDUPDATE_RET element which contains the properties.
You could modify your POJO like this to match the XML:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "CardUpdateResponse", namespace="http://www.samople.com/Prepaid")
public static class CardUpdateResponseWrapper {
#XmlElement(name="CARDUPDATE_RET")
private FVCardUpdateResponse response;
// Getter and setter for response
public static class FVCardUpdateResponse {
#XmlElement(name = "AccountNumber")
private String AccountNumber;
#XmlElement(name = "ResCode")
private String ResCode;
#XmlElement(name = "ResErrorCode")
private String ResErrorCode;
#XmlElement(name = "ResErrorMsg")
private String ResErrorMsg;
// Getters and setters
}
}
Now the CardUpdateResponseWrapper class will represent your root XML element and it will have instance of FVCardUpdateResponse which will represent the CARDUPDATE_RET XML element.
Do unmarshall it, just call:
File file = new File("D:/var/lib/tomcat7/webapps/tmpFiles/1.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(CardUpdateResponseWrapper.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
CardUpdateResponseWrapper wrapper = (CardUpdateResponseWrapper) jaxbUnmarshaller.unmarshal(file);
System.out.println(wrapper.getResponse().getResErrorMsg());

I think that the issue is a combination of two problems, one what Bohuslav is saying, the other you need to repeat your namespace on every XmlElement annotation, e.g.
#XmlElement(name = "ResCode", namespace="http://www.samople.com/Prepaid")
and one particular issue, you need to match the cases as well so the name for AccountNumber should be capitalized ACCOUNTNUMBER

Related

JAXB Unmarsharller: XMLAttributes are mapped, but its XmlElements are not

TL;DR: When I unmarshall from XML to POJO I only have the XmlAttributes well mapped, however all XmlElement are null.
Hi there!
I have the following problem. This class was generated with JAXB
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"activity"
})
#XmlRootElement(name = "activityDetails", namespace = "http://lorem.ipsum.com/")
public class ActivityDetails {
#XmlElement(required = true)
protected Activity activity;
#XmlAttribute(name = "schemaVersion", required = true)
protected float schemaVersion;
#XmlAttribute(name = "actionType")
protected ActionTypes actionType;
#XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar timestamp;
This is an example XML
<activityDetails
actionType="CREATE"
schemaVersion="2.0"
timestamp="2020-01-02T15:31:50.549Z"
xmlns="http://lorem.ipsum.com/">
<activity>
<activityId>
<start>2020-01-01T03:00:00Z</start>
<end>2020-01-02T02:59:00Z</end>
</activityId>
</activity>
</activityDetails>
But, when this code is executed (please don't judge me, it's legacy code):
Object xmlClass = Class.forName("com.lorem.ipsum." + className).getConstructor().newInstance();
final JAXBContext jaxbContext = JAXBContext.newInstance(xmlClass.getClass());
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object object = unmarshaller.unmarshal(new StringReader(element));
The result "object" have all XmlAttribute well mapped, but no one of their XmlElement
PS: The namespace in the generated class was added manually, if I don't do that I have this exception:
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://lorem.ipsum.com/", local:"activityDetails"). Expected elements are <{}activityDetails>
Thanks in advance.
UPDATED: If I set all #XmlElement the namespace property I finally map the elements, but I must intervene all the classes. Is there another way to achieve that without having to modify all the fields of all the classes?
I guess I am able to figure out the issue. This is happening because you have not provided any prefix to your namespace in XML. Following code would work for your provided sample XML:
XML:
<activityDetails
actionType="CREATE"
schemaVersion="2.0"
timestamp="2020-01-02T15:31:50.549Z"
xmlns:ns0="http://lorem.ipsum.com/">
<activity>
<activityId>
<start>2020-01-01T03:00:00Z</start>
<end>2020-01-02T02:59:00Z</end>
</activityId>
</activity>
</activityDetails>
ActivityDetails.class:
#XmlAccessorType(XmlAccessType.FIELD)
#Data
#XmlRootElement(name = "activityDetails", namespace = "http://lorem.ipsum.com/")
public class ActivityDetails {
private Activity activity;
#XmlAttribute
private float schemaVersion;
#XmlAttribute
private String actionType;
#XmlAttribute
private String timestamp;
}
Activity.class:
#Data
#XmlAccessorType(XmlAccessType.FIELD)
public class Activity {
private ActivityID activityId;
}
ActivityID.class:
#Data
#XmlAccessorType(XmlAccessType.FIELD)
public class ActivityID {
private String start;
private String end;
}
Main.class:
public class Main {
public static void main(String[] args) throws JAXBException, XMLStreamException {
final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("activity.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
final Unmarshaller unmarshaller = JAXBContext.newInstance(ActivityDetails.class).createUnmarshaller();
final ActivityDetails activityDetails = unmarshaller.unmarshal(xmlStreamReader, ActivityDetails.class).getValue();
System.out.println(activityDetails.toString());
Marshaller marshaller = JAXBContext.newInstance(ActivityDetails.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(activityDetails, System.out);
}
}
Following is your output:
ActivityDetails(activity=Activity(activityId=ActivityID(start=2020-01-01T03:00:00Z, end=2020-01-02T02:59:00Z)), schemaVersion=2.0, actionType=CREATE, timestamp=2020-01-02T15:31:50.549Z)
<ns0:activityDetails xmlns:ns0="http://lorem.ipsum.com/" schemaVersion="2.0" actionType="CREATE" timestamp="2020-01-02T15:31:50.549Z">
<activity>
<activityId>
<start>2020-01-01T03:00:00Z</start>
<end>2020-01-02T02:59:00Z</end>
</activityId>
</activity>
</ns0:activityDetails>
Finally I found this solution: Instead of putting the namespace in each of the XMLElements I put the following package-info.java in the package of the generated classes.
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
namespace="http://lorem.ipsum.com/",
xmlns={#XmlNs(prefix="", namespaceURI="http://lorem.ipsum.com/")})
package com.lorem.ipsum.generated;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

JAXB Define XML elements with dots

I need to create a XML which matches this structure:
<OfferPackage Name="aaa">
<OfferPackage.Offers>
<OfferCollection Capacity="1">
<Offer Price="12.34"/>
<Offer Price="12.34"/>
</OfferCollection>
</OfferPackage.Offers>
</OfferPackage>
My problem is that I do not know how to achieve this here: <OfferPackage.Offers>. How I can get this "dot notation" with just annotations? All I got out looks like this:
<OfferPackage Name="aaa">
<OfferCollection Capacity="1">
<Offer Price="12.34"/>
<Offer Price="12.34"/>
</OfferCollection>
</OfferPackage>
This is my current code:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
#SneakyThrows
public String toString() {
var sw = new StringWriter();
var marshaller = JAXBContext
.newInstance(OfferPackage.class)
.createMarshaller();
marshaller.setProperty(JAXB_FRAGMENT, true);
marshaller.marshal(this, sw);
return sw.toString();
}
}
#XmlRootElement(name = "Offer")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferCollection {
#XmlAttribute(name = "Capacity")
private Integer capacity = null;
#XmlElement(name = "Offer")
private List<Offer> offer = null;
}
You can achieve the desired behavior using the #XmlElementWrapper annotation:
Generates a wrapper element around XML representation. This is primarily intended to be used to produce a wrapper XML element around collections.
In your case, it will look similar to this:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElementWrapper(name="OfferPackage.Offers")
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
#SneakyThrows
public String toString() {
var sw = new StringWriter();
var marshaller = JAXBContext
.newInstance(OfferPackage.class)
.createMarshaller();
marshaller.setProperty(JAXB_FRAGMENT, true);
marshaller.marshal(this, sw);
return sw.toString();
}
}
Other possibility will be to define an intermediate class, OfferPackageOffers to wrap the OfferCollection List::
#XmlRootElement(name = "OfferPackage.Offers")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackageOffers {
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
//...
}
And use the new class in OfferPackage instead of the mentioned OfferCollection List:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElement( name = "OfferPackage.Offers")
private OfferPackageOffers offers = null;
//...
}

How to implement parent object attributes (props & values) for children objects during JAXB XML unmarshalling

I have XML configuration that I must unmarshal with JAXB and then use this objects in java code. I have one parent object "tags" and two child tags "innerTag". All tags have attributes. Input configuration is:
...
<tags attribute1="value1" attribute2="value2">
<innerTag attribute3="value3"/>
<innerTag attribute4="value4"/>
</tags>
...
My task is implementation of attribute1 and attribute2 for innerTags after unmarshaling. It must be unmarshal like such xml:
...
<tags>
<innerTag attribute1="value1" attribute2="value2" attribute3="value3"/>
<innerTag attribute1="value1" attribute2="value2" attribute4="value4"/>
</tags>
...
I create the classes that will represent the objects after parsing XML:
#XmlRootElement
class Tags {
private ArrayList<InnerTag> innerTags = new ArrayList<>();
private String attribute1;
private String attribute2;
...
#XmlElement(name = "innerTag")
#XmlElementWrapper(name="tags")
public ArrayList<InnerTag> getInnerTags(){
return innerTags;
}
...
#XmlAttribute
public String getAttribute1(){
return attribute1;
}
#XmlAttribute
public String getAttribute2(){
return attribute2;
}
...
}
And the InnerTag class:
#XmlRootElement
class InnerTag {
private String attribute1;
private String attribute2;
private String attribute3;
private String attribute4;
...
#XmlAttribute
public String getAttribute1(){
return attribute1;
}
#XmlAttribute
public String getAttribute2(){
return attribute2;
}
...
#XmlAttribute
public String getAttribute3(){
return attribute3;
}
#XmlAttribute
public String getAttribute4(){
return attribute4;
}
}
I have no idea how to implement the attributes and values of parent attribute for children... I have not found such JAXB derective that let me do such implementation of attributes. Help, please to solve this problem!
try with this,
unmarshal the Tags object firstly
File file = new File("XMLFile.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Tags.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Tags tags = (Tags) jaxbUnmarshaller.unmarshal(file);
then, attribute's (attribute1 and attribute2) values of tags set to the InnerTag
for (int i = 0; i < tags.getInnerTags().size(); i++) {
tags.getInnerTags().get(i).setAttribute1(tags.getAttribute1());
tags.getInnerTags().get(i).setAttribute2(tags.getAttribute2());
}

JAXB - how to unmarshal an entity into list of entities with size 1

I have the following JAXB entity:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNER)
public class FilePartner
{
#XmlAttribute(name = EntityConstants.IDENTIFIER, required = true)
private String identifier;
#XmlElement(name = EntityConstants.NAME)
private String name;
#XmlElement(name = EntityConstants.ROOT_PATH)
private String rootPath;
...
}
which serialized into a similar structure:
<file-partner identifier="foo">
<name>bar</name>
<root-path>path123</root-path>
...
</file-partner>
I also have an entity which represents a list of partners:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNERS)
public class FilePartnerList
{
#XmlElement(name = EntityConstants.PARTNER)
private List<FilePartner> partners = new ArrayList<FilePartner>();
public List<FilePartner> getPartners()
{
return partners;
}
public void addPartners(List<FilePartner> partners)
{
this.partners.addAll(partners);
}
}
which serializes into:
<partners>
<file-partner identifier="foo">
...
</file-partner>
<file-partner identifier="foo2">
...
</file-partner>
...
</partners>
I am looking for a way to force the jaxb unmarshaller to deserialize XMLs in the form of
<file-partner identifier="foo">
<name>bar</name>
<root-path>path123</root-path>
...
</file-partner>
into FilePartnerList instances with list size of 1, i.e:
JAXBContext context = JAXBContext.newInstance(FilePartner.class, FilePartnerList.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
InputStream inputStream = getResourceAsStream(filePartnerAsXml);
FilePartnerList partnerList = (FilePartnerList) unmarshaller.unmarshal(inputStream); // This SHOULD be unmarshalled to FilePartnerList instead of FilePartner
assertTrue(partnerList.getPartners().getSize().equals(1));
How do I achieve that?
private List<FilePartner> partners = new ArrayList<FilePartner>(**1**);
That way you'll get a fixed size input array....
But I'm sure that you will want to get the XSD of that model with the 'maxocurrs=1' so you will end modifying the XSD manually.
Anyway: why don't you, if the list size must be fixed to '1', simply set it as a simple node with a single child? Something like this (untested):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNERS)
public class FilePartnerList
{
#XmlElement(name = EntityConstants.PARTNER)
private FilePartner partners;
public FilePartner getFilePartner()
{
return partner;
}
public void setPartner(FilePartner partner)
{
this.partner = partner;
}
}
This way you will have one and only one partner per parnets-list.
The XML that fullfits the XSD of your service a text and in that text is indistinguible a list with max size 1 and a node.

JAXB troubles when trying to unmarshall a BES-XADES signature document

i need your help : please, please please.
I've a Xades-signed XML document that i receive as a byteArray : so i convert my byteArray to a String.
After, i try to unmarhall so that i obtain a Java Object mapped.
The result is that i get an instance of "MyJavaObj" with all informations but Xades-Signature. My signature is null in the Java Object while all other informations are well-mapped. The following is my java method. Please, help me to get the object signature in the instance of MyJavaObj.
<school>
<documentVersion>2.10</documentVersion>
<teacher>
.....
</teacher>
<student>
<name></name>
<age></age>
....
</student>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-2b72d2f4-4794-4a8b-8cbf-4c74d33629a7">
<ds:SignedInfo>
........
</ds:SignedInfo>
.......
</ds:Signature>
</school>
this is the method to convert
public static MyJavaObj unmarshallBinary(final byte[] pByteStr) {
try {
final String xmlFlow = new String(pByteStr, "UTF-8");
final StringBuffer xmlStr = new StringBuffer(xmlFlow);
// Unmarshalling with JAXB
final JAXBContext jaxbContext = JAXBContext.newInstance("generated.package");
// marshaller
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// Unmarshalling
final JAXBElement<MyJavaObj> root = unmarshaller.unmarshal(
new StreamSource(new StringReader(xmlStr.toString())), MyJavaObj.class);
return root.getValue();
} catch (final Throwable excep) {
excep.printStacktrace();
}
}
MyJavaObj result = unmarshallBinary(..a ByteArray..);
result.getDocumentVersion() : returns 2.10;
result.getStudent() : returns the students;
result.getSignature() : return NULL;
The file MyJavaObj.java is well annotated
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "My_Java_Obj", namespace = "urn:my_java_obj",
propOrder = {"documentVersion", "teacher", "student","signature"})
public class MyJavaObj {
#XmlElement(name = "documentVersion", required = true)
protected String documentVersion;
#XmlElement(name = "teacher", required = true)
protected Teacher teacher;
#XmlElement(name = "student", required = true)
protected Student student;
#XmlElement(name = "Signature")
protected Signature signature;
#XmlAttribute(name = "Id", required = true)
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String id;
.....
getters and setters
}
Thanks for any help.
The Signature element is in the http://www.w3.org/2000/09/xmldsig#" namespace so you need to include this in the #XmlElement for the signature field.
#XmlElement(name="Signature", namespace="http://www.w3.org/2000/09/xmldsig#")
protected Signature signature;
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
my solution is bit different
i used uddi-ws. Maven dependency is here:
<!-- https://mvnrepository.com/artifact/org.apache.juddi/uddi-ws -->
<dependency>
<groupId>org.apache.juddi</groupId>
<artifactId>uddi-ws</artifactId>
<version>3.3.2</version>
</dependency>
In class:
//in my case, import org.w3.x2000.x09.xmldsig.SignatureType isn't working
import org.w3._2000._09.xmldsig_.SignatureType;
//Signature declaration
private SignatureType Signature;
//namespace is important part, without namespace, it returns null
#XmlElement(name = "Signature", namespace = "http://www.w3.org/2000/09/xmldsig#")
public SignatureType getSignature() {
return Signature;
}
More info:
https://www.codesynthesis.com/pipermail/xsd-users/2006-December/000674.html

Categories

Resources