I have two classes which are having relations with each other as below. I have a list of ObjReal objects where the whole data is presented. I want to save the whole List into xml without losing the object relationships. I mean an object represented in XML should have their corresponding objStrucs along with it. To store ObjReal into xml is straight forward but i am getting confused with its ObjStruc relations. Please helpe to solve this problem.
My ObjReal is:
Class ObjReal
{
private String id;
private String data;
ArrayList<ObjStruc> objStrucs=new ArrayList<ObjStruc>();
public ArrayList<ObjStruc> getObjStrucs()
{
return objStrucs;
}
public String getId()
{
return id;
}
public String getData()
{
return data;
}
public void setId(String id)
{
this.id=id;
}
public void setData(String data)
{
this.data=data;
}
}
My ObjStruc is:
Class ObjStruc
{
private ObjReal objReal;
public ObjReal getObjReal()
{
return objReal;
}
public ObjReal setObjReal(ObjReal objReal)
{
this.objReal=objReal;
}
}
And the complete data is in ArrayList<ObjReal> obreals
object which i want to dump into xml. I hope i kept a clear point. Thanks in advance.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
There are a couple interesting aspects of your use case:
ObjReal
and ObjStruc
1. ARRAYLIST AS ROOT OBJECT
JAXB implementations (MOXy, Metro, JaxMe, etc) do not provide direct support for handling Collection
types as root objects. To handle this use case you simply need to create a wrapper class that has the desired Collection
as a field/property.
@XmlRootElement(name="root-element-name")
@XmlAccessorType(XmlAccessType.FIELD)
public class ListWrapper {
private ArrayList<ObjReal> objReals;
}
2. BIDIRECTIONAL RELATIOSNHIP
You can use the @XmlInverseReference
extension in EclipseLink implementation of JAXB to handle the bidirectional relationship in your model. Below I have included a complete example. I have omitted most of the accessor methods to save space.
ObjReal
import java.util.ArrayList;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class ObjReal {
private String id;
private String data;
ArrayList<ObjStruc> objStrucs=new ArrayList<ObjStruc>();
public ArrayList<ObjStruc> getObjStrucs() {
return objStrucs;
}
}
ObjStruc
The @XmlInverseReference
annotation is used on this class. On this annotation you specify the fied/property name for the other direction of the relationship:
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;
@XmlAccessorType(XmlAccessType.FIELD)
class ObjStruc {
@XmlInverseReference(mappedBy="objStrucs")
private ObjReal objReal;
public ObjReal getObjReal() {
return objReal;
}
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties with the following content in the same package as your domain classes:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
You can run the following code to verify the mapping:
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ObjReal.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum8868303/input.xml");
ObjReal objReal = (ObjReal) unmarshaller.unmarshal(xml);
for(ObjStruc objStruc : objReal.getObjStrucs()) {
System.out.println(objStruc.getObjReal());
}
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(objReal, System.out);
}
}
Input (input.xml)
<?xml version="1.0" encoding="UTF-8"?>
<objReal>
<id>123</id>
<data>some data</data>
<objStrucs/>
<objStrucs/>
</objReal>
Output
Below is the output from running the demo code. As you can see the objReal
property on each of the ObjStruc
objects was populated during the unmarshal:
forum8868303.ObjReal@7f712b3a
forum8868303.ObjReal@7f712b3a
<?xml version="1.0" encoding="UTF-8"?>
<objReal>
<id>123</id>
<data>some data</data>
<objStrucs/>
<objStrucs/>
</objReal>
For More Information
Download EclipseLink
You can download EclipseLink at:
There are several libraries that will serialiaze object structures to xml. One of them is XStream. There is an easy and fast tutorial here.
Just feed it to XStream! It works both ways. Code snippets here. Good luck!
Any easy way to write a java object to xml is to use the java xml encoder. This writes your entire object and its dependencies to xml format. You can then read them back in to your object also.
public static boolean writeXMLFile(final Object data, final String fileName) {
XMLEncoder encoder = null;
boolean result = true;
try {
encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(fileName)));
encoder.writeObject(data);
} catch (final IOException e) {
logger.error(e.getMessage());
result = false;
} finally {
if (encoder != null) {
encoder.close();
} else {
result = false;
}
}
public static Object readXMLFile(final String fileName) {
XMLDecoder decoder = null;
Object data = null;
try {
FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
decoder = new XMLDecoder(bis);
data = decoder.readObject();
} catch (final FileNotFoundException e) {
data = null;
logger.error(e.getMessage());
} catch (final Exception e) {
data = null;
logger.error(e.getMessage());
} finally {
if (decoder != null) {
decoder.close();
} else {
data = null;
}
}
return data;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With