In developing SOA
applications, it is necessary that you have tools in converting Java
objects to XML and vice-versa. In Oracle Human Task Services for
example, the task payloads are represented as XML elements, and if
there's a need to manipulate those payload then, I believe that its
better to do the manipulation on a Java instance equivalent, rather
than navigating to the complex tree structure of the XML payload.
With the Java instance, you could take advantage of Java's vast
frameworks and utilities.
--------------------------------------------------------------------------------
In this post, I
will demonstrate how to convert POJO's to XML and vice-versa using
Java Architecture for XML Binding (JAXB), and will give some tips in
annotating our entities to avoid some common gotchas.
To be able to
convert your POJO to XML, it is mandatory that you put an
"@XmlRootElement" annotation to your target classes.
To be able to
convert your POJO to XML, it is mandatory that you put an
"@XmlRootElement" annotation to your target classes.
package soadev.jaxbsample.model; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "job") @XmlAccessorType(XmlAccessType.FIELD) public class Job{ private String jobId; private String jobTitle; private Long maxSalary; private Long minSalary; //getters and setters
The root name "job" above will be the root of the generated XML as follows:
<job> <jobid></jobid> <jobtitle></jobtitle> <maxsalary></maxsalary> <minsalary></minsalary> </job>
The "@XmlAccessorType(XmlAccessType.FIELD)" annotation tells JAXB that only the fields will be marshalled to XML. There are other types which you can read from the links near the end of this post. I am more inclined to use this annotation particularly because our entities persistence annotations are also on the fields, and that we have a lot of transient methods like "computeTotal" which value I don't need to be marshalled.
I will also recommend that you removed any unnecessary associations (some auto-generated by JDeveloper when creating entities from database tables)like for example departmentList in the Employee class (mapped by the manager in Departments). Those associations will add too much complexity especially if you are already starting to expose your EJB session beans as Web Services or as EJB Service. When you cannot remove it due to some usage requirement then put "@XmlTransient" annotation if those associations are not necessary to be marshalled to XML.
If you have fields of type "java.sql.Timestamp", create a TimeStampAdapter class as follows:
package soadev.jaxb.adapters; import java.sql.Timestamp; import java.util.Date; import javax.xml.bind.annotation.adapters.XmlAdapter; public class TimestampAdapter extends XmlAdapter{ public Date marshal(Timestamp value) { if(value == null){ return null; } return new Date(value.getTime()); } public Timestamp unmarshal(Date value) { if (value == null){ return null; } return new Timestamp(value.getTime()); } }
...and annotate
your approriate fields as follows:
@XmlJavaTypeAdapter(value = TimestampAdapter.class)
private
Timestamp hireDate;
This annotation
can also be put inside a "package-info.java". Please see
the links for details.
The runner class
The class below
shows how to convert POJO to XML. It also contains a sample on how to
convert to POJO an XML element with a different root name.
package soadev.jaxbsample.clients; import java.io.ByteArrayInputStream; import java.io.InputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import oracle.bpel.services.common.util.XMLUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; import soadev.jaxbsample.model.Department; import soadev.jaxbsample.model.Employee; import soadev.jaxbsample.model.Job; public class SimpleJaxbClient { public static void main(String[] args) { SimpleJaxbClient client = new SimpleJaxbClient(); try { client.testMarshallUnmarshallSimplePojoWithSameRootQName(); client.testMarshallUnmarshallComplexPojoWithSameRootQName(); client.testUnmarshallComplexXmlWithDifferentRootQName(); } catch (Exception e) { e.printStackTrace(); } } public void testMarshallUnmarshallSimplePojoWithSameRootQName() throws Exception { System.out.println("----Start testMarshallUnmarshallSimplePojoWithSameRootQName----"); JAXBContext context = JAXBContext.newInstance(Job.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); System.out.println("Instantiating simple pojo..."); Job job = new Job(); job.setJobId("SOADEV"); job.setJobTitle("SOA Developer"); job.setMaxSalary(10000L); job.setMinSalary(8000L); System.out.println("Simple pojo created: " + job); System.out.println("Marshalling pojo to a DOM Node..."); DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = docBuilder.newDocument(); marshaller.marshal(job, document); Element jobElement = document.getDocumentElement(); System.out.println("Job element created: " + jobElement); System.out.println(XMLUtil.toString(jobElement)); System.out.println("Unmarshalling an xml element to a POJO"); Unmarshaller unmarshaller = context.createUnmarshaller(); Job jobPojoFromXml = (Job)unmarshaller.unmarshal(jobElement); System.out.println("Simple pojo from xml created :" + jobPojoFromXml); System.out.println(jobPojoFromXml); System.out.println(jobPojoFromXml.getJobTitle()); System.out.println(jobPojoFromXml.getJobId()); System.out.println("----End testMarshallUnmarshallSimplePojoWithSameRootQName----"); } public void testMarshallUnmarshallComplexPojoWithSameRootQName()throws Exception{ System.out.println("----Start testMarshallUnmarshallComplexPojoWithSameRootQName----"); JAXBContext context = JAXBContext.newInstance(Employee.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); System.out.println("Instantiating complex pojo..."); Employee employee = new Employee(); employee.setEmployeeId(1L); employee.setFirstName("Rommel"); employee.setLastName("Pino"); Job job = new Job(); job.setJobId("SOADEV"); job.setJobTitle("SOA Developer"); job.setMaxSalary(10000L); job.setMinSalary(5000L); employee.setJob(job); Department department = new Department(); department.setDepartmentName("Java Team"); employee.setDepartment(department); System.out.println("Complex pojo created: " + employee); System.out.println("Marshalling complex pojo to a DOM Node..."); DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = docBuilder.newDocument(); marshaller.marshal(employee, document); Element employeeElement = document.getDocumentElement(); System.out.println("Employee element created: "+ employeeElement); System.out.println(XMLUtil.toString(employeeElement)); System.out.println("Unmarshalling an xml element to a POJO"); Unmarshaller unmarshaller = context.createUnmarshaller(); Employee employeePojoFromXml = (Employee)unmarshaller.unmarshal(employeeElement); System.out.println("Complex pojo from xml created :" + employeePojoFromXml); System.out.println(employeePojoFromXml); System.out.println(employeePojoFromXml.getEmployeeId()); System.out.println(employeePojoFromXml.getFirstName()); System.out.println(employeePojoFromXml.getLastName()); System.out.println(employeePojoFromXml.getJob()); System.out.println(employeePojoFromXml.getJob().getJobTitle()); System.out.println(employeePojoFromXml.getDepartment()); System.out.println(employeePojoFromXml.getDepartment().getDepartmentName()); System.out.println("----End testMarshallUnmarshallComplexPojoWithSameRootQName----"); } public void testUnmarshallComplexXmlWithDifferentRootQName()throws Exception{ System.out.println("----Start testUnmarshallComplexXmlWithDifferentRootQName----"); //root is 'employeeVariable' instead of 'employee' String xmlString = "<employeeVariable>" + " <employeeId>1</employeeId>" + " <firstName>Rommel</firstName>" + " <lastName>Pino</lastName>" + " <job>" + " <jobId>SOADEV</jobId>" + " <jobTitle>SOA Developer</jobTitle>" + " <maxSalary>10000</maxSalary>" + " <minSalary>5000</minSalary>" + " </job>" + " <department>" + " <departmentName>Java Team</departmentName>" + " </department>" + "</employeeVariable>"; InputStream is = new ByteArrayInputStream(xmlString.getBytes()); DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = docBuilder.parse(is); Element varElement = document.getDocumentElement(); JAXBContext context = JAXBContext.newInstance(Employee.class); Unmarshaller unmarshaller = context.createUnmarshaller(); JAXBElement<Employee> employeeJaxbElement = unmarshaller.unmarshal(varElement, Employee.class); System.out.println("Element variable is :" + employeeJaxbElement.getName()); Employee employeePojoFromXml = employeeJaxbElement.getValue(); System.out.println("Complex pojo from xml created :" + employeePojoFromXml); System.out.println(employeePojoFromXml); System.out.println(employeePojoFromXml.getEmployeeId()); System.out.println(employeePojoFromXml.getFirstName()); System.out.println(employeePojoFromXml.getLastName()); System.out.println(employeePojoFromXml.getJob()); System.out.println(employeePojoFromXml.getJob().getJobTitle()); System.out.println(employeePojoFromXml.getDepartment()); System.out.println(employeePojoFromXml.getDepartment().getDepartmentName()); System.out.println("----End testUnmarshallComplexXmlWithDifferentRootQName----"); } }
Run Outpout
C:\Oracle\11g\jdk160_24\bin\javaw.exe
-client -classpath ...
----Start
testMarshallUnmarshallSimplePojoWithSameRootQName----
Instantiating
simple pojo...
Simple pojo
created: soadev.jaxbsample.model.Job@a6d51e
Marshalling pojo
to a DOM Node...
Job element
created: oracle.xml.parser.v2.XMLElement@9f5011
<job>
<jobId>SOADEV</jobId>
<jobTitle>SOA
Developer</jobTitle>
<maxSalary>10000</maxSalary>
<minSalary>8000</minSalary>
</job>
Unmarshalling an
xml element to a POJO
Simple pojo from
xml created :soadev.jaxbsample.model.Job@c62c8
soadev.jaxbsample.model.Job@c62c8
SOA Developer
SOADEV
----End
testMarshallUnmarshallSimplePojoWithSameRootQName----
----Start
testMarshallUnmarshallComplexPojoWithSameRootQName----
Instantiating
complex pojo...
Complex pojo
created: soadev.jaxbsample.model.Employee@76fba0
Marshalling
complex pojo to a DOM Node...
Employee element
created: oracle.xml.parser.v2.XMLElement@949f69
<employee>
<department>
<departmentName>Java Team</departmentName>
</department>
<employeeId>1</employeeId>
<firstName>Rommel</firstName>
<lastName>Pino</lastName>
<job>
<jobId>SOADEV</jobId>
<jobTitle>SOA Developer</jobTitle>
<maxSalary>10000</maxSalary>
<minSalary>5000</minSalary>
</job>
</employee>
Unmarshalling an
xml element to a POJO
Complex pojo from
xml created :soadev.jaxbsample.model.Employee@82764b
soadev.jaxbsample.model.Employee@82764b
1
Rommel
Pino
soadev.jaxbsample.model.Job@12452e8
SOA Developer
soadev.jaxbsample.model.Department@1bf3d87
Java Team
----End
testMarshallUnmarshallComplexPojoWithSameRootQName----
----Start
testUnmarshallComplexXmlWithDifferentRootQName----
Element variable
is :employeeVariable
Complex pojo from
xml created :soadev.jaxbsample.model.Employee@42552c
soadev.jaxbsample.model.Employee@42552c
1
Rommel
Pino
soadev.jaxbsample.model.Job@e5bbd6
SOA Developer
soadev.jaxbsample.model.Department@8ee016
Java Team
----End
testUnmarshallComplexXmlWithDifferentRootQName----
Process exited
with exit code 0.