Sunday, May 16, 2010

JAXB Context

Recently in one of the systems I work on, went through some bad times, we were struggling with performance, memory, and stability issues... during the days and days of investigations one of the many little improvements we made was the JAXBContextFactory. The JAXBContext proved to be a very very expensive object to make so I created a little Factory to cache the instances we created and reuse them:
package bob.blog;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

public final class JAXBContextFactory {

    private static JAXBContextFactory instance = new JAXBContextFactory();
    private static final Map< String, JAXBContext > instances = new ConcurrentHashMap< String, JAXBContext >();

    private JAXBContextFactory() {
    }

    /**
     * Returns an existing JAXBContext if one for the particular namespace exists, 
     * else it creates an instance adds it to a internal map.
     * @param contextPath the context path
     * @throws JAXBException exception in creating context
     * @return a created JAXBContext
     */
    public JAXBContext createJAXBContext(final String contextPath) throws JAXBException {
        JAXBContext context = instances.get(contextPath);
        if (context == null) {
            context = JAXBContext.newInstance(contextPath);
            instances.put(contextPath, context);
        }
        return context;
    }


        /**
     * Returns an existing JAXBContext if one for the particular namespace exists,
     * else it creates an instance adds it to a internal map.
     * @param contextPath the context path
     * @throws JAXBException exception in creating context
     * @return a created JAXBContext
     */
    public JAXBContext createJAXBContext(final Class contextPath) throws JAXBException {
        JAXBContext context = instances.get(contextPath.getName());
        if (context == null) {
            context = JAXBContext.newInstance(contextPath);
            instances.put(contextPath.getName(), context);
        }
        return context;
    }

    /**
     * Get instnace.
     * @return Instance of this factory
     */
    public static JAXBContextFactory getInstance() {
        return instance;
    }
}

2 comments:

  1. For thread safety, you should be using instances.putIfAbsent() (instances will need to be declared as type ConcurrentHashMap instead of Map).

    The code inside createJAXBContext() would then look like this:

    :
    :
    if ( null == context ) {
    context=instances.putIfAbsent(
    contextPath.getName(),
    JAXBContext.newInstance(contextPath));

    }

    //Paranoid sanity check
    if (null == context) {
    throw new NullPointerException("Could not instantiate new JAXBContext for " + contextPath.getName() + "or insert into map."
    }

    return context;

    ReplyDelete

Popular Posts

Followers