Browse Source

Revised MappingJackson2MessageConverter towards var-arg constructor

Issue: SPR-12724
pull/739/head
Juergen Hoeller 10 years ago
parent
commit
8716129058
  1. 79
      spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java
  2. 30
      spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java
  3. 12
      spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java

79
spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 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.
@ -32,10 +32,10 @@ import org.springframework.util.Assert;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
/** /**
* Abstract base class for {@link MessageConverter} implementations including support for * Abstract base class for {@link MessageConverter} implementations including support
* common properties and a partial implementation of the conversion methods mainly to * for common properties and a partial implementation of the conversion methods,
* check if the converter supports the conversion based on the payload class and MIME * mainly to check if the converter supports the conversion based on the payload class
* type. * and MIME type.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 4.0 * @since 4.0
@ -68,7 +68,7 @@ public abstract class AbstractMessageConverter implements MessageConverter {
* @param supportedMimeTypes the supported MIME types * @param supportedMimeTypes the supported MIME types
*/ */
protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) { protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) {
Assert.notNull(supportedMimeTypes, "SupportedMimeTypes must not be null"); Assert.notNull(supportedMimeTypes, "supportedMimeTypes must not be null");
this.supportedMimeTypes = new ArrayList<MimeType>(supportedMimeTypes); this.supportedMimeTypes = new ArrayList<MimeType>(supportedMimeTypes);
} }
@ -83,13 +83,11 @@ public abstract class AbstractMessageConverter implements MessageConverter {
/** /**
* Configure the {@link ContentTypeResolver} to use to resolve the content * Configure the {@link ContentTypeResolver} to use to resolve the content
* type of an input message. * type of an input message.
* <p> * <p>Note that if no resolver is configured, then
* Note that if no resolver is configured, then
* {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should * {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should
* be left as {@code false} (the default) or otherwise this converter will * be left as {@code false} (the default) or otherwise this converter will
* ignore all messages. * ignore all messages.
* <p> * <p>By default, a {@code DefaultContentTypeResolver} instance is used.
* By default, a {@code DefaultContentTypeResolver} instance is used.
*/ */
public void setContentTypeResolver(ContentTypeResolver resolver) { public void setContentTypeResolver(ContentTypeResolver resolver) {
this.contentTypeResolver = resolver; this.contentTypeResolver = resolver;
@ -106,20 +104,17 @@ public abstract class AbstractMessageConverter implements MessageConverter {
* Whether this converter should convert messages for which no content type * Whether this converter should convert messages for which no content type
* could be resolved through the configured * could be resolved through the configured
* {@link org.springframework.messaging.converter.ContentTypeResolver}. * {@link org.springframework.messaging.converter.ContentTypeResolver}.
* A converter can configured to be strict only when a * <p>A converter can configured to be strict only when a
* {@link #setContentTypeResolver(ContentTypeResolver) contentTypeResolver} * {@link #setContentTypeResolver contentTypeResolver} is configured and the
* is configured and the list of {@link #getSupportedMimeTypes() supportedMimeTypes} * list of {@link #getSupportedMimeTypes() supportedMimeTypes} is not be empty.
* is not be empty. * <p>When this flag is set to {@code true}, {@link #supportsMimeType(MessageHeaders)}
* * will return {@code false} if the {@link #setContentTypeResolver contentTypeResolver}
* then requires the content type of a message to be resolved * is not defined or if no content-type header is present.
*
* When set to true, #supportsMimeType(MessageHeaders) will return false if the
* contentTypeResolver is not defined or if no content-type header is present.
*/ */
public void setStrictContentTypeMatch(boolean strictContentTypeMatch) { public void setStrictContentTypeMatch(boolean strictContentTypeMatch) {
if (strictContentTypeMatch) { if (strictContentTypeMatch) {
Assert.notEmpty(getSupportedMimeTypes(), "Strict match requires non-empty list of supported mime types."); Assert.notEmpty(getSupportedMimeTypes(), "Strict match requires non-empty list of supported mime types");
Assert.notNull(getContentTypeResolver(), "Strict match requires ContentTypeResolver."); Assert.notNull(getContentTypeResolver(), "Strict match requires ContentTypeResolver");
} }
this.strictContentTypeMatch = strictContentTypeMatch; this.strictContentTypeMatch = strictContentTypeMatch;
} }
@ -166,14 +161,6 @@ public abstract class AbstractMessageConverter implements MessageConverter {
return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null); return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null);
} }
/**
* Whether the given class is supported by this converter.
* @param clazz the class to test for support
* @return {@code true} if supported; {@code false} otherwise
*/
protected abstract boolean supports(Class<?> clazz);
@Override @Override
public final Object fromMessage(Message<?> message, Class<?> targetClass) { public final Object fromMessage(Message<?> message, Class<?> targetClass) {
if (!canConvertFrom(message, targetClass)) { if (!canConvertFrom(message, targetClass)) {
@ -186,14 +173,8 @@ public abstract class AbstractMessageConverter implements MessageConverter {
return (supports(targetClass) && supportsMimeType(message.getHeaders())); return (supports(targetClass) && supportsMimeType(message.getHeaders()));
} }
/**
* Convert the message payload from serialized form to an Object.
*/
public abstract Object convertFromInternal(Message<?> message, Class<?> targetClass);
@Override @Override
public final Message<?> toMessage(Object payload, MessageHeaders headers) { public final Message<?> toMessage(Object payload, MessageHeaders headers) {
if (!canConvertTo(payload, headers)) { if (!canConvertTo(payload, headers)) {
return null; return null;
} }
@ -218,15 +199,10 @@ public abstract class AbstractMessageConverter implements MessageConverter {
} }
protected boolean canConvertTo(Object payload, MessageHeaders headers) { protected boolean canConvertTo(Object payload, MessageHeaders headers) {
Class<?> clazz = (payload != null) ? payload.getClass() : null; Class<?> clazz = (payload != null ? payload.getClass() : null);
return (supports(clazz) && supportsMimeType(headers)); return (supports(clazz) && supportsMimeType(headers));
} }
/**
* Convert the payload object to serialized form.
*/
public abstract Object convertToInternal(Object payload, MessageHeaders headers);
protected boolean supportsMimeType(MessageHeaders headers) { protected boolean supportsMimeType(MessageHeaders headers) {
if (getSupportedMimeTypes().isEmpty()) { if (getSupportedMimeTypes().isEmpty()) {
return true; return true;
@ -249,7 +225,26 @@ public abstract class AbstractMessageConverter implements MessageConverter {
} }
protected MimeType getMimeType(MessageHeaders headers) { protected MimeType getMimeType(MessageHeaders headers) {
return (this.contentTypeResolver != null) ? this.contentTypeResolver.resolve(headers) : null; return (this.contentTypeResolver != null ? this.contentTypeResolver.resolve(headers) : null);
} }
/**
* Whether the given class is supported by this converter.
* @param clazz the class to test for support
* @return {@code true} if supported; {@code false} otherwise
*/
protected abstract boolean supports(Class<?> clazz);
/**
* Convert the message payload from serialized form to an Object.
*/
public abstract Object convertFromInternal(Message<?> message, Class<?> targetClass);
/**
* Convert the payload object to serialized form.
*/
public abstract Object convertToInternal(Object payload, MessageHeaders headers);
} }

30
spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java

@ -21,7 +21,7 @@ import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Collection; import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonEncoding;
@ -68,33 +68,27 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
/** /**
* Construct a {@code MappingJackson2MessageConverter} supporting {@code application/json} MIME type. * Construct a {@code MappingJackson2MessageConverter} supporting
* the {@code application/json} MIME type.
*/ */
public MappingJackson2MessageConverter() { public MappingJackson2MessageConverter() {
this(new MimeType("application", "json", Charset.forName("UTF-8"))); super(new MimeType("application", "json", Charset.forName("UTF-8")));
initObjectMapper();
} }
/** /**
* Construct a {@code MappingJackson2MessageConverter} supporting a single MIME type. * Construct a {@code MappingJackson2MessageConverter} supporting
* @param supportedMimeType the supported MIME type * one or more custom MIME types.
* @since 4.1.5
*/
public MappingJackson2MessageConverter(MimeType supportedMimeType) {
super(supportedMimeType);
init();
}
/**
* Construct a {@code MappingJackson2MessageConverter} supporting multiple MIME types.
* @param supportedMimeTypes the supported MIME types * @param supportedMimeTypes the supported MIME types
* @since 4.1.5 * @since 4.1.5
*/ */
public MappingJackson2MessageConverter(Collection<MimeType> supportedMimeTypes) { public MappingJackson2MessageConverter(MimeType... supportedMimeTypes) {
super(supportedMimeTypes); super(Arrays.asList(supportedMimeTypes));
init(); initObjectMapper();
} }
private void init() {
private void initObjectMapper() {
this.objectMapper = new ObjectMapper(); this.objectMapper = new ObjectMapper();
this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

12
spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 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.
@ -23,7 +23,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import static org.hamcrest.Matchers.contains;
import org.junit.Test; import org.junit.Test;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
@ -31,17 +30,20 @@ import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder; import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Test fixture for {@link org.springframework.messaging.converter.MappingJackson2MessageConverter}. * Test fixture for {@link org.springframework.messaging.converter.MappingJackson2MessageConverter}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Sebastien Deleuze
*/ */
public class MappingJackson2MessageConverterTests { public class MappingJackson2MessageConverterTests {
private static Charset UTF_8 = Charset.forName("UTF-8"); private static Charset UTF_8 = Charset.forName("UTF-8");
@Test @Test
public void defaultConstructor() { public void defaultConstructor() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
@ -49,7 +51,7 @@ public class MappingJackson2MessageConverterTests {
assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
} }
@Test // SPR-12724 @Test // SPR-12724
public void mimetypeParametrizedConstructor() { public void mimetypeParametrizedConstructor() {
MimeType mimetype = new MimeType("application", "xml", UTF_8); MimeType mimetype = new MimeType("application", "xml", UTF_8);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(mimetype); MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(mimetype);
@ -57,11 +59,11 @@ public class MappingJackson2MessageConverterTests {
assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
} }
@Test // SPR-12724 @Test // SPR-12724
public void mimetypesParametrizedConstructor() { public void mimetypesParametrizedConstructor() {
MimeType jsonMimetype = new MimeType("application", "json", UTF_8); MimeType jsonMimetype = new MimeType("application", "json", UTF_8);
MimeType xmlMimetype = new MimeType("application", "xml", UTF_8); MimeType xmlMimetype = new MimeType("application", "xml", UTF_8);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(Arrays.asList(jsonMimetype, xmlMimetype)); MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(jsonMimetype, xmlMimetype);
assertThat(converter.getSupportedMimeTypes(), contains(jsonMimetype, xmlMimetype)); assertThat(converter.getSupportedMimeTypes(), contains(jsonMimetype, xmlMimetype));
assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); assertFalse(converter.getObjectMapper().getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
} }

Loading…
Cancel
Save