Versions
- Spring Messaging 6.0.3 / 5.3.24
Problems
DefaultContentTypeResolver#resolve
will return defaultMimeType
if null
is passed as MessageHeaders
.
https://github.com/spring-projects/spring-framework/blob/0fbc94fae002a2bf25b62b0591dcadffab817b94/spring-messaging/src/main/java/org/springframework/messaging/converter/DefaultContentTypeResolver.java#L58-L63
However, AbstractMessageConverter#getMimeType
does not call the contentTypeResolver
if null
is passed as MessageHeaders
.
https://github.com/spring-projects/spring-framework/blob/0fbc94fae002a2bf25b62b0591dcadffab817b94/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java#L252-L255
Because of this, even if DefaultContentTypeResolver#defaultMimeType
is set properly, it may be ignored.
I've confirmed this issue with Spring Cloud Stream
CompositeMessageConverter
.ApplicationJsonMessageMarshallingConverter
(child converter ofCompositeMessageConverter
) hasstrictContentTypeMatch=true
, so it thinks it's not a supported content type.
Fixes
ContentTypeResolver#resolve
accepts null
, so MessageConverter
should always delegate resolution to it.
Fix AbstractMessageConverter#getMimeType
not checking the value of MessageHeaders
.
Comment From: artembilan
Right, Rossen, it is not common to pass a null
for header value.
Even all our messaging API does not let do that: as long as we provide a null
, that is a signal to remove that header.
See a MessageHeaderAccessor
for example:
/**
* Set the value for the given header name.
* <p>If the provided value is {@code null}, the header will be removed.
*/
public void setHeader(String name, @Nullable Object value) {
if (isReadOnly(name)) {
throw new IllegalArgumentException("'" + name + "' header is read-only");
}
verifyType(name, value);
if (value != null) {
// Modify header if necessary
if (!ObjectUtils.nullSafeEquals(value, getHeader(name))) {
this.modified = true;
this.headers.getRawHeaders().put(name, value);
}
}
else {
// Remove header if available
if (this.headers.containsKey(name)) {
this.modified = true;
this.headers.getRawHeaders().remove(name);
}
}
}
Perhaps for consistency our MessageHeaders
must be fixed respectively - to ignore entries of the input Map
which has null
values...