diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java index 189bf9b218..2a0868549d 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * 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. @@ -17,11 +17,13 @@ package org.springframework.http.converter.xml; import java.io.IOException; + import javax.xml.transform.Result; import javax.xml.transform.Source; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.oxm.Marshaller; @@ -103,10 +105,20 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve this.unmarshaller = unmarshaller; } + @Override + public boolean canRead(Class clazz, MediaType mediaType) { + return canRead(mediaType) && (this.unmarshaller != null) && this.unmarshaller.supports(clazz); + } @Override - public boolean supports(Class clazz) { - return this.unmarshaller.supports(clazz); + public boolean canWrite(Class clazz, MediaType mediaType) { + return canWrite(mediaType) && (this.marshaller != null) && this.marshaller.supports(clazz); + } + + @Override + protected boolean supports(Class clazz) { + // should not be called, since we override canRead()/canWrite() + throw new UnsupportedOperationException(); } @Override @@ -134,5 +146,4 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex); } } - } diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java index 75de8e4019..ab016f5ae6 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java @@ -16,36 +16,60 @@ package org.springframework.http.converter.xml; -import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.Result; import javax.xml.transform.stream.StreamSource; -import org.junit.Before; import org.junit.Test; +import org.springframework.beans.TypeMismatchException; import org.springframework.http.MediaType; import org.springframework.http.MockHttpInputMessage; import org.springframework.http.MockHttpOutputMessage; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.oxm.Marshaller; +import org.springframework.oxm.MarshallingFailureException; import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.UnmarshallingFailureException; import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; /** + * Tests for {@link MarshallingHttpMessageConverter}. + * * @author Arjen Poutsma */ public class MarshallingHttpMessageConverterTests { - private MarshallingHttpMessageConverter converter; + @Test + public void canRead() throws Exception { + Unmarshaller unmarshaller = mock(Unmarshaller.class); - private Marshaller marshaller; + when(unmarshaller.supports(Integer.class)).thenReturn(false); + when(unmarshaller.supports(String.class)).thenReturn(true); - private Unmarshaller unmarshaller; + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(); + converter.setUnmarshaller(unmarshaller); - @Before - public void setUp() { - marshaller = mock(Marshaller.class); - unmarshaller = mock(Unmarshaller.class); - converter = new MarshallingHttpMessageConverter(marshaller, unmarshaller); + assertFalse(converter.canRead(Boolean.class, MediaType.TEXT_PLAIN)); + assertFalse(converter.canRead(Integer.class, MediaType.TEXT_XML)); + assertTrue(converter.canRead(String.class, MediaType.TEXT_XML)); + } + + @Test + public void canWrite() throws Exception { + Marshaller marshaller = mock(Marshaller.class); + + when(marshaller.supports(Integer.class)).thenReturn(false); + when(marshaller.supports(String.class)).thenReturn(true); + + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(); + converter.setMarshaller(marshaller); + + assertFalse(converter.canWrite(Boolean.class, MediaType.TEXT_PLAIN)); + assertFalse(converter.canWrite(Integer.class, MediaType.TEXT_XML)); + assertTrue(converter.canWrite(String.class, MediaType.TEXT_XML)); } @Test @@ -53,20 +77,84 @@ public class MarshallingHttpMessageConverterTests { String body = "Hello World"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); - given(unmarshaller.unmarshal(isA(StreamSource.class))).willReturn(body); + Unmarshaller unmarshaller = mock(Unmarshaller.class); + when(unmarshaller.unmarshal(isA(StreamSource.class))).thenReturn(body); + + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(); + converter.setUnmarshaller(unmarshaller); String result = (String) converter.read(Object.class, inputMessage); assertEquals("Invalid result", body, result); } + @Test(expected = TypeMismatchException.class) + public void readWithTypeMismatchException() throws Exception { + MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]); + + Marshaller marshaller = mock(Marshaller.class); + Unmarshaller unmarshaller = mock(Unmarshaller.class); + when(unmarshaller.unmarshal(isA(StreamSource.class))).thenReturn(Integer.valueOf(3)); + + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller, unmarshaller); + converter.read(String.class, inputMessage); + } + + @Test + public void readWithMarshallingFailureException() throws Exception { + MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]); + UnmarshallingFailureException ex = new UnmarshallingFailureException("forced"); + + Unmarshaller unmarshaller = mock(Unmarshaller.class); + when(unmarshaller.unmarshal(isA(StreamSource.class))).thenThrow(ex); + + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(); + converter.setUnmarshaller(unmarshaller); + + try { + converter.read(Object.class, inputMessage); + fail("HttpMessageNotReadableException should be thrown"); + } + catch (HttpMessageNotReadableException e) { + assertTrue("Invalid exception hierarchy", e.getCause() == ex); + } + } + @Test public void write() throws Exception { String body = "Hello World"; MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); + Marshaller marshaller = mock(Marshaller.class); + doNothing().when(marshaller).marshal(eq(body), isA(Result.class)); + + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); converter.write(body, null, outputMessage); - assertEquals("Invalid content-type", new MediaType("application", "xml"), - outputMessage.getHeaders().getContentType()); - verify(marshaller).marshal(eq(body), isA(StreamResult.class)); + + assertEquals("Invalid content-type", new MediaType("application", "xml"), outputMessage.getHeaders() + .getContentType()); + } + + @Test + public void writeWithMarshallingFailureException() throws Exception { + String body = "Hello World"; + MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); + MarshallingFailureException ex = new MarshallingFailureException("forced"); + + Marshaller marshaller = mock(Marshaller.class); + doThrow(ex).when(marshaller).marshal(eq(body), isA(Result.class)); + + try { + MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); + converter.write(body, null, outputMessage); + fail("HttpMessageNotWritableException should be thrown"); + } + catch (HttpMessageNotWritableException e) { + assertTrue("Invalid exception hierarchy", e.getCause() == ex); + } + } + + @Test(expected = UnsupportedOperationException.class) + public void supports() throws Exception { + new MarshallingHttpMessageConverter().supports(Object.class); } }