tags:

views:

565

answers:

3

I have been tasked with refactoring some components that used xmlbeans to now make use of jaxb. Everything is going great, until I get to a place where the previous author has called the copy() function of one of the XmlObjects. Since all objects in xmlbeans extend XmlObject, we get the magic deep copy function for free.

Jaxb does not seem to provide this for us. What is the correct and simple way to make a deep copy of a Jaxb object?

+1  A: 

You could make your JAXB classes serializable and then deep copying an object by serializing and deserializing it. The code might look something like:

Object obj = ...  // object to copy

ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());
out.writeObject(obj);
byte[] bytes = baos.toByteArray();

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object copy = in.readObject();
Steve Kuo
You don't really need to make them serializable, since the entire purpose behind JAXB is marshalling objects to and from XML. You could marshall and unmarhsall the object to make a copy, but that's probably far less efficient than writing your own clone() function.
nsayer
+1 I think this is the right way - it jives with other suggestions I have seen. Thanks for the example code.
Shane C. Mason
+1  A: 

You can declare a base class for the generated jaxb objects using an annotation in the XSD...

<xsd:annotation>
<xsd:appinfo>
  <jaxb:globalBindings>
    <xjc:superClass name="com.foo.types.support.JaxbBase" />
  </jaxb:globalBindings>
</xsd:appinfo>

You can add the clonability support there using the xmlbeans base class as a template.

Jherico
+1 I really like this idea - unfortunately, it does not fit into our use case (which is a little off the norm)
Shane C. Mason
A: 

You can use JAXBSource

Say you want to deep copy a sourceObject, of type Foo. Create 2 JAXBContexts for the same Type:

JAXBContext sourceJAXBContext = JAXBContext.newInstance("Foo.class");

JAXBContext targetJAXBContext = JAXBContext.newInstance("Foo.class");

and then do:

targetJAXBContext.createUnmarshaller().unmarshal( new JAXBSource(sourceJAXBContext,sourceObject);

Anand