Browse Source

Polishing contribution

See gh-24087
pull/24105/head
Rossen Stoyanchev 6 years ago
parent
commit
25f3465f1f
  1. 2
      spring-messaging/spring-messaging.gradle
  2. 31
      spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java
  3. 1
      spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java
  4. 3
      spring-messaging/src/main/java/org/springframework/messaging/converter/MarshallingMessageConverter.java
  5. 67
      spring-messaging/src/main/java/org/springframework/messaging/converter/ProtobufJsonFormatMessageConverter.java
  6. 95
      spring-messaging/src/main/java/org/springframework/messaging/converter/ProtobufMessageConverter.java
  7. 22
      spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java
  8. 17
      spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java
  9. 39
      spring-messaging/src/test/java/org/springframework/messaging/converter/ProtobufMessageConverterTests.java
  10. 10
      spring-messaging/src/test/java/org/springframework/messaging/simp/config/MessageBrokerConfigurationTests.java
  11. 21
      spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverter.java
  12. 1
      spring-websocket/spring-websocket.gradle
  13. 11
      spring-websocket/src/main/java/org/springframework/web/socket/config/MessageBrokerBeanDefinitionParser.java
  14. 9
      spring-websocket/src/test/java/org/springframework/web/socket/config/MessageBrokerBeanDefinitionParserTests.java
  15. 1
      src/checkstyle/checkstyle-suppressions.xml

2
spring-messaging/spring-messaging.gradle

@ -13,9 +13,9 @@ dependencies {
optional("io.rsocket:rsocket-transport-netty") optional("io.rsocket:rsocket-transport-netty")
optional("com.fasterxml.jackson.core:jackson-databind") optional("com.fasterxml.jackson.core:jackson-databind")
optional("javax.xml.bind:jaxb-api") optional("javax.xml.bind:jaxb-api")
optional("com.google.protobuf:protobuf-java-util")
optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core")
optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
optional("com.google.protobuf:protobuf-java-util")
testCompile("javax.inject:javax.inject-tck") testCompile("javax.inject:javax.inject-tck")
testCompile("javax.servlet:javax.servlet-api") testCompile("javax.servlet:javax.servlet-api")
testCompile("javax.validation:validation-api") testCompile("javax.validation:validation-api")

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2019 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.
@ -17,10 +17,10 @@
package org.springframework.messaging.converter; package org.springframework.messaging.converter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Arrays;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -48,7 +48,7 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private List<MimeType> supportedMimeTypes; private final List<MimeType> supportedMimeTypes = new ArrayList<>(4);
@Nullable @Nullable
private ContentTypeResolver contentTypeResolver = new DefaultContentTypeResolver(); private ContentTypeResolver contentTypeResolver = new DefaultContentTypeResolver();
@ -59,28 +59,28 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
/** /**
* Construct an {@code AbstractMessageConverter} supporting a single MIME type. * Constructor with a single MIME type.
* @param supportedMimeType the supported MIME type * @param supportedMimeType the supported MIME type
*/ */
protected AbstractMessageConverter(MimeType supportedMimeType) { protected AbstractMessageConverter(MimeType supportedMimeType) {
setSupportedMimeTypes(Collections.singletonList(supportedMimeType)); this(Collections.singletonList(supportedMimeType));
} }
/** /**
* Construct an {@code AbstractMessageConverter} supporting multiple MIME types. * Constructor with one or more MIME types via vararg.
* @param supportedMimeTypes the supported MIME types * @param supportedMimeTypes the supported MIME types
* @since 5.2.2
*/ */
protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) { protected AbstractMessageConverter(MimeType... supportedMimeTypes) {
setSupportedMimeTypes(new ArrayList<>(supportedMimeTypes)); this(Arrays.asList(supportedMimeTypes));
} }
/** /**
* Construct an {@code AbstractMessageConverter} supporting multiple MIME types. * Constructor with a Collection of MIME types.
* @param supportedMimeTypes the supported MIME types * @param supportedMimeTypes the supported MIME types
* @since 5.2.2
*/ */
protected AbstractMessageConverter(MimeType... supportedMimeTypes) { protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) {
setSupportedMimeTypes(Arrays.asList(supportedMimeTypes)); this.supportedMimeTypes.addAll(supportedMimeTypes);
} }
@ -92,12 +92,11 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
} }
/** /**
* Set the list of {@link MimeType} objects supported by this converter. * Allows sub-classes to add more supported mime types.
* @since 5.2.2 * @since 5.2.2
*/ */
protected void setSupportedMimeTypes(List<MimeType> supportedMimeTypes) { protected void addSupportedMimeTypes(MimeType... supportedMimeTypes) {
Assert.notNull(supportedMimeTypes, "supportedMimeTypes must not be null"); this.supportedMimeTypes.addAll(Arrays.asList(supportedMimeTypes));
this.supportedMimeTypes = supportedMimeTypes;
} }
/** /**

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

@ -22,7 +22,6 @@ import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.JsonView;

3
spring-messaging/src/main/java/org/springframework/messaging/converter/MarshallingMessageConverter.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2019 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.
@ -21,7 +21,6 @@ import java.io.ByteArrayOutputStream;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.util.Arrays;
import javax.xml.transform.Result; import javax.xml.transform.Result;
import javax.xml.transform.Source; import javax.xml.transform.Source;

67
spring-messaging/src/main/java/org/springframework/messaging/converter/ProtobufJsonFormatMessageConverter.java

@ -0,0 +1,67 @@
/*
* Copyright 2002-2019 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.messaging.converter;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.util.JsonFormat;
import org.springframework.lang.Nullable;
/**
* Subclass of {@link ProtobufMessageConverter} for use with the official
* {@code "com.google.protobuf:protobuf-java-util"} library for JSON support.
*
* <p>Most importantly, this class allows for custom JSON parser and printer
* configurations through the {@link JsonFormat} utility. If no special parser
* or printer configuration is given, default variants will be used instead.
*
* <p>Requires Protobuf 3.x and {@code "com.google.protobuf:protobuf-java-util"} 3.x,
* with 3.3 or higher recommended.
*
* @author Rossen Stoyanchev
* @since 5.2.2
*/
public class ProtobufJsonFormatMessageConverter extends ProtobufMessageConverter {
/**
* Constructor with default instances of {@link JsonFormat.Parser},
* {@link JsonFormat.Printer}, and {@link ExtensionRegistry}.
*/
public ProtobufJsonFormatMessageConverter(@Nullable ExtensionRegistry extensionRegistry) {
this(null, null);
}
/**
* Constructor with given instances of {@link JsonFormat.Parser},
* {@link JsonFormat.Printer}, and a default instance of {@link ExtensionRegistry}.
*/
public ProtobufJsonFormatMessageConverter(
@Nullable JsonFormat.Parser parser, @Nullable JsonFormat.Printer printer) {
this(parser, printer, null);
}
/**
* Constructor with given instances of {@link JsonFormat.Parser},
* {@link JsonFormat.Printer}, and {@link ExtensionRegistry}.
*/
public ProtobufJsonFormatMessageConverter(@Nullable JsonFormat.Parser parser,
@Nullable JsonFormat.Printer printer, @Nullable ExtensionRegistry extensionRegistry) {
super(new ProtobufJavaUtilSupport(parser, printer), extensionRegistry);
}
}

