diff --git a/core/src/main/java/com/github/dozermapper/core/factory/ConstructionStrategies.java b/core/src/main/java/com/github/dozermapper/core/factory/ConstructionStrategies.java index 8c577125c..5db49988c 100644 --- a/core/src/main/java/com/github/dozermapper/core/factory/ConstructionStrategies.java +++ b/core/src/main/java/com/github/dozermapper/core/factory/ConstructionStrategies.java @@ -409,19 +409,24 @@ private static T newInstance(Class clazz) { private static class XmlGregorian implements BeanCreationStrategy { + // Instantiating a DatatypeFactory with DatatypeFactory.newInstance() is expensive, so this should be cached. + // Regrettably the spec does not require implementations to be thread safe, so we are defensively using + // thread local caching here. + private static final ThreadLocal datatypeFactoryHolder = ThreadLocal.withInitial(() -> { + try { + return DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new MappingException(e); + } + }); + public boolean isApplicable(BeanCreationDirective directive) { Class actualClass = directive.getActualClass(); return XMLGregorianCalendar.class.isAssignableFrom(actualClass); } public Object create(BeanCreationDirective directive) { - DatatypeFactory dataTypeFactory; - try { - dataTypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException e) { - throw new MappingException(e); - } - return dataTypeFactory.newXMLGregorianCalendar(); + return datatypeFactoryHolder.get().newXMLGregorianCalendar(); } }