To allow you to propagate information about the content type of produced messages, Spring Cloud Stream attaches, by default, a
contentType
header to outbound messages.
For middleware that does not directly support headers, Spring Cloud Stream provides its own mechanism of automatically wrapping outbound messages in an envelope of its own.
For middleware that does support headers, Spring Cloud Stream applications may receive messages with a given content type from non-Spring Cloud Stream applications.
The content type resolution process have been redesigned for Spring Cloud Stream 2.0.
Please read the migrating from 1.3 section to understand the changes when interacting with applications using versions of the framework.
The framework depends on a
contentType
to be present as a header in order to know how serialize/deserialize a payload.
Spring Cloud Stream allows you to declaratively configure type conversion for inputs and outputs using the
spring.cloud.stream.bindings.<channelName>.content-type
property of a binding.
Note that general type conversion may also be accomplished easily by using a transformer inside your application.
|
Note
|
For both input and output channel, setting a contentType via a property or via annotation only triggers the
default
converter if a message header with value
contentType
is not present.
This is useful for cases where you just want to send a
POJO
without sending any header information, or to consume messages that do not have a
contentType
header present.
The framework will always override any default settings with the value found on the message headers.
|
|
Tip
|
Although contentType became a required property, the framework will set a default value of
application/json
for all input/output channels if one is not
provided by the user.
|
Starting with version 2.0, the framework will no longer try to infer a contentType based on the payload
T
of a
Message<T>
.
It will instead use the contentType header (or the default provided by the framework) to configure the right
MessageConverter
to serialize the payload into
byte[]
.
The
contentType
you set is a hint to activate the corresponding
MessageConverter
. The converter can then modify the contentType to augment the information, such as the case with
Kryo
and
Avro
conveters.
For outbound messages, if your payload is of typ
byte[]
, the framework will skip the conversion logic, and just write those bytes to the wire.
In this case, if
contentType
of the message is absent, it will set the default value specified to channel.
|
Tip
|
If you intend to bypass conversion, just make sure you set the appropriate
contentType
header, otherwise you could be sending some arbitrary binary data, and the framework may set the header as
application/json
(default).
|
The following snippet shows how you can bypass conversion and set the correct contentType header.
@Autowired
private Source source;
public void sendImageData(File f) throws Exception {
byte[] data = Files.readAllBytes(f.toPath());
MimeType mimeType = (f.getName().endsWith("gif")) ? MimeTypeUtils.IMAGE_GIF : MimeTypeUtils.IMAGE_JPEG;
source.output().send(MessageBuilder.withPayload(data)
.setHeader(MessageHeaders.CONTENT_TYPE, mimeType)
.build());
}
Regardless of contentType used, the result is always a
Message<byte[]>
with a header
contentType
set. This is what gets passed to the binder to be sent over the wire.