Cloning a JAXB object

When you are using Java language to integrate applications you sooner or later will need a XML Binding framework. I have always used JAXB which is very easy to use in combination with Maven and the right plugin. Currently I am using it to bind XML to Java objects that I use in my JBPM processes. Although I am using the combination Maven-JAXB for over 8 years I am still learning new things. Today I ran into the need of cloning an existing JAXB object. There are several options for this. Since JAXB is all about marshalling and unmarshalling to XML you can marshall your JAXB object to XML and unmarshall it back to a new JAXB object. Although there is nothing wrong with this approach it is not very friendly performance-wise. Another way is using the ‘standard’ serialization and unserialization. To do this you have to make the generated JAXB classes serializable which I describe here how to do it. But there is even a better solution available which is to use the JAXB2 Basic plugin. I have never used it before but it is really handy. The homepage for this plugin can be found here. To make my generated classes define a copyTo method to clone them I had to include the following configuration to my existing pom.xml:

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId> 
  <artifactId>maven-jaxb2-plugin</artifactId> 
  <version>0.7.1</version>
  <executions>   
    ... 
  </executions>
  <configuration>            
    <schemaDirectory>src/main/resources/schemas</schemaDirectory>              
    <extension>true</extension>       
    <args>
      <arg>-XtoString</arg>
      <arg>-Xcopyable</arg>
      <arg>-Xequals</arg>
    </args>
    <schemaIncludes>         
      <schemaInclude>*.xsd</schemaInclude>       
    </schemaIncludes>   
    <sourceDestDir>${basedir}/generated/src/main/java</sourceDestDir>
    <generatePackage>net.pascalalma.model</generatePackage>
    <plugins>
      <plugin>
        <groupId>org.jvnet.jaxb2_commons</groupId>
        <artifactId>jaxb2-basics</artifactId>
        <version>0.6.4</version>
      </plugin>
    </plugins>
  </configuration>
</plugin>

And to make the plugin in the plugin available I had to add the dependency to the dependencies part of the pom:

<dependency>
  <groupId>org.jvnet.jaxb2_commons</groupId>
  <artifactId>jaxb2-basics</artifactId>
  <version>0.6.4</version>
</dependency>

The JAXB classes that are now generated implement several interfaces by newly added methods like this:

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-792 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2012.11.20 at 09:48:23 AM CET 
//

package net.pascalalma.model;

import ...;

/**
 …
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    ...
    })
@XmlRootElement(name = "priceImport")
public class PriceImport
    implements Cloneable, CopyTo, Equals, ToString
{

  ...
    public String toString() {
        final ToStringStrategy strategy = JAXBToStringStrategy.INSTANCE;
        final StringBuilder buffer = new StringBuilder();
        append(null, buffer, strategy);
        return buffer.toString();
    }

    public StringBuilder append(ObjectLocator locator, StringBuilder buffer, ToStringStrategy strategy) {
        strategy.appendStart(locator, this, buffer);
        appendFields(locator, buffer, strategy);
        strategy.appendEnd(locator, this, buffer);
        return buffer;
    }

    public StringBuilder appendFields(ObjectLocator locator, StringBuilder buffer, ToStringStrategy strategy) {        
        ...
        return buffer;
    }

    public Object clone() {
        return copyTo(createNewInstance());
    }

    public Object copyTo(Object target) {
        final CopyStrategy strategy = JAXBCopyStrategy.INSTANCE;
        return copyTo(null, target, strategy);
    }

    public Object copyTo(ObjectLocator locator, Object target, CopyStrategy strategy) {
        final Object draftCopy = ((target == null)?createNewInstance():target);
        ...
        return draftCopy;
    }

    public Object createNewInstance() {
        return new PriceImport();
    }

    public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy strategy) {
        if (!(object instanceof PriceImport)) {
            return false;
        }
        if (this == object) {
            return true;
        }
        final PriceImport that = ((PriceImport) object);
       ...
        return true;
    }

    public boolean equals(Object object) {
        final EqualsStrategy strategy = JAXBEqualsStrategy.INSTANCE;
        return equals(null, null, object, strategy);
    }

}

And now you can simply say yourJaxbObject.copyTo(newInstance) to create a cloned JAXB object. The only thing I needed to do is to make the JAXB-basics-runtime.jar available in my JBPM instance as described here.

About Pascal Alma

Pascal is a senior IT consultant and has been working in IT since 1997. He is monitoring the latest development in new technologies (Mobile, Cloud, Big Data) closely and particularly interested in Java open source tool stacks, cloud related technologies like AWS and mobile development like building iOS apps with Swift. Specialties: Java/JEE/Spring Amazon AWS API/REST Big Data Continuous Delivery Swift/iOS
This entry was posted in JAXB, Maven and tagged , . Bookmark the permalink.