95
spring-messaging/src/main/java/org/springframework/messaging/converter/ProtobufMessageConverter.java

@ -23,12 +23,12 @@ import java.io.OutputStreamWriter;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessageHeaders;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -77,59 +77,23 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
/** /**
* Construct a new {@code ProtobufMessageConverter}. * Constructor with a default instance of {@link ExtensionRegistry}.
*/ */
public ProtobufMessageConverter() { public ProtobufMessageConverter() {
this((ProtobufFormatSupport) null, (ExtensionRegistry) null); this(null, null);
} }
/** /**
* Construct a new {@code ProtobufMessageConverter} with a registry that specifies * Constructor with a given {@code ExtensionRegistry}.
* protocol message extensions.
*
* @param extensionRegistry the registry to populate
*/ */
public ProtobufMessageConverter(@Nullable ExtensionRegistry extensionRegistry) { public ProtobufMessageConverter(ExtensionRegistry extensionRegistry) {
this(null, extensionRegistry); this(null, extensionRegistry);
} }
/** ProtobufMessageConverter(@Nullable ProtobufFormatSupport formatSupport,
* Construct a new {@code ProtobufMessageConverter} with the given @Nullable ExtensionRegistry extensionRegistry) {
* {@code JsonFormat.Parser} and {@code JsonFormat.Printer} configuration.
*
* @param parser the JSON parser configuration
* @param printer the JSON printer configuration
*/
public ProtobufMessageConverter(@Nullable JsonFormat.Parser parser, @Nullable JsonFormat.Printer printer) {
this(new ProtobufJavaUtilSupport(parser, printer), (ExtensionRegistry) null);
}
/** super(PROTOBUF, TEXT_PLAIN);
* Construct a new {@code ProtobufMessageConverter} with the given
* {@code JsonFormat.Parser} and {@code JsonFormat.Printer} configuration, also
* accepting a registry that specifies protocol message extensions.
*
* @param parser the JSON parser configuration
* @param printer the JSON printer configuration
* @param extensionRegistry the registry to populate
*/
public ProtobufMessageConverter(@Nullable JsonFormat.Parser parser,
@Nullable JsonFormat.Printer printer, @Nullable ExtensionRegistry extensionRegistry) {
this(new ProtobufJavaUtilSupport(parser, printer), extensionRegistry);
}
/**
* Construct a new {@code ProtobufMessageConverter} with the given
* {@code ProtobufFormatSupport} configuration, also
* accepting a registry that specifies protocol message extensions.
*
* @param formatSupport support third party
* @param extensionRegistry the registry to populate
*/
public ProtobufMessageConverter(@Nullable ProtobufFormatSupport formatSupport,
@Nullable ExtensionRegistry extensionRegistry) {
super(PROTOBUF);
if (formatSupport != null) { if (formatSupport != null) {
this.protobufFormatSupport = formatSupport; this.protobufFormatSupport = formatSupport;
@ -142,12 +106,13 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
} }
if (this.protobufFormatSupport != null) { if (this.protobufFormatSupport != null) {
setSupportedMimeTypes(Arrays.asList(protobufFormatSupport.supportedMediaTypes())); addSupportedMimeTypes(this.protobufFormatSupport.supportedMediaTypes());
} }
this.extensionRegistry = (extensionRegistry == null ? ExtensionRegistry.newInstance() : extensionRegistry); this.extensionRegistry = (extensionRegistry == null ? ExtensionRegistry.newInstance() : extensionRegistry);
} }
@Override @Override
protected boolean supports(Class<?> clazz) { protected boolean supports(Class<?> clazz) {
return Message.class.isAssignableFrom(clazz); return Message.class.isAssignableFrom(clazz);
@ -161,7 +126,9 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
} }
@Override @Override
protected Object convertFromInternal(org.springframework.messaging.Message<?> message, Class<?> targetClass, @Nullable Object conversionHint) { protected Object convertFromInternal(org.springframework.messaging.Message<?> message,
Class<?> targetClass, @Nullable Object conversionHint) {
MimeType contentType = getMimeType(message.getHeaders()); MimeType contentType = getMimeType(message.getHeaders());
final Object payload = message.getPayload(); final Object payload = message.getPayload();
@ -175,18 +142,16 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
} }
Message.Builder builder = getMessageBuilder(targetClass); Message.Builder builder = getMessageBuilder(targetClass);
try { try {
if (PROTOBUF.isCompatibleWith(contentType)) { if (PROTOBUF.isCompatibleWith(contentType)) {
builder.mergeFrom((byte[]) payload, this.extensionRegistry); builder.mergeFrom((byte[]) payload, this.extensionRegistry);
} }
else if (protobufFormatSupport != null) { else if (this.protobufFormatSupport != null) {
this.protobufFormatSupport.merge( this.protobufFormatSupport.merge(message, charset, contentType, this.extensionRegistry, builder);
message, charset, contentType, this.extensionRegistry, builder);
} }
} }
catch (IOException e) { catch (IOException ex) {
throw new MessageConversionException(message, "Could not read proto message" + e.getMessage(), e); throw new MessageConversionException(message, "Could not read proto message" + ex.getMessage(), ex);
} }
return builder.build(); return builder.build();
@ -194,13 +159,14 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
@Override @Override
protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { protected Object convertToInternal(
Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) {
final Message message = (Message) payload; final Message message = (Message) payload;
MimeType contentType = getMimeType(headers); MimeType contentType = getMimeType(headers);
if (contentType == null) { if (contentType == null) {
contentType = PROTOBUF; contentType = PROTOBUF;
} }
Charset charset = contentType.getCharset(); Charset charset = contentType.getCharset();
@ -220,14 +186,13 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
payload = new String(outputStream.toByteArray(), charset); payload = new String(outputStream.toByteArray(), charset);
} }
} }
catch (IOException e) { catch (IOException ex) {
throw new MessageConversionException("Could not write proto message" + e.getMessage(), e); throw new MessageConversionException("Could not write proto message" + ex.getMessage(), ex);
} }
return payload; return payload;
} }
/** /**
* Create a new {@code Message.Builder} instance for the given class. * Create a new {@code Message.Builder} instance for the given class.
* <p>This method uses a ConcurrentReferenceHashMap for caching method lookups. * <p>This method uses a ConcurrentReferenceHashMap for caching method lookups.
@ -257,9 +222,9 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
boolean supportsWriteOnly(@Nullable MimeType mediaType); boolean supportsWriteOnly(@Nullable MimeType mediaType);
void merge(org.springframework.messaging.Message<?> message, Charset charset, MimeType contentType, void merge(org.springframework.messaging.Message<?> message,
ExtensionRegistry extensionRegistry, Message.Builder builder) Charset charset, MimeType contentType, ExtensionRegistry extensionRegistry,
throws IOException, MessageConversionException; Message.Builder builder) throws IOException, MessageConversionException;
void print(Message message, OutputStream output, MimeType contentType, Charset charset) void print(Message message, OutputStream output, MimeType contentType, Charset charset)
throws IOException, MessageConversionException; throws IOException, MessageConversionException;
@ -283,7 +248,7 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
@Override @Override
public MimeType[] supportedMediaTypes() { public MimeType[] supportedMediaTypes() {
return new MimeType[]{PROTOBUF, TEXT_PLAIN, APPLICATION_JSON}; return new MimeType[]{APPLICATION_JSON};
} }
@Override @Override
@ -292,8 +257,8 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
} }
@Override @Override
public void merge(org.springframework.messaging.Message<?> message, Charset charset, MimeType contentType, public void merge(org.springframework.messaging.Message<?> message, Charset charset,
ExtensionRegistry extensionRegistry, Message.Builder builder) MimeType contentType, ExtensionRegistry extensionRegistry, Message.Builder builder)
throws IOException, MessageConversionException { throws IOException, MessageConversionException {
if (contentType.isCompatibleWith(APPLICATION_JSON)) { if (contentType.isCompatibleWith(APPLICATION_JSON)) {
@ -313,12 +278,12 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
OutputStreamWriter writer = new OutputStreamWriter(output, charset); OutputStreamWriter writer = new OutputStreamWriter(output, charset);
this.printer.appendTo(message, writer); this.printer.appendTo(message, writer);
writer.flush(); writer.flush();
} else { }
else {
throw new MessageConversionException( throw new MessageConversionException(
"protobuf-java-util does not support printing " + contentType); "protobuf-java-util does not support printing " + contentType);
} }
} }
} }
} }

22
spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java

@ -37,7 +37,6 @@ import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.converter.ProtobufMessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
import org.springframework.messaging.simp.SimpLogging; import org.springframework.messaging.simp.SimpLogging;
@ -94,15 +93,9 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
private static final String MVC_VALIDATOR_NAME = "mvcValidator"; private static final String MVC_VALIDATOR_NAME = "mvcValidator";
private static final boolean jackson2Present; private static final boolean jackson2Present = ClassUtils.isPresent(
"com.fasterxml.jackson.databind.ObjectMapper", AbstractMessageBrokerConfiguration.class.getClassLoader());
private static final boolean protobufPresent;
static {
ClassLoader classLoader = AbstractMessageBrokerConfiguration.class.getClassLoader();
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader);
protobufPresent = ClassUtils.isPresent("com.google.protobuf.Message", classLoader);
}
@Nullable @Nullable
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@ -398,9 +391,6 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
if (jackson2Present) { if (jackson2Present) {
converters.add(createJacksonConverter()); converters.add(createJacksonConverter());
} }
if (protobufPresent) {
converters.add(createProtobufConverter());
}
} }
return new CompositeMessageConverter(converters); return new CompositeMessageConverter(converters);
} }
@ -413,14 +403,6 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
return converter; return converter;
} }
protected ProtobufMessageConverter createProtobufConverter() {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(ProtobufMessageConverter.PROTOBUF);
final ProtobufMessageConverter converter = new ProtobufMessageConverter();
converter.setContentTypeResolver(resolver);
return converter;
}
/** /**
* Override this method to add custom message converters. * Override this method to add custom message converters.
* @param messageConverters the list to add converters to, initially empty * @param messageConverters the list to add converters to, initially empty

17
spring-messaging/src/test/java/org/springframework/messaging/converter/MessageConverterTests.java

@ -78,8 +78,7 @@ public class MessageConverterTests {
public void supportsMimeTypeNoneConfigured() { public void supportsMimeTypeNoneConfigured() {
Message<String> message = MessageBuilder.withPayload( Message<String> message = MessageBuilder.withPayload(
"ABC").setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON).build(); "ABC").setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON).build();
final MimeType[] empty = {}; this.converter = new TestMessageConverter(new MimeType[0]);
this.converter = new TestMessageConverter(empty);
assertThat(this.converter.fromMessage(message, String.class)).isEqualTo("success-from"); assertThat(this.converter.fromMessage(message, String.class)).isEqualTo("success-from");
} }
@ -100,10 +99,8 @@ public class MessageConverterTests {
@Test @Test
public void setStrictContentTypeMatchWithNoSupportedMimeTypes() { public void setStrictContentTypeMatchWithNoSupportedMimeTypes() {
final MimeType[] empty = {}; this.converter = new TestMessageConverter(new MimeType[0]);
this.converter = new TestMessageConverter(empty); assertThatIllegalArgumentException().isThrownBy(() -> this.converter.setStrictContentTypeMatch(true));
assertThatIllegalArgumentException().isThrownBy(() ->
this.converter.setStrictContentTypeMatch(true));
} }
@Test @Test
@ -158,15 +155,15 @@ public class MessageConverterTests {
} }
@Override @Override
protected Object convertFromInternal(Message<?> message, Class<?> targetClass, protected Object convertFromInternal(
@Nullable Object conversionHint) { Message<?> message, Class<?> targetClass, @Nullable Object conversionHint) {
return "success-from"; return "success-from";
} }
@Override @Override
protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, protected Object convertToInternal(
@Nullable Object conversionHint) { Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) {
return "success-to"; return "success-to";
} }

39
spring-messaging/src/test/java/org/springframework/messaging/converter/ProtobufMessageConverterTest.java → spring-messaging/src/test/java/org/springframework/messaging/converter/ProtobufMessageConverterTests.java

@ -16,13 +16,13 @@
package org.springframework.messaging.converter; package org.springframework.messaging.converter;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.ExtensionRegistry;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.protobuf.Msg; import org.springframework.messaging.protobuf.Msg;
@ -39,15 +39,18 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON;
* *
* @author Parviz Rozikov * @author Parviz Rozikov
*/ */
class ProtobufMessageConverterTest { public class ProtobufMessageConverterTests {
private ProtobufMessageConverter converter; private ProtobufMessageConverter converter;
private ExtensionRegistry extensionRegistry; private ExtensionRegistry extensionRegistry;
private Msg testMsg; private Msg testMsg;
private Message<byte[]> message; private Message<byte[]> message;
private Message<byte[]> messageWithoutContentType; private Message<byte[]> messageWithoutContentType;
private Message<String> messageJson; private Message<String> messageJson;
@ -58,20 +61,22 @@ class ProtobufMessageConverterTest {
this.testMsg = Msg.newBuilder().setFoo("Foo").setBlah(SecondMsg.newBuilder().setBlah(123).build()).build(); this.testMsg = Msg.newBuilder().setFoo("Foo").setBlah(SecondMsg.newBuilder().setBlah(123).build()).build();
this.message = MessageBuilder.withPayload(this.testMsg.toByteArray()) this.message = MessageBuilder.withPayload(this.testMsg.toByteArray())
.setHeader(CONTENT_TYPE, ProtobufMessageConverter.PROTOBUF).build(); .setHeader(CONTENT_TYPE, ProtobufMessageConverter.PROTOBUF).build();
this.messageWithoutContentType = MessageBuilder.withPayload(this.testMsg.toByteArray()) this.messageWithoutContentType = MessageBuilder.withPayload(this.testMsg.toByteArray()).build();
this.messageJson = MessageBuilder.withPayload(
"{\n" +
" \"foo\": \"Foo\",\n" +
" \"blah\": {\n" +
" \"blah\": 123\n" +
" }\n" +
"}")
.setHeader(CONTENT_TYPE, APPLICATION_JSON)
.build(); .build();
this.messageJson = MessageBuilder.withPayload("{\n" +
" \"foo\": \"Foo\",\n" +
" \"blah\": {\n" +
" \"blah\": 123\n" +
" }\n" +
"}")
.setHeader(CONTENT_TYPE, APPLICATION_JSON).build();
} }
@Test @Test
public void extensionRegistryNull() { public void extensionRegistryNull() {
ProtobufMessageConverter converter = new ProtobufMessageConverter((ExtensionRegistry) null); ProtobufMessageConverter converter = new ProtobufMessageConverter(null);
assertThat(converter.extensionRegistry).isNotNull(); assertThat(converter.extensionRegistry).isNotNull();
} }
@ -92,13 +97,13 @@ class ProtobufMessageConverterTest {
@Test @Test
public void convertFrom() throws IOException { public void convertFrom() {
final Msg msg = (Msg) converter.fromMessage(message, Msg.class); final Msg msg = (Msg) converter.fromMessage(message, Msg.class);
assertThat(msg).isEqualTo(testMsg); assertThat(msg).isEqualTo(testMsg);
} }
@Test @Test
public void convertTo() throws IOException { public void convertTo() {
final Message<?> message = converter.toMessage(this.testMsg, this.message.getHeaders()); final Message<?> message = converter.toMessage(this.testMsg, this.message.getHeaders());
assertThat(message).isNotNull(); assertThat(message).isNotNull();
assertThat(message.getPayload()).isEqualTo(this.message.getPayload()); assertThat(message.getPayload()).isEqualTo(this.message.getPayload());
@ -106,19 +111,19 @@ class ProtobufMessageConverterTest {
@Test @Test
public void convertFromNoContentType() throws IOException { public void convertFromNoContentType(){
Msg result = (Msg) converter.fromMessage(messageWithoutContentType, Msg.class); Msg result = (Msg) converter.fromMessage(messageWithoutContentType, Msg.class);
assertThat(result).isEqualTo(testMsg); assertThat(result).isEqualTo(testMsg);
} }
@Test @Test
public void defaultContentType() throws Exception { public void defaultContentType() {
assertThat(converter.getDefaultContentType(testMsg)).isEqualTo(ProtobufMessageConverter.PROTOBUF); assertThat(converter.getDefaultContentType(testMsg)).isEqualTo(ProtobufMessageConverter.PROTOBUF);
} }
@Test @Test
public void testJsonWithGoogleProtobuf() throws Exception { public void testJsonWithGoogleProtobuf() {
this.converter = new ProtobufMessageConverter( this.converter = new ProtobufMessageConverter(
new ProtobufMessageConverter.ProtobufJavaUtilSupport(null, null), new ProtobufMessageConverter.ProtobufJavaUtilSupport(null, null),
extensionRegistry); extensionRegistry);
@ -139,4 +144,4 @@ class ProtobufMessageConverterTest {
assertThat(msg).isEqualTo(this.testMsg); assertThat(msg).isEqualTo(this.testMsg);
} }
} }

10
spring-messaging/src/test/java/org/springframework/messaging/simp/config/MessageBrokerConfigurationTests.java

@ -41,7 +41,6 @@ import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.converter.ProtobufMessageConverter;
import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
@ -282,17 +281,13 @@ public class MessageBrokerConfigurationTests {
CompositeMessageConverter compositeConverter = config.brokerMessageConverter(); CompositeMessageConverter compositeConverter = config.brokerMessageConverter();
List<MessageConverter> converters = compositeConverter.getConverters(); List<MessageConverter> converters = compositeConverter.getConverters();
assertThat(converters).hasSize(4); assertThat(converters).hasSize(3);
assertThat(converters.get(0)).isInstanceOf(StringMessageConverter.class); assertThat(converters.get(0)).isInstanceOf(StringMessageConverter.class);
assertThat(converters.get(1)).isInstanceOf(ByteArrayMessageConverter.class); assertThat(converters.get(1)).isInstanceOf(ByteArrayMessageConverter.class);
assertThat(converters.get(2)).isInstanceOf(MappingJackson2MessageConverter.class); assertThat(converters.get(2)).isInstanceOf(MappingJackson2MessageConverter.class);
assertThat(converters.get(3)).isInstanceOf(ProtobufMessageConverter.class);
ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver(); ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver();
assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(MimeTypeUtils.APPLICATION_JSON); assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(MimeTypeUtils.APPLICATION_JSON);
resolver = ((ProtobufMessageConverter) converters.get(3)).getContentTypeResolver();
assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(ProtobufMessageConverter.PROTOBUF);
} }
@Test @Test
@ -344,13 +339,12 @@ public class MessageBrokerConfigurationTests {
}; };
CompositeMessageConverter compositeConverter = config.brokerMessageConverter(); CompositeMessageConverter compositeConverter = config.brokerMessageConverter();
assertThat(compositeConverter.getConverters()).hasSize(5); assertThat(compositeConverter.getConverters()).hasSize(4);
Iterator<MessageConverter> iterator = compositeConverter.getConverters().iterator(); Iterator<MessageConverter> iterator = compositeConverter.getConverters().iterator();
assertThat(iterator.next()).isEqualTo(testConverter); assertThat(iterator.next()).isEqualTo(testConverter);
assertThat(iterator.next()).isInstanceOf(StringMessageConverter.class); assertThat(iterator.next()).isInstanceOf(StringMessageConverter.class);
assertThat(iterator.next()).isInstanceOf(ByteArrayMessageConverter.class); assertThat(iterator.next()).isInstanceOf(ByteArrayMessageConverter.class);
assertThat(iterator.next()).isInstanceOf(MappingJackson2MessageConverter.class); assertThat(iterator.next()).isInstanceOf(MappingJackson2MessageConverter.class);
assertThat(iterator.next()).isInstanceOf(ProtobufMessageConverter.class);
} }
@Test @Test

