JAXB Bigdecimal/BigInteger adapter

JAXB BigDecimal / BigInteger apapters

Jaxb NumberFormatException

XML attributes represents null values with empty string. During unmarshalling an XML with empty value for a BigDecimal/BigInteger JAXB throws NumberFormatException.
For the case of BigDecimal it will be NumberFormatException at java.math.BigDecimal.<init> and for BigInteger it can be NumberFormatException: Zero length BigInteger at java.math.BigInteger.<init> exception.

To overcome this problem, Jaxb provides a feature called TypeAdapters. Using TypeAdapters we can specify how to marshall/unmarshall a particular object or complex xml type when some of its fields are not proper. For example we can instruct JAXB if BigDecimal is empty treat it as 0, don't report an exception.

BigDecimal Adapter

 

Below is the sample BigDecimal Adapter which advices marshall and unmarshall in the event of null values.

/*
 * 
 * BigDecimalAdapter.java 
 * Adapter for java.math.BigDecimal objects
 *
 */

package com.sample.xmadapters;

import java.math.BigDecimal;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class BigDecimalAdapter extends XmlAdapter<string bigdecimal="">{

    /* Adapter method for BigDecimal marshaling
     * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
     */
    @Override
    public String marshal(BigDecimal bigDecimal) throws Exception {
	if (bigDecimal != null){
		return bigDecimal.toString();
	}
	else {
		return null;
	}

    }

    /* Adapter for BigDecimal marshaling
     * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
     */
    @Override
    public BigDecimal unmarshal(String string) throws Exception {
	try {
	    return new BigDecimal(string);
	} catch (NumberFormatException e) {
	    return null;
	}

    }

}

Registering the adapter at package level.

We can put the above adapter for each of the classes we require, but when you have tons of classes we have to annotate all of them separately. Instead of putting annotations in each of the generated classes we can put the annotation at package level of our xml types package.

package-info.java

/*
 *
 * packageinfo.java 
 * 
 * This file is required for JAXB to process package level 
 * annotations.
 *
 * File: package-info.java
 *
 */
@XmlJavaTypeAdapters({ 
		@XmlJavaTypeAdapter(value = com.sample.xmadapters.BigDecimalAdapter.class, type = java.math.BigDecimal.class),
		@XmlJavaTypeAdapter(value = com.sample.xmadapters.BigIntegerAdapter.class, type = java.math.BigInteger.class)
})
package com.sample.xmltypes;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

/* package-info.java end */

Comments

Post a Comment

Popular posts from this blog

Log4j multiple WAR files in single EAR configuration

Java NIO2 - Watching a directory for changes. FileWatcherService.

Ubuntu Add programs to launcher (Desktop)