Its easier to explain with an example,
Sample XML:
<root>
<company>
<name>xyz</name>
<employees>
<employeeref>emp1</employeeref>
<employeeref>emp2</employeeref>
</employees>
</company>
<employee id="emp1">
<name>a</name>
<age>12</age> </employee>
<employee id="emp2">
<name>b</name>
<age>24</age> </employee>
<employee id="emp3">
<name>c</name>
<age>36</age>
</employee>
</root>
This would need Company.java and Employee.java.
My question is,
How do i bind the xml to java objects using Jaxb annotations?
You can use #XmlID in combination with #XmlIDREF
Employee
On the Employee class you need to annotate which field/property is going to be the "key" for the object. In JAXB this is done with the #XmlID annotation.
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
#XmlAttribute
#XmlID
private String id;
}
Company
In the Company class we will indicate that we want to marshal instances of Employee as a reference to the real object. This is done using the #XmlIDREF annotation.
#XmlAccesorType(XmlAccessType.FIELD)
public class Company {
#XmlElementWrapper
#XmlElement(name="elementref")
#XmlIDREF
private List<Employee> employees;
}
Root
In order for #XmlIDREF to work the object must mapped somewhere else with an #XmlElement annotation. In this example this happes in the Root class.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private Company company;
#XmlElement(name="employee")
private List<Employee> employees;
}
For More Information
You can read more about #XmlID and #XmlIDREF on my blog:
http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html
I think you need following class, here is sample, you can do it with other ways
Root One class for Root
| -- Company Company class
| |
| | employess(List) one more class for employess collection
|
|
employee (collection) one class for employee
EmployeeData
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "root")
public class EmployeeData {
#XmlElement
private Company company;
private List<Employee> employee;
// getter/setter
}
Company
#XmlAccessorType(XmlAccessType.FIELD)
public class Company {
#XmlElement(required = true)
private String name;
#XmlElement(required = true)
private Employees employees;
//...// getter/setter
}
Employee
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
#XmlElement
private String name;
private int age;
#XmlAttribute(name = "id")
private String id;
///// getter/setter
}
Employees
#XmlAccessorType(XmlAccessType.FIELD)
public class Employees {
private List<String> employeeref;
// getter/setter
}
Java classes can be structured in such a way that they form a tree hierarchy as described in the XML file. Annotations are used in the Java classes to describe this structure.
Here is a list of some annotations used:
#XmlRootElement : Maps a class or an enum type to an XML element.
#XmlAttribute : Maps a JavaBean property to a XML attribute.
#XmlElement : Maps a JavaBean property to a XML element derived from property name
The Employee class can be like that:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Employee {
private String id;
private String name;
private String age;
public String getId() {
return id;
}
#XmlAttribute
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
#XmlElement
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
#XmlElement
public void setAge(String age) {
this.age = age;
}
}
Related
I would like to ask on how to marshal an object with property order from a nested object.
#XmlRootElement(name = "sample")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {"title", "code"})
public class SampleObject {
#XmlAttribute(name = "title")
private String title;
#XmlAttribute(name = "code")
private String code;
}
I have a wrapperList to set that object:
#XmlRootElement(name = "listWrapper")
#XmlAccessorType(XmlAccessType.FIELD)
public class WrapperObject {
#XmlAnyElement(lax=true)
private List<SampleObject> objectList;
}
And i want to set the list on this object. This object is the one who is being marshalled.
#XmlRootElement(name = "marshaller")
#XmlAccessorType(XmlAccessType.FIELD)
public class MarshallerObject {
#XmlElement(name = "wrapperList")
private WrapperObject objectList;
}
This is the output that i'm aiming for:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<marshaller>
<wrapperList>
<sample title="sampleTitle code"001"/>
</wrapperList>
</marshaller>
</soap:Envelope>
Thanks in advance!
I know this question was asked before, but still no response to that.
Indeed, I have this Java Entity:
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
private String firstName;
private String lastName;
}
and my goal is to transform/map the class below into this xml format:
<customer>
<id>...</id>
<email>....</email>
<names>
<firstName>...</firstName>
<lastName>...</lastName>
<names>
</customer>
The problem is that I can't use #XmlElementWrapper because it is not applicable on non collection property, and I'm searching for a solution that doesn't require to create a class "names" which will contains firstname and lastname.
I cannot get #XmlType with propOrder working with Lombok:
#Getter
#Setter
#NoArgsConstructor
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {
"street",
"postalCode",
"city",
"country"})
public class Alternative extends BaseAddress {
#XmlElement
private String street;
#XmlElement
private String city;
}
#Getter
#Setter
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {
"postalCode",
"country"})
public abstract class BaseAddress implements Serializable {
#XmlElement
private String postalCode;
#XmlElement
private String country;
I get errors on fields postalCode and country if I use lombok:
Field 'postalCode' does not exist
Field 'country' does not exist
Do you guys know why and if lombok supports the JAXB structure?
This has nothing to do with Lombok because even with getters & setters (w/o lombok annotations) you would run into the same issue. You cannot specify parent class properties in the child class' propOrder because with inheritance, properties from parent class are always set first. So there are two approaches. You either follow the order of parent props and then child props:
#XmlType(propOrder = {"street", "city"})
public class Alternative extends BaseAddress {
..
#XmlType(propOrder = {"postalCode", "country"})
public abstract class BaseAddress {
Or you annotate base class with #XmlTransient
#XmlType(propOrder = {"postalCode", "country", "street", "city"})
public class Alternative extends BaseAddress {
..
#XmlTransient
public abstract class BaseAddress {
Taken from #XmlTransient doc:
When placed on a class, it indicates that the class shouldn't be mapped
to XML by itself. Properties on such class will be mapped to XML along
with its derived classes, as if the class is inlined.
This works:
#Getter
#Setter
#NoArgsConstructor
#XmlAccessorType(XmlAccessType.NONE)
#XmlType(propOrder = {
"street",
"postalCode",
"city",
"country"})
public class Alternative extends BaseAddress {
#XmlElement
private String street;
#XmlElement
private String city;
}
#Getter
#Setter
#XmlAccessorType(XmlAccessType.NONE)
#XmlTransient
public abstract class BaseAddress implements Serializable {
#XmlElement
private String postalCode;
#XmlElement
private String country;
Adding #XmlTransient and #XmlAccessorType(XmlAccessType.NONE) to both classes did the job.
#XmlAccessorType(XmlAccessType.NONE) means none of the fields is mapped to XML unless they have some JAXB annotations.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<batch-execution>
<insert out-identifier="employee" return-object="true" entry-point="DEFAULT">
<fact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="employee">
<name>Rajashekhar</name>
<age>21</age>
</fact>
</insert>
<fire-all-rules></fire-all-rules>
</batch-execution>
Now I am getting this output as above but I want out put like below
<batch-execution>
<insert out-identifier="employee" return-object="true"
entry-point="DEFAULT">
<com.practise.Employee>
<name>Rajashekhar</name>
<age>21</age>
</com.practise.Employee>
</insert>
<fire-all-rules />
</batch-execution>
My Jaxb classes are
Request.java
#XmlRootElement(name = "batch-execution")
#XmlAccessorType(XmlAccessType.FIELD)
public class Request implements Serializable {
#XmlElement(name = "insert")
private List<Insert> insert;
#XmlElement(name = "fire-all-rules",nillable=true)
private String fireAllRules = "";
.
..
setters and getter
Insert.java
#XmlAccessorType(XmlAccessType.FIELD)
public class Insert {
#XmlAttribute(name = "out-identifier", required = true)
private String outIdentifier;
#XmlAttribute(name = "return-object")
private boolean returnObject;
#XmlAttribute(name = "entry-point")
private String entryPoint;
private Object fact;
.
.
setters and gettes
com.practise.Employee.java
#XmlRootElement(name="kewill.com.kewill.practoise.Employee")
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee implements java.io.Serializable
{
static final long serialVersionUID = 1L;
#org.kie.api.definition.type.Label("Name")
private java.lang.String name;
#org.kie.api.definition.type.Label("Id")
private java.lang.Integer id;
#org.kie.api.definition.type.Label("Age")
private int age;
#org.kie.api.definition.type.Label(value = "valid")
private java.lang.Boolean valid;
.
. setters and getters
I think it is possible through xtream api but I want to use JAXB please provide me the solution in jaxb.
In Insert.java
added Annotation for
private Object fact;
as
#XmlAnyElement(lax = true)
private Object fact;
Now it is giving expected output.
I want to create xml from my object, but instead of xml nodes I'd like to create attribute i.e.
#XmlRootElement
class MyObject{
private String name;
private String age;
...getters/setters...
}
And I want my object to create this xml :
<MyObject name="something">
<age></age>
</MyObject>
How can I do this?
You can use the #XmlAttribute annotation to map to an XML attribute.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
class MyObject{
#XmlAttribute // Maps to an XML attribute
private String name;
private String age; // Maps to an XML element
...getters/setters...
}