diff --git a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/ClassPathJaxb2TypeScanner.java b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/ClassPathJaxb2TypeScanner.java index 368655356b..f3047013a6 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/ClassPathJaxb2TypeScanner.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/ClassPathJaxb2TypeScanner.java @@ -19,7 +19,9 @@ package org.springframework.oxm.jaxb; import java.io.IOException; import java.util.ArrayList; import java.util.List; + import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlRegistry; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; @@ -42,6 +44,7 @@ import org.springframework.util.ClassUtils; * @author Arjen Poutsma * @author Juergen Hoeller * @author David Harrigan + * @author Biju Kunjummen * @since 3.1.1 * @see #scanPackages() */ @@ -50,8 +53,11 @@ class ClassPathJaxb2TypeScanner { private static final String RESOURCE_PATTERN = "/**/*.class"; private static final TypeFilter[] JAXB2_TYPE_FILTERS = new TypeFilter[] { - new AnnotationTypeFilter(XmlRootElement.class, false), new AnnotationTypeFilter(XmlType.class, false), - new AnnotationTypeFilter(XmlSeeAlso.class, false), new AnnotationTypeFilter(XmlEnum.class, false)}; + new AnnotationTypeFilter(XmlRootElement.class, false), + new AnnotationTypeFilter(XmlType.class, false), + new AnnotationTypeFilter(XmlSeeAlso.class, false), + new AnnotationTypeFilter(XmlEnum.class, false), + new AnnotationTypeFilter(XmlRegistry.class, false)}; private final ResourcePatternResolver resourcePatternResolver; diff --git a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Airplane.java b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Airplane.java new file mode 100644 index 0000000000..bc0060b0f4 --- /dev/null +++ b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Airplane.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.oxm.jaxb; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Airplane { + + private String name; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java index aa3eca0777..bd75b70adb 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java @@ -51,10 +51,15 @@ import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; -import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + import static org.junit.Assert.*; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; import static org.mockito.BDDMockito.*; +/** + * @author Arjen Poutsma + * @author Biju Kunjummen + */ public class Jaxb2MarshallerTests extends AbstractMarshallerTests { private static final String CONTEXT_PATH = "org.springframework.oxm.jaxb.test"; @@ -281,6 +286,21 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests { verify(mimeContainer, times(3)).addAttachment(isA(String.class), isA(DataHandler.class)); } + @Test + public void marshalAWrappedObjectHoldingAnXmlElementDeclElement() throws Exception { + // SPR-10714 + marshaller = new Jaxb2Marshaller(); + marshaller.setPackagesToScan(new String[] { "org.springframework.oxm.jaxb" }); + marshaller.afterPropertiesSet(); + Airplane airplane = new Airplane(); + airplane.setName("test"); + StringWriter writer = new StringWriter(); + Result result = new StreamResult(writer); + marshaller.marshal(airplane, result); + assertXMLEqual("Marshalling should use root Element", + writer.toString(), "test"); + } + @XmlRootElement @SuppressWarnings("unused") public static class DummyRootElement { diff --git a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2UnmarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2UnmarshallerTests.java index 55a3f8d226..04842a7366 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2UnmarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2UnmarshallerTests.java @@ -39,6 +39,10 @@ import org.springframework.util.xml.StaxUtils; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; +/** + * @author Arjen Poutsma + * @author Biju Kunjummen + */ public class Jaxb2UnmarshallerTests extends AbstractUnmarshallerTests { private static final String INPUT_STRING = "" + @@ -104,6 +108,7 @@ public class Jaxb2UnmarshallerTests extends AbstractUnmarshallerTests { @Test @Override + @SuppressWarnings("unchecked") public void unmarshalPartialStaxSourceXmlStreamReader() throws Exception { XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING)); @@ -115,5 +120,18 @@ public class Jaxb2UnmarshallerTests extends AbstractUnmarshallerTests { testFlight(flight); } + @Test + @SuppressWarnings("unchecked") + public void unmarshalAnXmlReferingToAWrappedXmlElementDecl() throws Exception { + // SPR-10714 + unmarshaller = new Jaxb2Marshaller(); + unmarshaller.setPackagesToScan(new String[] { "org.springframework.oxm.jaxb" }); + unmarshaller.afterPropertiesSet(); + Source source = new StreamSource(new StringReader( + "test")); + JAXBElement airplane = (JAXBElement) unmarshaller.unmarshal(source); + assertEquals("Unmarshalling via explicit @XmlRegistry tag should return correct type", + "test", airplane.getValue().getName()); + } } diff --git a/spring-oxm/src/test/java/org/springframework/oxm/jaxb/XmlRegObjectFactory.java b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/XmlRegObjectFactory.java new file mode 100644 index 0000000000..a3f6c702af --- /dev/null +++ b/spring-oxm/src/test/java/org/springframework/oxm/jaxb/XmlRegObjectFactory.java @@ -0,0 +1,16 @@ + +package org.springframework.oxm.jaxb; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + +@XmlRegistry +public class XmlRegObjectFactory { + + @XmlElementDecl(name = "brand-airplane") + public JAXBElement createAirplane(Airplane airplane) { + return new JAXBElement(new QName("brand-airplane"), Airplane.class, null, airplane); + } +} \ No newline at end of file