Shane C. Mason
Shane C. Mason

Reputation: 7615

How to make a deep copy of JAXB object like xmlbean XmlObject.copy()?

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?

Upvotes: 2

Views: 8601

Answers (4)

Renganathan M G
Renganathan M G

Reputation: 5209

You can refer this

public static <T> T deepCopyJAXB(T object, Class<T> clazz) {
  try {
    JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
    JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, object);
    JAXBSource source = new JAXBSource(jaxbContext, contentObject);
    return jaxbContext.createUnmarshaller().unmarshal(source, clazz).getValue();
  } catch (JAXBException e) {
      throw new RuntimeException(e);
  }
}

public static <T> T deepCopyJAXB(T object) {
  if(object==null) throw new RuntimeException("Can't guess at class");
  return deepCopyJAXB(object, (Class<T>) object.getClass());
}

It works for me.

All the credit goes to https://gist.github.com/darrend/821410

Upvotes: 7

Jherico
Jherico

Reputation: 29240

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>
</xsd:annotation>

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

Upvotes: 3

Anand
Anand

Reputation: 419

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);

Upvotes: 4

Steve Kuo
Steve Kuo

Reputation: 63094

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();

Upvotes: 3

Related Questions