21
spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverter.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2019 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.
@ -42,18 +42,16 @@ import org.springframework.lang.Nullable;
public class ProtobufJsonFormatHttpMessageConverter extends ProtobufHttpMessageConverter { public class ProtobufJsonFormatHttpMessageConverter extends ProtobufHttpMessageConverter {
/** /**
* Construct a new {@code ProtobufJsonFormatHttpMessageConverter} with default * Constructor with default instances of {@link JsonFormat.Parser},
* {@code JsonFormat.Parser} and {@code JsonFormat.Printer} configuration. * {@link JsonFormat.Printer}, and {@link ExtensionRegistry}.
*/ */
public ProtobufJsonFormatHttpMessageConverter() { public ProtobufJsonFormatHttpMessageConverter() {
this(null, null, (ExtensionRegistry)null); this(null, null, (ExtensionRegistry)null);
} }
/** /**
* Construct a new {@code ProtobufJsonFormatHttpMessageConverter} with the given * Constructor with given instances of {@link JsonFormat.Parser},
* {@code JsonFormat.Parser} and {@code JsonFormat.Printer} configuration. * {@link JsonFormat.Printer}, and a default instance of {@link ExtensionRegistry}.
* @param parser the JSON parser configuration
* @param printer the JSON printer configuration
*/ */
public ProtobufJsonFormatHttpMessageConverter( public ProtobufJsonFormatHttpMessageConverter(
@Nullable JsonFormat.Parser parser, @Nullable JsonFormat.Printer printer) { @Nullable JsonFormat.Parser parser, @Nullable JsonFormat.Printer printer) {
@ -62,13 +60,8 @@ public class ProtobufJsonFormatHttpMessageConverter extends ProtobufHttpMessageC
} }
/** /**
* Construct a new {@code ProtobufJsonFormatHttpMessageConverter} with the given * Constructor with given instances of {@link JsonFormat.Parser},
* {@code JsonFormat.Parser} and {@code JsonFormat.Printer} configuration, also * {@link JsonFormat.Printer}, and {@link ExtensionRegistry}.
* accepting a registry that specifies protocol message extensions.
* @param parser the JSON parser configuration
* @param printer the JSON printer configuration
* @param extensionRegistry the registry to populate
* @since 5.1
*/ */
public ProtobufJsonFormatHttpMessageConverter(@Nullable JsonFormat.Parser parser, public ProtobufJsonFormatHttpMessageConverter(@Nullable JsonFormat.Parser parser,
@Nullable JsonFormat.Printer printer, @Nullable ExtensionRegistry extensionRegistry) { @Nullable JsonFormat.Printer printer, @Nullable ExtensionRegistry extensionRegistry) {

1
spring-websocket/spring-websocket.gradle

@ -21,7 +21,6 @@ dependencies {
optional("io.undertow:undertow-servlet") optional("io.undertow:undertow-servlet")
optional("io.undertow:undertow-websockets-jsr") optional("io.undertow:undertow-websockets-jsr")
optional("com.fasterxml.jackson.core:jackson-databind") optional("com.fasterxml.jackson.core:jackson-databind")
optional("com.google.protobuf:protobuf-java-util")
testCompile("org.apache.tomcat.embed:tomcat-embed-core") testCompile("org.apache.tomcat.embed:tomcat-embed-core")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket") testCompile("org.apache.tomcat.embed:tomcat-embed-websocket")
testCompile("io.projectreactor.netty:reactor-netty") testCompile("io.projectreactor.netty:reactor-netty")

11
spring-websocket/src/main/java/org/springframework/web/socket/config/MessageBrokerBeanDefinitionParser.java

@ -44,7 +44,6 @@ import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.DefaultContentTypeResolver; import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.converter.ProtobufMessageConverter;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.SimpSessionScope; import org.springframework.messaging.simp.SimpSessionScope;
import org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler; import org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler;
@ -116,13 +115,10 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
private static final boolean javaxValidationPresent; private static final boolean javaxValidationPresent;
private static final boolean protobufPresent;
static { static {
ClassLoader classLoader = MessageBrokerBeanDefinitionParser.class.getClassLoader(); ClassLoader classLoader = MessageBrokerBeanDefinitionParser.class.getClassLoader();
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader); jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader);
javaxValidationPresent = ClassUtils.isPresent("javax.validation.Validator", classLoader); javaxValidationPresent = ClassUtils.isPresent("javax.validation.Validator", classLoader);
protobufPresent = ClassUtils.isPresent("com.google.protobuf.Message", classLoader);
} }
@ -506,13 +502,6 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
jacksonConverterDef.getPropertyValues().add("objectMapper", jacksonFactoryDef); jacksonConverterDef.getPropertyValues().add("objectMapper", jacksonFactoryDef);
converters.add(jacksonConverterDef); converters.add(jacksonConverterDef);
} }
if (protobufPresent) {
final RootBeanDefinition protoConverterDef = new RootBeanDefinition(ProtobufMessageConverter.class);
RootBeanDefinition resolverDef = new RootBeanDefinition(DefaultContentTypeResolver.class);
resolverDef.getPropertyValues().add("defaultMimeType", ProtobufMessageConverter.PROTOBUF);
protoConverterDef.getPropertyValues().add("contentTypeResolver", resolverDef);
converters.add(protoConverterDef);
}
} }
ConstructorArgumentValues cargs = new ConstructorArgumentValues(); ConstructorArgumentValues cargs = new ConstructorArgumentValues();
cargs.addIndexedArgumentValue(0, converters); cargs.addIndexedArgumentValue(0, converters);

