Castor data binding framework mapping XMLGregorianCalendar
The goal of this article is to show how to carry out complex castor mapping and to share a knowledge that I've just gained on how to map javax.xml.datatype.XMLGregorianCalendar within castor.
Castor supports lots of system types except javax.xml.datatype.XMLGregorianCalendar.
So, how can I tackle this issue?
I've started thinking on how I can provide a mecchanism to make this javax.xml.datatype.XMLGregorianCalendar date field work in castor context mapping?
The answer was YES
In effect, this is not what I consider a proper article, but a sort of hand to those who might go through this kind of issue.
Well, to give a hand to those who might face this issue, I have built a simple eclipse project to make this solution easier to comprehend.
Components that make up this small but working solution
@XmlType
org.sample.castor.Customer
org.sample.castor.Order
org.sample.castor.OrderResponse
org.sample.castor.Orders
#Manipolatore (Handler) del campo data javax.xml.datatype.XMLGregorianCalendar
org.sample.castor.handler.OrderDateHandler
org.sample.castor.util.DateUtil
#Main class nel package di default
default/OrderManager
# Mapping file
mapping.xml
#Main class
import java.io.InputStream;
import java.io.StringReader;
import java.util.List;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.exolab.castor.xml.XMLContext;
import org.sample.castor.Order;
import org.sample.castor.OrderResponse;
import org.sample.castor.Orders;
import org.xml.sax.InputSource;
public class OrderManager {
private static StringBuffer message;
static{
message = new StringBuffer();
message.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
message.append("<ns2:orderResponse xmlns:ns2=\"http://org.sample.castor\">\n");
message.append(" <customer>\n");
message.append(" <id>101</id>\n");
message.append(" <name>Paolo</name>\n");
message.append(" <surname>Rossi</surname>\n");
message.append(" <address>Via della Giustiniana, 71</address>\n");
message.append(" <email>p.rossi@gmail.com</email>\n");
message.append(" </customer>\n");
message.append(" <orders>\n");
message.append(" <order>\n");
message.append(" <id>701</id>\n");
message.append(" <description>Order 701</description>\n");
message.append(" <orderDate>2013-03-23T00:00:00+02:00</orderDate>\n");
message.append(" </order>\n");
message.append(" <order>\n");
message.append(" <id>702</id>\n");
message.append(" <description>Order 702</description>\n");
message.append(" <orderDate>2013-07-23T00:00:00+02:00</orderDate>\n");
message.append(" </order>\n");
message.append(" </orders>\n");
message.append("</ns2:orderResponse>\n");
}
public static void main(String[] args) throws MappingException, MarshalException, ValidationException {
InputStream istream = OrderManager.class.getResourceAsStream("mapping.xml");
System.out.println(message.toString());
InputSource is = new InputSource(istream);
// Load Mapping
Mapping mapping = new Mapping();
mapping.loadMapping(is);
// initialize and configure XMLContext
XMLContext context = new XMLContext();
context.addMapping(mapping);
// Create a new Unmarshaller
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setClass(OrderResponse.class);
is.setCharacterStream(new StringReader(message.toString()));
OrderResponse orderResponse = (OrderResponse)unmarshaller.unmarshal(is);
System.out.println(orderResponse);
System.out.println(orderResponse.getCustomer().getId());
System.out.println(orderResponse.getCustomer().getName());
System.out.println(orderResponse.getCustomer().getSurname());
System.out.println(orderResponse.getCustomer().getAddress());
System.out.println(orderResponse.getCustomer().getEmail());
Orders orders = orderResponse.getOrders();
for(Order order : orders.getOrders()){
System.out.println(order.getId());
System.out.println(order.getOrderDate());
System.out.println(order.getDescription());
}
}
}
#Simple dto/xsd
package org.sample.castor;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "customer", namespace="http://org.sample.castor", propOrder = {
"id",
"name",
"surname",
"address",
"email"
})
public class Customer implements Serializable{
private long id;
private String name;
private String surname;
private String address;
private String email;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
#Simple dto/xsd
package org.sample.castor;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "order", namespace="http://org.sample.castor", propOrder = {
"id",
"orderDate",
"description"
})
public class Order implements Serializable{
private long id;
private XMLGregorianCalendar orderDate;
private String description;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public XMLGregorianCalendar getOrderDate() {
return orderDate;
}
public void setOrderDate(XMLGregorianCalendar orderDate) {
this.orderDate = orderDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
#Simple dto/xsd
package org.sample.castor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "orderResponse", namespace="http://org.sample.castor", propOrder = {
"customer",
"orders"
})
public class OrderResponse implements Serializable{
private Customer customer;
private Orders orders;
public Orders getOrders() {
return orders;
}
public void setOrders(Orders orders) {
this.orders = orders;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
#Simple dto/xsd
package org.sample.castor;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "orders", namespace="http://org.sample.castor", propOrder = {
"orders"
})
public class Orders {
private List<Order> orders;
public List<Order> getOrders() {
if (orders == null) {
orders = new ArrayList<Order>();
}
return this.orders;
}
}
#Handler
package org.sample.castor.handler;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.datatype.DatatypeConfigurationException;
import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.mapping.ValidityException;
import org.sample.castor.Order;
import org.sample.castor.util.DateUtil;
public class OrderDateHandler implements FieldHandler{
private static final String FORMAT = "yyyy-MM-dd";
/**
* Creates a new OrderDateHandler instance
*/
public OrderDateHandler() {
super();
}
public Object getValue(final Object object) throws IllegalStateException {
Order root = (Order)object;
Date value = new Date(); //root.getDate();
if (value == null) return null;
SimpleDateFormat formatter = new SimpleDateFormat(FORMAT);
Date date = (Date)value;
return formatter.format(date);
}
public void setValue(Object object, Object value)
throws IllegalStateException, IllegalArgumentException {
Order root = (Order)object;
SimpleDateFormat formatter = new SimpleDateFormat(FORMAT);
Date date = null;
try {
date = formatter.parse((String)value);
}
catch(ParseException px) {
throw new IllegalArgumentException(px.getMessage());
}
try {
root.setOrderDate(DateUtil.toXMLGregorianCalendar(date));
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
}
public Object newInstance(Object parent) throws IllegalStateException {
//-- Since it's marked as a string...just return null,
//-- it's not needed.
return null;
}
public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
((Order)object).setOrderDate(null);
}
@Override
public void checkValidity(Object arg0) throws ValidityException,
IllegalStateException {
// TODO Auto-generated method stub
}
}
#utility class
package org.sample.castor.util;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateUtil {
public static XMLGregorianCalendar toXMLGregorianCalendar(Date date) throws DatatypeConfigurationException {
GregorianCalendar c = new GregorianCalendar();
c.setTime(date);
XMLGregorianCalendar xmlGreCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
return xmlGreCal;
}
public static XMLGregorianCalendar toXMLGregorianCalendar(String date)
throws DatatypeConfigurationException {
XMLGregorianCalendar xmlGCal = null;
try {
xmlGCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(date);
} catch (DatatypeConfigurationException ex) {
ex.printStackTrace();
}
return xmlGCal;
}
}
#castor file mapping.xml
<?xml version="1.0"?>
<mapping>
<class name="org.sample.castor.OrderResponse" type="org.sample.castor.OrderResponse">
<map-to xml="orderResponse"/>
<field name="customer"
type="org.sample.castor.Customer">
<bind-xml name="customer" node="element"/>
</field>
<field name="orders"
type="org.sample.castor.Orders">
<bind-xml name="orders" node="element"/>
</field>
</class>
<class name="org.sample.castor.Orders" type="org.sample.castor.Orders">
<map-to xml="orders"/>
<field name="orders"
type="org.sample.castor.Order" collection="arraylist">
<bind-xml name="orders" node="element"/>
</field>
</class>
<class name="org.sample.castor.Order" type="org.sample.castor.Order">
<map-to xml="order"/>
<field name="id"
type="java.lang.Long">
<bind-xml name="id" node="element"/>
</field>
<field name="orderDate"
type="java.lang.String" handler="org.sample.castor.handler.OrderDateHandler">
<bind-xml name="orderDate" node="element"/>
</field>
<field name="description"
type="java.lang.String">
<bind-xml name="description" node="element"/>
</field>
</class>
<class name="org.sample.castor.Customer" type="org.sample.castor.Customer">
<map-to xml="customer"/>
<field name="id"
type="java.lang.Long">
<bind-xml name="id" node="element"/>
</field>
<field name="name"
type="java.lang.String">
<bind-xml name="name" node="element"/>
</field>
<field name="surname"
type="java.lang.String">
<bind-xml name="surname" node="element"/>
</field>
<field name="address"
type="java.lang.String">
<bind-xml name="address" node="element"/>
</field>
<field name="email"
type="java.lang.String">
<bind-xml name="email" node="element"/>
</field>
</class>
</mapping>
libraries:
castor-1.3.1-xml.jar
castor-core-1.3.2.jar
In case the blogging system might not support attachments, you could email me at doviche@gmail.com and I will reply with a rar or zip file, containing both jar files.
Thanks for reading
Douglas Oviche
Nessun commento:
Posta un commento