diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java index 7fd76de04c..840e253fab 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 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. @@ -63,15 +63,13 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter /** * Constructor with a single MIME type. - * @param supportedMimeType the supported MIME type */ protected AbstractMessageConverter(MimeType supportedMimeType) { this(Collections.singletonList(supportedMimeType)); } /** - * Constructor with one or more MIME types via vararg. - * @param supportedMimeTypes the supported MIME types + * Constructor with multiple MIME types. * @since 5.2.2 */ protected AbstractMessageConverter(MimeType... supportedMimeTypes) { @@ -79,8 +77,7 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter } /** - * Constructor with a Collection of MIME types. - * @param supportedMimeTypes the supported MIME types + * Constructor with Collection of MIME types. */ protected AbstractMessageConverter(Collection supportedMimeTypes) { this.supportedMimeTypes.addAll(supportedMimeTypes); @@ -103,20 +100,21 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter } /** - * Configure the {@link ContentTypeResolver} to use to resolve the content - * type of an input message. - *

Note that if no resolver is configured, then - * {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should - * be left as {@code false} (the default) or otherwise this converter will - * ignore all messages. + * Configure a {@link ContentTypeResolver} for resolving the content type + * of input messages. *

By default, a {@code DefaultContentTypeResolver} instance is used. + *

Note: if the resolver is set to {@code null}, then + * {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should + * be {@code false}, which is the default, or otherwise this converter will + * ignore all messages. */ public void setContentTypeResolver(@Nullable ContentTypeResolver resolver) { this.contentTypeResolver = resolver; } /** - * Return the configured {@link ContentTypeResolver}. + * Return the {@link #setContentTypeResolver(ContentTypeResolver) configured} + * {@code ContentTypeResolver}. */ @Nullable public ContentTypeResolver getContentTypeResolver() { @@ -125,11 +123,11 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter /** * Whether this converter should convert messages for which no content type - * could be resolved through the configured + * can be resolved through the configured * {@link org.springframework.messaging.converter.ContentTypeResolver}. *

A converter can be configured to be strict only when a * {@link #setContentTypeResolver contentTypeResolver} is configured and the - * list of {@link #getSupportedMimeTypes() supportedMimeTypes} is not be empty. + * list of {@link #getSupportedMimeTypes() supportedMimeTypes} is not empty. *

When this flag is set to {@code true}, {@link #supportsMimeType(MessageHeaders)} * will return {@code false} if the {@link #setContentTypeResolver contentTypeResolver} * is not defined or if no content-type header is present. @@ -193,7 +191,9 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter @Override @Nullable - public final Message toMessage(Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { + public final Message toMessage( + Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { + if (!canConvertTo(payload, headers)) { return null; } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/converter/DefaultContentTypeResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/converter/DefaultContentTypeResolverTests.java index 9013a05cd3..d9c335be3e 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/converter/DefaultContentTypeResolverTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/converter/DefaultContentTypeResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 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,10 +17,8 @@ package org.springframework.messaging.converter; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.messaging.MessageHeaders; @@ -32,67 +30,50 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** - * Test fixture for {@link org.springframework.messaging.converter.DefaultContentTypeResolver}. + * Unit tests for + * {@link org.springframework.messaging.converter.DefaultContentTypeResolver}. * * @author Rossen Stoyanchev */ public class DefaultContentTypeResolverTests { - private DefaultContentTypeResolver resolver; + private final DefaultContentTypeResolver resolver = new DefaultContentTypeResolver(); - @BeforeEach - public void setup() { - this.resolver = new DefaultContentTypeResolver(); - } - @Test public void resolve() { - Map map = new HashMap<>(); - map.put(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON); - MessageHeaders headers = new MessageHeaders(map); - + MessageHeaders headers = headers(MimeTypeUtils.APPLICATION_JSON); assertThat(this.resolver.resolve(headers)).isEqualTo(MimeTypeUtils.APPLICATION_JSON); } @Test public void resolveStringContentType() { - Map map = new HashMap<>(); - map.put(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE); - MessageHeaders headers = new MessageHeaders(map); - + MessageHeaders headers = headers(MimeTypeUtils.APPLICATION_JSON_VALUE); assertThat(this.resolver.resolve(headers)).isEqualTo(MimeTypeUtils.APPLICATION_JSON); } @Test public void resolveInvalidStringContentType() { - Map map = new HashMap<>(); - map.put(MessageHeaders.CONTENT_TYPE, "invalidContentType"); - MessageHeaders headers = new MessageHeaders(map); - assertThatExceptionOfType(InvalidMimeTypeException.class).isThrownBy(() -> - this.resolver.resolve(headers)); + MessageHeaders headers = headers("invalidContentType"); + assertThatExceptionOfType(InvalidMimeTypeException.class).isThrownBy(() -> this.resolver.resolve(headers)); } @Test public void resolveUnknownHeaderType() { - Map map = new HashMap<>(); - map.put(MessageHeaders.CONTENT_TYPE, 1); - MessageHeaders headers = new MessageHeaders(map); - assertThatIllegalArgumentException().isThrownBy(() -> - this.resolver.resolve(headers)); + MessageHeaders headers = headers(1); + assertThatIllegalArgumentException().isThrownBy(() -> this.resolver.resolve(headers)); } @Test public void resolveNoContentTypeHeader() { - MessageHeaders headers = new MessageHeaders(Collections.emptyMap()); - + MessageHeaders headers = new MessageHeaders(Collections.emptyMap()); assertThat(this.resolver.resolve(headers)).isNull(); } @Test public void resolveDefaultMimeType() { this.resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON); - MessageHeaders headers = new MessageHeaders(Collections.emptyMap()); + MessageHeaders headers = new MessageHeaders(Collections.emptyMap()); assertThat(this.resolver.resolve(headers)).isEqualTo(MimeTypeUtils.APPLICATION_JSON); } @@ -100,9 +81,11 @@ public class DefaultContentTypeResolverTests { @Test public void resolveDefaultMimeTypeWithNoHeader() { this.resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON); - MessageHeaders headers = null; + assertThat(this.resolver.resolve(null)).isEqualTo(MimeTypeUtils.APPLICATION_JSON); + } - assertThat(this.resolver.resolve(headers)).isEqualTo(MimeTypeUtils.APPLICATION_JSON); + private MessageHeaders headers(Object mimeType) { + return new MessageHeaders(Map.of(MessageHeaders.CONTENT_TYPE, mimeType)); } } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java b/spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java index b70770006a..d7b4d7b931 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 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. @@ -138,10 +138,11 @@ public class MessageConverterTests { assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeTypeUtils.TEXT_PLAIN); } - @Test + @Test // gh-29768 public void toMessageDefaultContentType() { DefaultContentTypeResolver resolver = new DefaultContentTypeResolver(); resolver.setDefaultMimeType(MimeTypeUtils.TEXT_PLAIN); + TestMessageConverter converter = new TestMessageConverter(); converter.setContentTypeResolver(resolver); converter.setStrictContentTypeMatch(true); @@ -167,16 +168,12 @@ public class MessageConverterTests { } @Override - protected Object convertFromInternal( - Message message, Class targetClass, @Nullable Object conversionHint) { - + protected Object convertFromInternal(Message message, Class targetClass, @Nullable Object hint) { return "success-from"; } @Override - protected Object convertToInternal( - Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - + protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, @Nullable Object hint) { return "success-to"; } }