9
spring-websocket/src/test/java/org/springframework/web/socket/config/MessageBrokerBeanDefinitionParserTests.java

@ -41,7 +41,6 @@ import org.springframework.messaging.converter.ContentTypeResolver;
import org.springframework.messaging.converter.DefaultContentTypeResolver; import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.ProtobufMessageConverter;
import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
@ -340,18 +339,14 @@ public class MessageBrokerBeanDefinitionParserTests {
assertThat(simpMessagingTemplate.getUserDestinationPrefix()).isEqualTo("/personal/"); assertThat(simpMessagingTemplate.getUserDestinationPrefix()).isEqualTo("/personal/");
List<MessageConverter> converters = compositeMessageConverter.getConverters(); List<MessageConverter> converters = compositeMessageConverter.getConverters();
assertThat(converters).hasSize(4); assertThat(converters).hasSize(3);
assertThat(converters.get(0)).isInstanceOf(StringMessageConverter.class); assertThat(converters.get(0)).isInstanceOf(StringMessageConverter.class);
assertThat(converters.get(1)).isInstanceOf(ByteArrayMessageConverter.class); assertThat(converters.get(1)).isInstanceOf(ByteArrayMessageConverter.class);
assertThat(converters.get(2)).isInstanceOf(MappingJackson2MessageConverter.class); assertThat(converters.get(2)).isInstanceOf(MappingJackson2MessageConverter.class);
assertThat(converters.get(3)).isInstanceOf(ProtobufMessageConverter.class);
ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver(); ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver();
assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(MimeTypeUtils.APPLICATION_JSON); assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(MimeTypeUtils.APPLICATION_JSON);
resolver = ((ProtobufMessageConverter) converters.get(3)).getContentTypeResolver();
assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(ProtobufMessageConverter.PROTOBUF);
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(annotationMethodMessageHandler); DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(annotationMethodMessageHandler);
Object pathMatcher = handlerAccessor.getPropertyValue("pathMatcher"); Object pathMatcher = handlerAccessor.getPropertyValue("pathMatcher");
String pathSeparator = (String) new DirectFieldAccessor(pathMatcher).getPropertyValue("pathSeparator"); String pathSeparator = (String) new DirectFieldAccessor(pathMatcher).getPropertyValue("pathSeparator");
@ -420,7 +415,7 @@ public class MessageBrokerBeanDefinitionParserTests {
CompositeMessageConverter compositeConverter = this.appContext.getBean(CompositeMessageConverter.class); CompositeMessageConverter compositeConverter = this.appContext.getBean(CompositeMessageConverter.class);
assertThat(compositeConverter).isNotNull(); assertThat(compositeConverter).isNotNull();
assertThat(compositeConverter.getConverters().size()).isEqualTo(5); assertThat(compositeConverter.getConverters().size()).isEqualTo(4);
assertThat(compositeConverter.getConverters().iterator().next().getClass()).isEqualTo(StringMessageConverter.class); assertThat(compositeConverter.getConverters().iterator().next().getClass()).isEqualTo(StringMessageConverter.class);
} }

1
src/checkstyle/checkstyle-suppressions.xml

@ -52,6 +52,7 @@
<suppress files="StompHeaderAccessor" checks="JavadocVariable" /> <suppress files="StompHeaderAccessor" checks="JavadocVariable" />
<suppress files="StompHeaders" checks="JavadocVariable" /> <suppress files="StompHeaders" checks="JavadocVariable" />
<suppress files="org[\\/]springframework[\\/]messaging[\\/]handler[\\/]annotation[\\/]ValueConstants" checks="InterfaceIsType" /> <suppress files="org[\\/]springframework[\\/]messaging[\\/]handler[\\/]annotation[\\/]ValueConstants" checks="InterfaceIsType" />
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]messaging[\\/]protobuf[\\/].*" checks=".*" />
<!-- spring-orm --> <!-- spring-orm -->
<suppress files="jpa[\\/]vendor[\\/]Database" checks="JavadocVariable|JavadocStyle"/> <suppress files="jpa[\\/]vendor[\\/]Database" checks="JavadocVariable|JavadocStyle"/>

Loading…
Cancel
Save