Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Carlos Martins Getting Started with Juffrou-XMLJuffrou-XML is an open source java library to marshall beans to xml and back. The objective is to make this simple, logical and flexible.
With Juffrou-XML you have simplified marshalling, wich means that you can obtain the XML representation of complex structure of java beans with all its nested beans represented as nested elements, but you can also get a "flattened" XML representation with properties from the root bean and properties from the nested beans in a very simple manner.
Enough talk! Let's see how it works:
To start using Juffrou-XML in your maven project just add the following dependency:
<dependency> <groupId>net.sf.juffrou</groupId> <artifactId>juffrou-xml</artifactId> <version></version> </dependency>
Download the file juffrou--bundle.zip from the website and extract it's contents to a temporary directory.
Add juffrou-reflect-.jar and juffrou-xml-.jar to the classpath of your project and you are good to go.
With these libraries in your classpath you can start using juffrou-XML right away:
Person person = new Person(); person.setFirstName("Carlos"); person.setLastName("Martins"); person.setBirthDay(new SimpleDateFormat("yyyy-MM-dd").parse("1967-10-01")); JuffrouXml juffrouXml = new JuffrouXml(); String xmlString = juffrouXml.toXml(person);
The output will be the following XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <net.sf.juffrou.xml.test.dom.Person> <firstName>Carlos</firstName> <lastName>Martins</lastName> <birthDay>10/1/67 12:00 AM</birthDay> </net.sf.juffrou.xml.test.dom.Person>
Without configuration, the names of root elements will be the class name of the corresponding bean, all its properties will be marshalled and the names of the child elements will be the names of the corresponding property. Juffrou-XML is also able to unmarshall the XML text back to a person bean as long as the classes in the root elements are in the program classpath like in the following example:
Person person = (Person) juffrouXml.fromXml(xmlString);
If you want to change the element names of the beans or how those beans are marshalled / unmarshalled, then you need configuration. Configuration can be done either through direct coding or by means of an XML file.
To configure by file you can instantiate Juffrou-XML and pass the file name in the constructor, or you can instantiate Juffrou-XML with the default constructor and then call the readConfigFile method.
JuffrouXml juffrouXml = new JuffrouXml("classpath:juffrou-config.xml"); JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.readConfigFile("classpath:config-file-one.xml"); juffrouXml.readConfigFile("file:/etc/config-file-two.xml");
JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.registerRootElement(Person.class, "Person");
<?xml version="1.0" encoding="UTF-8"?> <mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://juffrou.sourceforge.net/juffrou-xml" xsi:schemaLocation="http://juffrou.sourceforge.net/juffrou-xml http://juffrou.sourceforge.net/juffrou-xml/schemas/juffrou-xml.xsd"> <root-element xml="Person" type="net.sf.juffrou.xml.test.dom.Person" /> </mapping>
The corresponding XML now looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <Person> <firstName>Carlos</firstName> <lastName>Martins</lastName> <birthDay>10/1/67 12:00 AM</birthDay> </Person>
JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.registerElement(Person.class, "lastName", "Surname");
<?xml version="1.0" encoding="UTF-8"?> <mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://juffrou.sourceforge.net/juffrou-xml" xsi:schemaLocation="http://juffrou.sourceforge.net/juffrou-xml http://juffrou.sourceforge.net/juffrou-xml/schemas/juffrou-xml.xsd"> <root-element xml="Person" type="net.sf.juffrou.xml.test.dom.Person"> <element property="firstName" /> <element property="lastName" xml="Surname" /> <element property="birthDay" /> </root-element> </mapping>
The corresponding XML now looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <Person> <firstName>Carlos</firstName> <Surname>Martins</Surname> <birthDay>10/1/67 12:00 AM</birthDay> </Person>
JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.registerAttribute(Person.class, "firstName", "name");
<?xml version="1.0" encoding="UTF-8"?> <mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://juffrou.sourceforge.net/juffrou-xml" xsi:schemaLocation="http://juffrou.sourceforge.net/juffrou-xml http://juffrou.sourceforge.net/juffrou-xml/schemas/juffrou-xml.xsd"> <root-element xml="Person" type="net.sf.juffrou.xml.test.dom.Person"> <attribute property="firstName" xml="name" /> <element property="lastName" xml="Surname" /> <element property="birthDay" /> </root-element> </mapping>
The corresponding XML now looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <Person name="Carlos"> <Surname>Martins</Surname> <birthDay>10/1/67 12:00 AM</birthDay> </Person>
Serializers are the classes responsible for translating bean property values to XML and back. Juffrou-xml comes with serializers for the basic java types, like String, Integer and Boolean for instance. You can see the complete list of serializers in the javadoc for the package net.sf.juffrou.xml.serializer.
You may want to create your own serializers and tell juffrou to use them. For intance, you may want to have properties of type Date displayed in a particular format, so you create a serailizer that knows how to convert between Date and that specific format. You can also use serializers to convert between the text in an XML element and a more complex type. For example, in a class called Person, with a property private Address home you may want to represent home as a single text string. In this case you create a serializer that knows how to convert between Address and that text string.
Creating your own serializer is simple. Just implement the Serializer interface like in the following example:
public class SimpleDateSerializer implements Serializer { private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); @Override public void serialize(JuffrouWriter writer, BeanWrapper valueOwner, String valuePropertyName) { writer.write(formatter.format((Date)valueOwner.getValue(valuePropertyName))); } @Override public void deserialize(JuffrouReader reader, BeanWrapper valueOwner, String valuePropertyName) { String value = reader.getText(); try { valueOwner.setValue(valuePropertyName, formatter.parse(value)); } catch (ParseException e) { } } }
Once your serializer class is created, you can use it to translate your beans or bean properties using by configuring through code or mapping file.
JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.registerSerializer("mySimpleDateSerializer", new SimpleDateSerializer()); juffrouXml.registerElement(Person.class, "birthDay", "birthday", "mySimpleDateSerializer");
When using a configuration file you can define reusable serializers to share between bean properties or define a serializer that is exlusive to a perticular bean property.
<?xml version="1.0" encoding="UTF-8"?> <mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://juffrou.sourceforge.net/juffrou-xml" xsi:schemaLocation="http://juffrou.sourceforge.net/juffrou-xml http://juffrou.sourceforge.net/juffrou-xml/schemas/juffrou-xml.xsd"> <serializer id="mySimpleDateSerializer" class="net.sf.juffrou.xml.test.dom.SimpleDateSerializer"/> <root-element xml="Person" type="net.sf.juffrou.xml.test.dom.Person"> <attribute property="firstName" xml="name" /> <element property="lastName" xml="Surname"> <serializer class="net.sf.juffrou.xml.serializer.StringSerializer"/> </element> <element property="birthDay" xml="birthday"> <serializer ref="mySimpleDateSerializer"/> </element> </root-element> </mapping>
You can define serializers to share between bean properties with serializer element in the mapping file:
<serializer id="mySimpleDateSerializer" class="net.sf.juffrou.xml.test.dom.SimpleDateSerializer"/>
Id of the serializer to be referenced by the bean property serializers.
Class name of the serializer. This class will be instantiated only once and will be shared between the bean properties that reference it.
You can define a serializer for a bean property by nesting a serializer element like in the above example. Below are all the properties for a property serializer:
<serializer class="net.sf.juffrou.xml.test.dom.SimpleDateSerializer" ref="mySimpleDateSerializer" bean="mySpringBeanSerializer" />
Class name of the specific serializer class to use. This class will be instantiated and used exclusively for the bean property.
Id of the shared serializer.
Id of a springframework bean which implements serializer. This is only valid when using the library juffrou-xml-spring
Simplified marshalling is the possibility of marshalling nested beans into a "flat" XML structure like this: imagine that you don't want the whole home address marshalled for this person. You only want his home city and you want it displayed as it were a simple property of person.
Easy! All you have to do is this:
JuffrouXml juffrouXml = new JuffrouXml(); juffrouXml.registerRootElement(Person.class, "Person"); juffrouXml.registerElement(Person.class, "home.city", "homeTown", null); String xmlString = juffrouXml.toXml(person);
The output will now be:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <Person> <firstName>Carlos</firstName> <lastName>Martins</lastName> <birthDay>1967-10-01</birthDay> <homeTown>Lisboa</homeTown> </Person>
Of course this XML will also be unmarshalled back to a person object. That person object will have a home with city Lisboa.