jaxb annotations for verbose OTA XML - jaxb

For my sins, I'm working with Airline OTA XML. It has verbose elements such as:
<FlightInfo>
<Success />
<DepartureAirport LocationCode="LHR" />
<ArrivalAirport LocationCode="LAX" />
</FlightInfo>
where the presence of a Success element means the response is successful, and airport codes are embedded as Attributes in holding Elements.
To preserve my sanity as I write java code, I want to convert this into a simple POJO like this:
public class FlightInfo {
private boolean success;
private String departureAirport;
private String arrivalAirport;
}
Using JAXB, what is the recommended approach for this - use XmlJavaTypeAdapter for all these elements?

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You could use the #XmlPath extension in MOXy for the departureAirport and arrivalAirport fields:
#XmlPath("DepartureAirport/#LocationCode")
private String departureAirport;
#XmlPath("ArrivalAirport/#LocationCode")
private String arrivalAirport;
And you could use an XmlAdapter to represent the boolean field success with the presence or absence of the Success element:
#XmlJavaTypeAdapter(SuccessAdapter.class)
private boolean success;
FlightInfo
Below is what your FlightInfo class would look like with MOXy and JAXB annotations:
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
#XmlRootElement(name="FlightInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class FlightInfo {
#XmlJavaTypeAdapter(SuccessAdapter.class)
private boolean success;
#XmlPath("DepartureAirport/#LocationCode")
private String departureAirport;
#XmlPath("ArrivalAirport/#LocationCode")
private String arrivalAirport;
}
For More Information
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2010/12/represent-string-values-as-element.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

Related

Handling of XML elements with different name but similar structure using JAXB

I have a XML file with elements having different names but similar structure(same attributes and child elements). I want to convert XML file to Java objects. I have used #XmlAnyElement annotation and it gives the element but it is not convertible to the Java object class. Through eclipse debugging I have verified that it is in the form ElementNSImpl which cannot be cast to the Object class.
Sample XML structure is following,
<element1 attr1="" attr2="" attr3="">
<childElement1>
<childElement2>
</element1>
<element2 attr1="" attr2="" attr3="">
<childElement1>
<childElement2>
</element2>
I am using JAXB annotations.
Root
In JAXB Java classes correspond to complex types in XML Schema. If element1 and element2 have the same type then they refer to the same class.
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private Element element1;
private Element element2;
}
Element
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlAttribute
private String attr1;
#XmlAttribute
private String attr2;
#XmlAttribute
private String attr3;
private String childElement1;
private String childElement2;
}

XML element with two attributes and simple element using JAXB

I would like to un marshall using JAXB. I am facing issue while unmarshalling for the following use case.
Please suggest how to generate below xml using JAXB.
<Source type="system" gender="male">
<Description>He is a man</Description>
</Source>
You can do the following. The #XmlAttribute annotation is used to mark something an XML attribute. By default everything is treated as an element, if you need the name different from the default then you can use the #XmlElement annotation to specify this.
#XmlRootElement(name="Source")
#XmlAccessorType(XmlAccessType.FIELD)
public class Source {
#XmlAttribute
private String type;
#XmlAttribute
private String gender;
#XmlElement(name="Description")
private String description;
}

IllegalAnnotationExceptions while converting object to XML using Jaxb

I have a TrainingCalendarWrapper class which have a list which hold TrainingCalendarVO. In my application
I'm setting the details in TrainingCalendarVO and then added to trainingList of TrainingCalendarWrapper
And then converting TrainingCalendarWrapper to XML using Jaxb.
#XmlRootElement
public class TrainingCalendarWrapper implements Serializable
{
public ArrayList<TrainingCalendarVO> trainingList;
Getters & Setters for trainingList
}
1 counts of illegalAnnotationException Class has two properties of the same name "trainingList" for the below line of code
JAXBContext jaxbContext = JAXBContext.newInstance(TrainingCalendarWrapper.class);
If you are annotating the fields (instance variables) then you need to specify #XmlAccessorType(XmlAccessType.FIELD) at the class level. Otherwise you can add the annotation to the get or set methods.
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html

How to ignore JAXB annotated properties in a parent class?

