Affects: org.springframework:spring-messaging:5.3.6
We are using org.springframework:spring-messaging:5.3.6 with com.google.protobuf:protobuf-java:3.13.0 and com.google.protobuf:protobuf-java-util:3.13.0 to send and receive protobuf messages as application/json.
static class ProtobufJavaUtilSupport implements ProtobufFormatSupport {
...
@Override
public void merge(org.springframework.messaging.Message<?> message, Charset charset,
MimeType contentType, ExtensionRegistry extensionRegistry, Message.Builder builder)
throws IOException, MessageConversionException {
if (contentType.isCompatibleWith(APPLICATION_JSON)) {
this.parser.merge(message.getPayload().toString(), builder);
}
else {
throw new MessageConversionException(
"protobuf-java-util does not support parsing " + contentType);
}
}
...
}
message.getPayload()
returns a byte array (GenericMessage [payload=byte[230], headers={...}]). Calling toString
on a byte array produces a string similar to "[B@27fe3806".
Attempt to parse resulting string as JSON produces the following error:
com.google.protobuf.InvalidProtocolBufferException: java.io.EOFException: End of input at line 1 column 12 path $[1]
at com.google.protobuf.util.JsonFormat$ParserImpl.merge (JsonFormat.java:1347)
at com.google.protobuf.util.JsonFormat$Parser.merge (JsonFormat.java:477)
at org.springframework.messaging.converter.ProtobufMessageConverter$ProtobufJavaUtilSupport.merge (ProtobufMessageConverter.java:265)
at org.springframework.messaging.converter.ProtobufMessageConverter.convertFromInternal (ProtobufMessageConverter.java:150)
I assume that byte arrays need special handling so that we use String constructor instead of toString()
call in order to get actual JSON content (i.e. something akin to new String(message.getPayload(), StandardCharsets.UTF_8)
).
Comment From: snicoll
I assume that byte arrays need special handling so that we use String constructor instead of toString() call in order to get actual JSON content
Yes although it looks a bit odd to me that the MimeType
of the body is application/json
and then the actual content of the body is not text. To make sure I am not missing anything, can you please share a small sample that we can run ourselves? You can do so by attaching a zip to this issue or pushing the code to a separate GitHub repository.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Comment From: gnagy
Hi, I just ran into this exact same issue on a project. My use case is to read Protobuf messages from Kafka (has ByteArray native payload format) and ProtobufMessageConverter
is the only converter configured.
Following the answer here https://stackoverflow.com/questions/70121156/how-to-use-org-springframework-messaging-converter-protobufmessageconverter have subclassed ProtobufMessageConverter
.
This works OK for binary protobuf encoding, when content-type: application/x-protobuf
is set. The same converter supports JSON encoding (by checking protobufFormatSupport
field) when content-type: application/json
is set, but fails with the exception described above.
Looking at other MessageConverters, they seem to support multiple payload types, therefore I believe in ProtobufMessageConverter it is a bug. - https://github.com/spring-projects/spring-framework/blob/main/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java#L229 - https://github.com/spring-cloud/spring-cloud-function/blob/main/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/JsonMessageConverter.java - https://github.com/spring-cloud/spring-cloud-function/blob/main/spring-cloud-funct[…]java/org/springframework/cloud/function/json/JacksonMapper.java
Comment From: gnagy
Another related shortcoming:
If com.google.protobuf:protobuf-java-util
is on the classpath, therefore ProtobufMessageConverter.protobufJsonFormatPresent
is true, then ProtobufMessageConverter
will try to handle content-type: application/json
messages, preventing another JSON MessageConverter
to handle those. This will fail for cases when protobuf binary and non-protobuf JSON topics are configured within the same app. There is no apparent way to configure the supported mime types in ProtobufMessageConverter
.
Comment From: siaavush
I have the exact same problem here