Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataTypeFactory usage in creating XMLGregorianCalendar hits performance badly

Given a time in milliseconds, we can create XMLGregorianCalendar using the following snippet.

GregorianCalendar greCal = new GregorianCalendar();
greCal.setTimeInMillis(timeInMilliseconds);
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(greCal));

But the problem is, it hits the performance badly.

http://www.java.net/node/666491

There is a bug filed for this with SUN but they have not listed any workarounds. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6466177

Tried searching for some other alternative but in vain. Do any of you folks have an alternative to do the same?

Thanks

Raman

like image 721
Raman Avatar asked Sep 08 '11 10:09

Raman


People also ask

What is XML Gregorian calendar?

XML Gregorian Calendar: The rules for specifying dates in XML format are defined in the XML Schema standard. The Java XMLGregorianCalendar class, introduced in Java 1.5, is a representation of the W3C XML Schema 1.0 date/time datatypes and is required to use the XML format.

How do I create an instance of XMLGregorianCalendar?

Create a new XMLGregorianCalendar by parsing the String as a lexical representation. Create a Java representation of XML Schema builtin datatype date or g* . Create a Java instance of XML Schema builtin datatype time. Create a Java instance of XML Schema builtin datatype time .

What is DatatypeFactory?

DatatypeFactory ", exists, a class with the name of the property's value is instantiated. Any Exception thrown during the instantiation process is wrapped as a DatatypeConfigurationException . If the file ${JAVA_HOME}/lib/jaxp. properties exists, it is loaded in a Properties Object .


2 Answers

The expensive part is DatatypeFactory.newInstance(), it shows right on top when profiling the application. In our case we stored the DatatypeFactory as static variable and we were able to circumvent the repeated initialization. This should work because the DatatypeFactory implementation we use is supposed to be thread safe (as stated in the bug report). I agree that there's a chance that this may change depending on the implementation used. So I'll recommend to doublecheck.

private static DatatypeFactory datatypeFactory;
static{
    try {
        datatypeFactory = DatatypeFactory.newInstance();
    } catch (DatatypeConfigurationException e) {
        throw new RuntimeException("Init Error!", e);
    }
}

public void foo(long timeInMilliseconds){
    GregorianCalendar greCal = new GregorianCalendar(); greCal.setTimeInMillis(timeInMilliseconds); 
    XMLGregorianCalendar xmlGregorienCalendar = datatypeFactory.newXMLGregorianCalendar(greCal);
    // ...
}
like image 106
VivaceVivo Avatar answered Oct 12 '22 10:10

VivaceVivo


Since as @VivaceVivo mentioned DataFactory.newInstance() is expensive and impl not guaranteed to be thread-safe, consider using a ThreadLocal:

final private static ThreadLocal<DatatypeFactory> datatypeFactoryHolder = new ThreadLocal<DatatypeFactory>()
    {
        @Override
        protected DatatypeFactory initialValue()
        {
            try
            {
                return DatatypeFactory.newInstance();
            } catch (DatatypeConfigurationException e)
            {
                throw new IllegalStateException("failed to create " + DatatypeFactory.class.getSimpleName(), e);
            }
        }
    };

    public static XMLGregorianCalendar dateToXMLGregorianCalendar(Date date)
    {
        GregorianCalendar c = new GregorianCalendar();
        c.setTime(date);
        return datatypeFactoryHolder.get().newXMLGregorianCalendar(c);
    }
}

..as long as you don't care if threads retain an extra object or have a way of clearing ThreadLocalMap when needed

like image 27
Nikita Avatar answered Oct 12 '22 09:10

Nikita