diff --git a/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java b/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java index 4d2f16da7..bda6f47e0 100644 --- a/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java +++ b/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java @@ -113,22 +113,32 @@ public class ProjectingJackson2HttpMessageConverter extends MappingJackson2HttpM @Override public boolean canRead(Type type, Class contextClass, MediaType mediaType) { - Class rawType = ResolvableType.forType(type).getRawClass(); + if (!canRead(mediaType)) { + return false; + } + Class rawType = ResolvableType.forType(type).getRawClass(); Boolean result = supportedTypesCache.get(rawType); if (result != null) { return result; } - result = canRead(mediaType) && rawType.isInterface() - && AnnotationUtils.findAnnotation(rawType, ProjectedPayload.class) != null; - + result = rawType.isInterface() && AnnotationUtils.findAnnotation(rawType, ProjectedPayload.class) != null; supportedTypesCache.put(rawType, result); return result; } + /* + * (non-Javadoc) + * @see org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#canWrite(java.lang.Class, org.springframework.http.MediaType) + */ + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + return false; + } + /* * (non-Javadoc) * @see org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#read(java.lang.reflect.Type, java.lang.Class, org.springframework.http.HttpInputMessage) diff --git a/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java b/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java index 8fc17bcc7..9704232b8 100644 --- a/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java +++ b/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java @@ -16,8 +16,6 @@ package org.springframework.data.web; import java.io.IOException; -import java.util.Collections; -import java.util.List; import java.util.Map; import org.springframework.core.ResolvableType; @@ -25,6 +23,7 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; @@ -39,7 +38,7 @@ import org.xmlbeam.XBProjector; * @see http://www.xmlbeam.org * @soundtrack Dr. Kobayashi Maru & The Mothership Connection - Anthem (EPisode One) */ -public class XmlBeamHttpMessageConverter implements HttpMessageConverter { +public class XmlBeamHttpMessageConverter extends AbstractHttpMessageConverter { private final ProjectionFactory projectionFactory; private final Map, Boolean> supportedTypesCache = new ConcurrentReferenceHashMap, Boolean>(); @@ -48,26 +47,27 @@ public class XmlBeamHttpMessageConverter implements HttpMessageConverter * Creates a new {@link XmlBeamHttpMessageConverter}. */ public XmlBeamHttpMessageConverter() { + + super(MediaType.APPLICATION_XML, MediaType.parseMediaType("application/*+xml")); + this.projectionFactory = new XBProjector(); } - /* + /* * (non-Javadoc) - * @see org.springframework.http.converter.HttpMessageConverter#canRead(java.lang.Class, org.springframework.http.MediaType) + * @see org.springframework.http.converter.AbstractHttpMessageConverter#supports(java.lang.Class) */ @Override - public boolean canRead(Class type, MediaType mediaType) { + protected boolean supports(Class type) { Class rawType = ResolvableType.forType(type).getRawClass(); - Boolean result = supportedTypesCache.get(rawType); if (result != null) { return result; } - result = mediaType.isCompatibleWith(MediaType.APPLICATION_XML) && rawType.isInterface() - && AnnotationUtils.findAnnotation(rawType, ProjectedPayload.class) != null; + result = rawType.isInterface() && AnnotationUtils.findAnnotation(rawType, ProjectedPayload.class) != null; supportedTypesCache.put(rawType, result); @@ -85,28 +85,19 @@ public class XmlBeamHttpMessageConverter implements HttpMessageConverter /* * (non-Javadoc) - * @see org.springframework.http.converter.HttpMessageConverter#getSupportedMediaTypes() + * @see org.springframework.http.converter.AbstractHttpMessageConverter#readInternal(java.lang.Class, org.springframework.http.HttpInputMessage) */ @Override - public List getSupportedMediaTypes() { - return Collections.singletonList(MediaType.APPLICATION_XML); - } - - /* - * (non-Javadoc) - * @see org.springframework.http.converter.HttpMessageConverter#read(java.lang.Class, org.springframework.http.HttpInputMessage) - */ - @Override - public Object read(Class clazz, HttpInputMessage inputMessage) + protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return projectionFactory.io().stream(inputMessage.getBody()).read(clazz); } /* * (non-Javadoc) - * @see org.springframework.http.converter.HttpMessageConverter#write(java.lang.Object, org.springframework.http.MediaType, org.springframework.http.HttpOutputMessage) + * @see org.springframework.http.converter.AbstractHttpMessageConverter#writeInternal(java.lang.Object, org.springframework.http.HttpOutputMessage) */ @Override - public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) + protected void writeInternal(Object t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {} } diff --git a/src/test/java/org/springframework/data/web/XmlBeamHttpMessageConverterUnitTests.java b/src/test/java/org/springframework/data/web/XmlBeamHttpMessageConverterUnitTests.java index 957bfee56..37d81214e 100644 --- a/src/test/java/org/springframework/data/web/XmlBeamHttpMessageConverterUnitTests.java +++ b/src/test/java/org/springframework/data/web/XmlBeamHttpMessageConverterUnitTests.java @@ -26,7 +26,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.web.ProjectingJackson2HttpMessageConverterUnitTests.UnannotatedInterface; import org.springframework.http.HttpInputMessage; +import org.springframework.http.MediaType; import org.xmlbeam.annotation.XBRead; /** @@ -70,10 +72,45 @@ public class XmlBeamHttpMessageConverterUnitTests { assertThat(customer.getLastname(), is("Matthews")); } + /** + * @see DATACMNS-885 + */ + @Test + public void supportsAnnotatedInterface() { + assertThat(converter.canRead(Customer.class, MediaType.APPLICATION_XML), is(true)); + } + + /** + * @see DATACMNS-885 + */ + @Test + public void supportsXmlBasedMediaType() { + assertThat(converter.canRead(Customer.class, MediaType.APPLICATION_ATOM_XML), is(true)); + } + + /** + * @see DATACMNS-885 + */ + @Test + public void doesNotSupportUnannotatedInterface() { + assertThat(converter.canRead(UnannotatedInterface.class, MediaType.APPLICATION_XML), is(false)); + } + + /** + * @see DATACMNS-885 + */ + @Test + public void supportsInterfaceAfterLookupForDifferrentMediaType() { + + assertThat(converter.canRead(Customer.class, MediaType.APPLICATION_JSON), is(false)); + assertThat(converter.canRead(Customer.class, MediaType.APPLICATION_XML), is(true)); + } + private void preparePayload(String payload) throws IOException { when(message.getBody()).thenReturn(new ByteArrayInputStream(payload.getBytes())); } + @ProjectedPayload public interface Customer { @XBRead("//firstname") @@ -82,4 +119,6 @@ public class XmlBeamHttpMessageConverterUnitTests { @XBRead("//lastname") String getLastname(); } + + public interface UnnannotatedInterface {} }