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");