Browse Source

Merge pull request #474 from sdeleuze/SPR-11488

pull/466/merge
Rossen Stoyanchev 11 years ago
parent
commit
3786993eb0
  1. 30
      spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java
  2. 3
      spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java
  3. 115
      spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java

30
spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,7 +47,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
protected final Marshaller createMarshaller(Class<?> clazz) { protected final Marshaller createMarshaller(Class<?> clazz) {
try { try {
JAXBContext jaxbContext = getJaxbContext(clazz); JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createMarshaller(); Marshaller marshaller = jaxbContext.createMarshaller();
customizeMarshaller(marshaller);
return marshaller;
} }
catch (JAXBException ex) { catch (JAXBException ex) {
throw new HttpMessageConversionException( throw new HttpMessageConversionException(
@ -55,6 +57,16 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
} }
} }
/**
* Customize the {@link Marshaller} created by this
* message converter before using it to write the object to the output.
* @param marshaller the marshaller to customize
* @see #createMarshaller(Class)
* @since 4.0.3
*/
protected void customizeMarshaller(Marshaller marshaller) {
}
/** /**
* Create a new {@link Unmarshaller} for the given class. * Create a new {@link Unmarshaller} for the given class.
* @param clazz the class to create the unmarshaller for * @param clazz the class to create the unmarshaller for
@ -64,7 +76,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
protected final Unmarshaller createUnmarshaller(Class<?> clazz) throws JAXBException { protected final Unmarshaller createUnmarshaller(Class<?> clazz) throws JAXBException {
try { try {
JAXBContext jaxbContext = getJaxbContext(clazz); JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller(); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
customizeUnmarshaller(unmarshaller);
return unmarshaller;
} }
catch (JAXBException ex) { catch (JAXBException ex) {
throw new HttpMessageConversionException( throw new HttpMessageConversionException(
@ -72,6 +86,16 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
} }
} }
/**
* Customize the {@link Unmarshaller} created by this
* message converter before using it to read the object from the input.
* @param unmarshaller the unmarshaller to customize
* @see #createUnmarshaller(Class)
* @since 4.0.3
*/
protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
}
/** /**
* Return a {@link JAXBContext} for the given class. * Return a {@link JAXBContext} for the given class.
* @param clazz the class to return the context for * @param clazz the class to return the context for

3
spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java

@ -28,7 +28,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlType;
import javax.xml.transform.Result; import javax.xml.transform.Result;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource; import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamSource;
@ -39,7 +38,6 @@ import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.xml.StaxUtils;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.XMLReader; import org.xml.sax.XMLReader;
@ -53,6 +51,7 @@ import org.xml.sax.helpers.XMLReaderFactory;
* annotated with with {@link XmlRootElement}, or subclasses thereof. * annotated with with {@link XmlRootElement}, or subclasses thereof.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sebastien Deleuze
* @since 3.0 * @since 3.0
*/ */
public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> { public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> {

115
spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java

@ -17,15 +17,20 @@
package org.springframework.http.converter.xml; package org.springframework.http.converter.xml;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import static org.custommonkey.xmlunit.XMLAssert.*; import static org.custommonkey.xmlunit.XMLAssert.*;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -37,10 +42,13 @@ import org.springframework.core.io.Resource;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.MockHttpInputMessage; import org.springframework.http.MockHttpInputMessage;
import org.springframework.http.MockHttpOutputMessage; import org.springframework.http.MockHttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.xml.sax.SAXParseException;
/** @author Arjen Poutsma */ /**
* Tests for {@link Jaxb2RootElementHttpMessageConverter}.
*
* @author Arjen Poutsma
* @author Sebastien Deleuze
*/
public class Jaxb2RootElementHttpMessageConverterTests { public class Jaxb2RootElementHttpMessageConverterTests {
private Jaxb2RootElementHttpMessageConverter converter; private Jaxb2RootElementHttpMessageConverter converter;
@ -146,6 +154,27 @@ public class Jaxb2RootElementHttpMessageConverterTests {
outputMessage.getBodyAsString(Charset.forName("UTF-8"))); outputMessage.getBodyAsString(Charset.forName("UTF-8")));
} }
// SPR-11488
@Test
public void customizeMarshaller() throws Exception {
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
MyJaxb2RootElementHttpMessageConverter myConverter = new MyJaxb2RootElementHttpMessageConverter();
myConverter.write(new MyRootElement(new MyCustomElement("a", "b")), null, outputMessage);
assertXMLEqual("Invalid result", "<myRootElement><element>a|||b</element></myRootElement>",
outputMessage.getBodyAsString(Charset.forName("UTF-8")));
}
@Test
public void customizeUnmarshaller() throws Exception {
byte[] body = "<myRootElement><element>a|||b</element></myRootElement>".getBytes("UTF-8");
MyJaxb2RootElementHttpMessageConverter myConverter = new MyJaxb2RootElementHttpMessageConverter();
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body);
MyRootElement result = (MyRootElement) myConverter.read(MyRootElement.class, inputMessage);
assertEquals("a", result.getElement().getField1());
assertEquals("b", result.getElement().getField2());
}
@XmlRootElement @XmlRootElement
public static class RootElement { public static class RootElement {
@ -176,4 +205,84 @@ public class Jaxb2RootElementHttpMessageConverterTests {
} }
public static class MyJaxb2RootElementHttpMessageConverter extends Jaxb2RootElementHttpMessageConverter {
@Override
protected void customizeMarshaller(Marshaller marshaller) {
marshaller.setAdapter(new MyCustomElementAdapter());
}
@Override
protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
unmarshaller.setAdapter(new MyCustomElementAdapter());
}
}
public static class MyCustomElement {
private String field1;
private String field2;
public MyCustomElement() {
}
public MyCustomElement(String field1, String field2) {
this.field1 = field1;
this.field2 = field2;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
}
@XmlRootElement
public static class MyRootElement {
private MyCustomElement element;
public MyRootElement() {
}
public MyRootElement(MyCustomElement element) {
this.element = element;
}
@XmlJavaTypeAdapter(MyCustomElementAdapter.class)
public MyCustomElement getElement() {
return element;
}
public void setElement(MyCustomElement element) {
this.element = element;
}
}
public static class MyCustomElementAdapter extends XmlAdapter<String, MyCustomElement> {
@Override
public String marshal(MyCustomElement c) throws Exception {
return c.getField1() + "|||" + c.getField2();
}
@Override
public MyCustomElement unmarshal(String c) throws Exception {
String[] t = c.split("\\|\\|\\|");
return new MyCustomElement(t[0], t[1]);
}
}
} }

Loading…
Cancel
Save