We have a class with a JAXB annotation on one property. We then have several subclasses which annotate the rest of the important data. We have one subclass, however, where we want to ignore the parent class annotation so that it does not get marshalled. Here's some example code.
Parent class:
#XmlType(name="Request")
#XmlAccessorType(XmlAccessorType.NONE)
public abstract class Request {
#XmlElement(required=true)
private UUID uuid;
... setter/getter
}
Now for the subclass:
#Xsd(name="concreteRequest")
#XmlRootElement("ConcreteRequest")
#XmlType(name="ConcreteRequest")
#XmlAccessorType(XmlAccessorType.FIELD)
public class ConcreteClass {
#XmlElement(required=true)
private String data1;
#XmlElement(required=true)
private String data1;
... setters/getters ...
}
When I masrhall an instance of ConcreteClass I get the following XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ConcreteRequest>
<uuid>uuid</uuid>
<data1>data</data1>
<data2>data</data3>
</ConcreteRequest>
Where I want XML like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ConcreteRequest>
<data1>data</data1>
<data2>data</data3>
</ConcreteRequest>
We have other implementations of Request, however that do require the UUID, this is just a special case. Is there a way to ignore the UUID field in my ConcreteRequest?
I hope, I understood your problem. Here is the solution.
JAXB provides #XmlTransient(javax.xml.bind.annotation.XmlTransient)(javadoc) to ignore any field during marshalling.
Override the field "uuid" as #XmlTransient in your derived class (ConcreteRequest.class) along with its correspoding Getter/Setter method. It is necessary to override the Getter/Setter methods also, these will be invoked during marshalling.
#Xsd(name="concreteRequest")
#XmlRootElement("ConcreteRequest")
#XmlType(name="ConcreteRequest")
#XmlAccessorType(XmlAccessorType.FIELD)
public class ConcreteClass {
#XmlElement(required=true)
private String data1;
#XmlElement(required=true)
private String data2;
#XmlTransient
private UUID uuid;
... setters/getters ...
}
This will override your Base Class attribute.
Get back to me for more information.
You can use
#XmlAccessorType(XmlAccessType.NONE)
on parent class, and
#XmlAccessorType(XmlAccessType.FIELD)
on derived class.

How do I use JAXB #XmlValue on a subclass?

I want XML like this:
<simple>Foo</simple>
I can do this successfully via a JAXB class that looks like this:
#XmlRootElement(name="simple")
class Simple {
#XmlValue
public String contents;
}
But now I need to make the Simple class be a subclass of another class like so:
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlValue
public String contents;
}
That fails with #XmlValue is not allowed on a class that derives another class. I can't easily refactor the superclass away (because of the way we're using #XmlElementRef on a wrapper class). Is there a workaround that will let me annotate my subclass to generate that simple XML?
The accepted answer didn't work for me.
Everything is fine as described but I also needed to add the #XmlTransient to the superclass
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
This use case is supported by MOXy, and IMHO should be supported by the JAXB RI as well:
Simple
This class has a field mapped with #XmlValue and extends OtherClass:
package forum809827;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlValue
// #XmlValueExtension
// As of moxy 2.6, XmlValueExtension needs to be added for this to work
public String contents;
}
OtherClass
This is the super class. In MOXy the subclass can map a field/property with #XmlValue as long as the super class does not have any mappings to an XML element:
package forum809827;
import javax.xml.bind.annotation.XmlAttribute;
public class OtherClass {
#XmlAttribute
public String other;
}
Demo
package forum809827;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Simple.class);
Simple simple = new Simple();
simple.contents = "FOO";
simple.other = "BAR";
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(simple, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<simple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" other="BAR">FOO</simple>
For More Information on Specifying MOXy as Your JAXB Provider
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
I was able to make this work by changing #XmlValue to #XmlMixed and changing the variable to a list. The resulting class should look like the following.
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlMixed
public List<String> contents;
}
This problem happened to me , and took me a little bit time.
Thanks to Blaise Doughan
I go through his blog and find the answer
you have to add a
jaxb.properties file with javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
in the same package in order to use MOXy
add moxy to your maven dependency or add moxy jar
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.5.0</version>
</dependency>
then all set
I have sample here you can go though my project and take a look at
https://github.com/cicidi/HelloCCD/tree/master/Jaxb

Resources