I posted some days ago an article explaining how to “XML-serialize” objects with JAXB in Eclipse. The downside of using XSD for XML serialization is the dependency on the XML schema that will generate java classes; this is because I wanted to extend the classes to have extra-functionality, more constructors and so on. So I started looking for a way to serialize objects to XML without creating XSD definitions… but I found a problem: every time java classes are generated, an additional class, called ObjectFactory.java is also created. It is also needed for XML marshalling/unmarshalling. The only viable solution I found was to write my one ObjectFactory.java class, to be used by JAXB when serializing objects.
But I creating ObjectFactory is not necessary. We can simply serialize from simple xml files(see here).
But if we want we can create our own ObjectFactory Class. Example:
Step 1: Create the java classes that you need. In my case, I had two main entities, Node and Line, and two additional collections, Lines and Nodes. I also created a Graph entity, holding a list with nodes and a list with lines. Below are presented Line.java, Lines.java and Graph.java files
Line.java
package com.vaani.jaxb.objects;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Line", propOrder = { "startNode", "endNode" })
public class Line {
@XmlAttribute(name = "StartNode")
protected int startNode;
@XmlAttribute(name = "EndNode")
protected int endNode;
public Line(int start, int end) {
this.setStartNode(start);
this.setEndNode(end);
}
public Line() {
this(0, 0);
}
public int getStartNode() {
return startNode;
}
public void setStartNode(int value) {
this.startNode = value;
}
public int getEndNode() {
return endNode;
}
public void setEndNode(int value) {
this.endNode = value;
}
}
Lines.java
package com.vaani.jaxb.objects;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "lines", propOrder = { "lines" })
public class Lines {
@XmlElement(name = "Line")
protected List<Line> lines;
public List<Line> getLines() {
if (lines == null) {
lines = new ArrayList<Line>();
}
return this.lines;
}
}
Graph.java
package com.vaani.jaxb.objects;
import java.io.*;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Graph")
public class Graph {
@XmlElement(name = "Nodes", required = true)
protected Nodes nodes = new Nodes();
@XmlElement(name = "Lines", required = true)
protected Lines lines = new Lines();
@XmlAttribute(name = "StartNode")
protected int startNode;
@XmlAttribute(name = "EndNode")
protected int endNode;
public void addNode(int x, int y) {
getNodes().add(new Node(x, y, getNodes().size() + 1));
}
public void addLine(int start, int end) {
getLines().add(new Line(start, end));
}
public List<Node> getNodes() {
return nodes.getNodes();
}
public void setNodes(Nodes value) {
this.nodes = value;
}
public List<Line> getLines() {
return lines.getLines();
}
public void setLines(Lines value) {
this.lines = value;
}
public int getStartNode() {
return startNode;
}
public void setStartNode(int value) {
this.startNode = value;
}
public int getEndNode() {
return endNode;
}
public void setEndNode(int value) {
this.endNode = value;
}
public void marshalToFile(String fileName) {
try {
JAXBContext jc = JAXBContext.newInstance(this.getClass().getPackage().getName());
Marshaller m = jc.createMarshaller();
m.marshal( this, new FileOutputStream(fileName) );
} catch(Exception e) {
e.printStackTrace();
}
}
public static Graph unmarshalFromFile(String fileName) {
try {
JAXBContext jc = JAXBContext.newInstance((new Graph()).getClass().getPackage().getName());
Unmarshaller um = jc.createUnmarshaller();
return (Graph) um.unmarshal(new File(fileName));
} catch (Exception e) {
return new Graph();
}
}
}
In order to be able to serialize the above classes, we must use the XML annotations like @XmlRootElement, @XmlElement, @XmlAttribute, @XmlType. For the serialization, we use the same JAXBContext, Marshaller and Unmarshaller classes.
Step 2: Implement the ObjectFactory.java class
package com.vaani.jaxb.objects;
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public Graph createGraph() {
return new Graph();
}
public Node createNode() {
return new Node();
}
public Line createLine() {
return new Line();
}
}
As you can see, the class must be preceded by @XmlRegistry annotation.
Step 3: Test the serialization
package com.vaani.jaxb.objects;
import org.junit.*;
import static org.junit.Assert.*;
public class GraphTest {
Graph graph;
@Test
public void test_graph()
{
createGraph();
graph.marshalToFile("newGraphOutput.xml");
Graph secondGraph = Graph.unmarshalFromFile("newGraphOutput.xml");
assertTrue(secondGraph.getLines().size() == 2);
assertTrue(secondGraph.getNodes().size() == 3);
}
private void createGraph()
{
graph = new Graph();
graph.addNode(60, 60);
graph.addNode(110, 110);
graph.addNode(60, 110);
graph.addLine(1, 3);
graph.addLine(2, 3);
}
}
Step 4: Check the result
No comments:
Post a Comment