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 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -47,7 +47,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt @@ -47,7 +47,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
protected final Marshaller createMarshaller(Class<?> clazz) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createMarshaller();
Marshaller marshaller = jaxbContext.createMarshaller();
customizeMarshaller(marshaller);
return marshaller;
}
catch (JAXBException ex) {
throw new HttpMessageConversionException(
@ -55,6 +57,16 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt @@ -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.
* @param clazz the class to create the unmarshaller for
@ -64,7 +76,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt @@ -64,7 +76,9 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt
protected final Unmarshaller createUnmarshaller(Class<?> clazz) throws JAXBException {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller();
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
customizeUnmarshaller(unmarshaller);
return unmarshaller;
}
catch (JAXBException ex) {
throw new HttpMessageConversionException(
@ -72,6 +86,16 @@ public abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractXmlHt @@ -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.
* @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; @@ -28,7 +28,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
@ -39,7 +38,6 @@ import org.springframework.http.converter.HttpMessageConversionException; @@ -39,7 +38,6 @@ import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.ClassUtils;
import org.springframework.util.xml.StaxUtils;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@ -53,6 +51,7 @@ import org.xml.sax.helpers.XMLReaderFactory; @@ -53,6 +51,7 @@ import org.xml.sax.helpers.XMLReaderFactory;
* annotated with with {@link XmlRootElement}, or subclasses thereof.
*
* @author Arjen Poutsma
* @author Sebastien Deleuze
* @since 3.0
*/
public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> {

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

@ -17,15 +17,20 @@ @@ -17,15 +17,20 @@
package org.springframework.http.converter.xml;
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.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
@ -37,10 +42,13 @@ import org.springframework.core.io.Resource; @@ -37,10 +42,13 @@ import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.MockHttpInputMessage;
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 {
private Jaxb2RootElementHttpMessageConverter converter;
@ -146,6 +154,27 @@ public class Jaxb2RootElementHttpMessageConverterTests { @@ -146,6 +154,27 @@ public class Jaxb2RootElementHttpMessageConverterTests {
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
public static class RootElement {
@ -176,4 +205,84 @@ public class Jaxb2RootElementHttpMessageConverterTests { @@ -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