SPR-5745 - Support lazy initialization within Jaxb2 OXM classes

This commit is contained in:
Arjen Poutsma 2009-06-11 09:20:29 +00:00
parent 1dc346a32c
commit 58d3e704bf
2 changed files with 55 additions and 20 deletions

View File

@ -140,6 +140,8 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
private Schema schema; private Schema schema;
private boolean lazyInit = false;
/** /**
* Set a JAXB context path. * Set a JAXB context path.
@ -259,31 +261,53 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
this.mtomEnabled = mtomEnabled; 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}.
* <p>Early initialization just applies if <code>afterPropertiesSet()</code> is called.
* @see #afterPropertiesSet()
*/
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}
public void setBeanClassLoader(ClassLoader classLoader) { public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader; this.beanClassLoader = classLoader;
} }
public final void afterPropertiesSet() throws Exception { 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)) { if (!ObjectUtils.isEmpty(this.schemaResources)) {
this.schema = loadSchema(this.schemaResources, this.schemaLanguage); this.schema = loadSchema(this.schemaResources, this.schemaLanguage);
} }
} }
protected JAXBContext createJaxbContext() throws Exception { protected synchronized JAXBContext getJaxbContext() {
if (StringUtils.hasLength(this.contextPath) && !ObjectUtils.isEmpty(this.classesToBeBound)) { if (this.jaxbContext == null) {
throw new IllegalArgumentException("Specify either 'contextPath' or 'classesToBeBound property'; not both"); try {
} if (StringUtils.hasLength(this.contextPath)) {
if (StringUtils.hasLength(this.contextPath)) { this.jaxbContext = createJaxbContextFromContextPath();
return createJaxbContextFromContextPath(); }
} else if (!ObjectUtils.isEmpty(this.classesToBeBound)) {
else if (!ObjectUtils.isEmpty(this.classesToBeBound)) { this.jaxbContext = createJaxbContextFromClasses();
return createJaxbContextFromClasses(); }
} }
else { catch (JAXBException ex) {
throw new IllegalArgumentException("setting either contextPath or classesToBeBound is required"); throw convertJaxbException(ex);
}
} }
return jaxbContext;
} }
private JAXBContext createJaxbContextFromContextPath() throws JAXBException { private JAXBContext createJaxbContextFromContextPath() throws JAXBException {
@ -364,7 +388,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
return false; return false;
} }
// Marshalling // Marshalling
public void marshal(Object graph, Result result) throws XmlMappingException { public void marshal(Object graph, Result result) throws XmlMappingException {
@ -410,7 +433,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
*/ */
protected Marshaller createMarshaller() { protected Marshaller createMarshaller() {
try { try {
Marshaller marshaller = this.jaxbContext.createMarshaller(); Marshaller marshaller = getJaxbContext().createMarshaller();
initJaxbMarshaller(marshaller); initJaxbMarshaller(marshaller);
return marshaller; return marshaller;
} }
@ -495,7 +518,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
*/ */
protected Unmarshaller createUnmarshaller() { protected Unmarshaller createUnmarshaller() {
try { try {
Unmarshaller unmarshaller = this.jaxbContext.createUnmarshaller(); Unmarshaller unmarshaller = getJaxbContext().createUnmarshaller();
initJaxbUnmarshaller(unmarshaller); initJaxbUnmarshaller(unmarshaller);
return unmarshaller; return unmarshaller;
} }
@ -557,7 +580,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
} }
} }
private static class Jaxb2AttachmentMarshaller extends AttachmentMarshaller { private static class Jaxb2AttachmentMarshaller extends AttachmentMarshaller {
private final MimeContainer mimeContainer; private final MimeContainer mimeContainer;

View File

@ -21,13 +21,13 @@ import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import javax.activation.DataHandler; import javax.activation.DataHandler;
import javax.activation.FileDataSource; import javax.activation.FileDataSource;
import javax.xml.bind.JAXBException;
import javax.xml.transform.Result; import javax.xml.transform.Result;
import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import static org.custommonkey.xmlunit.XMLAssert.*;
import static org.easymock.EasyMock.*; import static org.easymock.EasyMock.*;
import static org.junit.Assert.*; import static org.junit.Assert.assertTrue;
import org.junit.Test; import org.junit.Test;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler; import org.xml.sax.ContentHandler;
@ -37,6 +37,7 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.oxm.AbstractMarshallerTests; import org.springframework.oxm.AbstractMarshallerTests;
import org.springframework.oxm.Marshaller; import org.springframework.oxm.Marshaller;
import org.springframework.oxm.UncategorizedMappingException;
import org.springframework.oxm.XmlMappingException; import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.jaxb.test.FlightType; import org.springframework.oxm.jaxb.test.FlightType;
import org.springframework.oxm.jaxb.test.Flights; import org.springframework.oxm.jaxb.test.Flights;
@ -94,6 +95,18 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
verify(handlerMock); 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 @Test
public void properties() throws Exception { public void properties() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
@ -110,7 +123,7 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
marshaller.afterPropertiesSet(); marshaller.afterPropertiesSet();
} }
@Test(expected = JAXBException.class) @Test(expected = UncategorizedMappingException.class)
public void testInvalidContextPath() throws Exception { public void testInvalidContextPath() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("ab"); marshaller.setContextPath("ab");