From 58d3e704bff9a5aa28e364608f2341b61fca74c7 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 11 Jun 2009 09:20:29 +0000 Subject: [PATCH] SPR-5745 - Support lazy initialization within Jaxb2 OXM classes --- .../oxm/jaxb/Jaxb2Marshaller.java | 56 +++++++++++++------ .../oxm/jaxb/Jaxb2MarshallerTests.java | 19 ++++++- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java b/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java index 59c69c3338e..fb5669111c5 100644 --- a/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java +++ b/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java @@ -140,6 +140,8 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl private Schema schema; + private boolean lazyInit = false; + /** * Set a JAXB context path. @@ -259,31 +261,53 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl this.mtomEnabled = mtomEnabled; } + /** + * Set whether to lazily initialize the {@link JAXBContext} for this marshaller. + * Default is {@code false} to initialize on startup; can be switched to + * {@code true}. + *

Early initialization just applies if afterPropertiesSet() is called. + * @see #afterPropertiesSet() + */ + public void setLazyInit(boolean lazyInit) { + this.lazyInit = lazyInit; + } + + public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } public final void afterPropertiesSet() throws Exception { - this.jaxbContext = createJaxbContext(); + if (StringUtils.hasLength(this.contextPath) && !ObjectUtils.isEmpty(this.classesToBeBound)) { + throw new IllegalArgumentException("Specify either 'contextPath' or 'classesToBeBound property'; not both"); + } + else if (!StringUtils.hasLength(this.contextPath) && ObjectUtils.isEmpty(this.classesToBeBound)) { + throw new IllegalArgumentException("Setting either 'contextPath' or 'classesToBeBound' is required"); + } + if (!lazyInit) { + getJaxbContext(); + } if (!ObjectUtils.isEmpty(this.schemaResources)) { this.schema = loadSchema(this.schemaResources, this.schemaLanguage); } } - protected JAXBContext createJaxbContext() throws Exception { - if (StringUtils.hasLength(this.contextPath) && !ObjectUtils.isEmpty(this.classesToBeBound)) { - throw new IllegalArgumentException("Specify either 'contextPath' or 'classesToBeBound property'; not both"); - } - if (StringUtils.hasLength(this.contextPath)) { - return createJaxbContextFromContextPath(); - } - else if (!ObjectUtils.isEmpty(this.classesToBeBound)) { - return createJaxbContextFromClasses(); - } - else { - throw new IllegalArgumentException("setting either contextPath or classesToBeBound is required"); + protected synchronized JAXBContext getJaxbContext() { + if (this.jaxbContext == null) { + try { + if (StringUtils.hasLength(this.contextPath)) { + this.jaxbContext = createJaxbContextFromContextPath(); + } + else if (!ObjectUtils.isEmpty(this.classesToBeBound)) { + this.jaxbContext = createJaxbContextFromClasses(); + } + } + catch (JAXBException ex) { + throw convertJaxbException(ex); + } } + return jaxbContext; } private JAXBContext createJaxbContextFromContextPath() throws JAXBException { @@ -364,7 +388,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl return false; } - // Marshalling public void marshal(Object graph, Result result) throws XmlMappingException { @@ -410,7 +433,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl */ protected Marshaller createMarshaller() { try { - Marshaller marshaller = this.jaxbContext.createMarshaller(); + Marshaller marshaller = getJaxbContext().createMarshaller(); initJaxbMarshaller(marshaller); return marshaller; } @@ -495,7 +518,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl */ protected Unmarshaller createUnmarshaller() { try { - Unmarshaller unmarshaller = this.jaxbContext.createUnmarshaller(); + Unmarshaller unmarshaller = getJaxbContext().createUnmarshaller(); initJaxbUnmarshaller(unmarshaller); return unmarshaller; } @@ -557,7 +580,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl } } - private static class Jaxb2AttachmentMarshaller extends AttachmentMarshaller { private final MimeContainer mimeContainer; diff --git a/org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java b/org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java index c715f7ee912..963de2d6cef 100644 --- a/org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java +++ b/org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java @@ -21,13 +21,13 @@ import java.lang.reflect.Method; import java.util.Collections; import javax.activation.DataHandler; import javax.activation.FileDataSource; -import javax.xml.bind.JAXBException; import javax.xml.transform.Result; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamResult; +import static org.custommonkey.xmlunit.XMLAssert.*; import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; import org.junit.Test; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -37,6 +37,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.oxm.AbstractMarshallerTests; import org.springframework.oxm.Marshaller; +import org.springframework.oxm.UncategorizedMappingException; import org.springframework.oxm.XmlMappingException; import org.springframework.oxm.jaxb.test.FlightType; import org.springframework.oxm.jaxb.test.Flights; @@ -94,6 +95,18 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests { verify(handlerMock); } + @Test + public void laxyInit() throws Exception { + marshaller = new Jaxb2Marshaller(); + marshaller.setContextPath(CONTEXT_PATH); + marshaller.setLazyInit(true); + marshaller.afterPropertiesSet(); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + marshaller.marshal(flights, result); + assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString()); + } + @Test public void properties() throws Exception { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); @@ -110,7 +123,7 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests { marshaller.afterPropertiesSet(); } - @Test(expected = JAXBException.class) + @Test(expected = UncategorizedMappingException.class) public void testInvalidContextPath() throws Exception { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath("ab");