Monday, March 28, 2011

JAXB Cloning : JAXB Object clone API

JAXB Cloning

How Do I Clone A JAXB Object

JAXB generated POJO classes are not implementing either Serializable or Cloneable interaces. Because of the fact that, the data on wire willbe transmitted as marshalled one (XML) instead of JAVA object.

If JAXB objects needs to be cloned then there is not straight forward approach exist to do that. Any of the following round about may help to achieve this

  1. Vendor extension - Add JAVA code using vendor specific extension to implement cloneable or serializable
  2. Marshall JAXB object and then Unmarshall again
  3. Write specific code for particular XML element by getting the value using getter method and set the same using setter method

All the above approaches, either time consuming one to implement or produces OutOfMemoryException or performance slow.

At last reflection approach is considered to arrive at Generalized solution. All the public methods which are all starts with either is or get fetched using reflection and values are set using set method found in the same object. If deep cloning is required then other than wrapper/primitive class objects has to be recursively called to clone.

Sample code to start with JAXB cloning


 public static final Object clone(Object src, boolean deep ) {
  if (null == src)
   throw new IllegalArgumentException("src can not be null");

  Object trg = null;
  
  try {
   trg = src.getClass().newInstance();

   Method[] methods = src.getClass().getMethods();
   for (Method method : methods) {
    Class clasObj = method.getReturnType();

    String name = method.getName();
    if (name.equals("getClass")) {
     continue;
    }
    if (name.startsWith("is")) {
     name = name.substring(2);
    } else if (name.startsWith("get")) {
     name = name.substring(3);
    } else {
     continue;
    }

    name = "set" + name;

    try {
     Object retObj = method.invoke(src);
     if (null != retObj) {
      if (retObj instanceof Map) {
       retObj = Collections.unmodifiableMap((Map) retObj);
      } else if (retObj instanceof Collection) {
       retObj = Collections
         .unmodifiableCollection((Collection) retObj);
      } else if (retObj.getClass().getName()
        .startsWith("java.lang")) {
       if (clasObj.getSimpleName().equals("boolean")) {
        clasObj = Boolean.class;
       }
      } else /* Other than Wrapper classes then clone further */
      {
       if(!deep)
        continue;
       retObj = clone(retObj, deep);
      }

      Method m = trg.getClass().getMethod(name, clasObj);
      m.invoke(trg, retObj);
     }
    } catch (NoSuchMethodException e) {
     e.printStackTrace();
    } catch (java.lang.reflect.InvocationTargetException e) {
     e.printStackTrace();
    }
   }
  } catch (IllegalArgumentException e) {
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
  } catch (InstantiationException e) {
   e.printStackTrace();
  }
  return trg;
 }

No comments:

Post a Comment

Recent Posts

Unix Commands | List all My Posts

Texts

This blog intended to share the knowledge and contribute to JAVA Community such a way that by providing samples and pointing right documents/webpages. We try to give our knowledege level best and no guarantee can be claimed on truth. Copyright and Terms of Policy refer blogspot.com