5

I am using Spring Cloud Stream, with RabbitMQ binder. It works great with byte[] payload and Java native serialization, but I need to work with JSON payload.

Here's my processor class.

@EnableBinding(Processor.class)
public class MessageProcessor {
    @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
    public OutputDto handleIncomingMessage(InputDto inputDto) {
        // Run some job.
        return new OutputDto();
    }
}

InputDto and OutputDto are POJOs with Jackson annotations.

  • How do I configure JSON conversion strategy?
  • How should message headers look like to be accepted and processed?
wst
  • 4,040
  • 4
  • 41
  • 59

1 Answers1

8

In your consumer you can add a content type configuration, e.g.

spring.cloud.stream.bindings.input.content-type: application/x-java-object;type=my.package.InputDto

You could also add

spring.cloud.stream.bindings.output.content-type: application/json

to force the outgoing message payload to be JSON (for interop etc.).

Note that "input" and "output" are the binder channel names (i.e. as defined in Processor in your app).

I think there is a good chance this could be made easier or more automatic, but there is some engineering effort required to make that happen in Spring Cloud. There's an issue in github if you want to follow it: https://github.com/spring-cloud/spring-cloud-stream/issues/156.

To send a message manually to a Spring Cloud Stream you can set the headers up yourself manually (but it's easier to use a Stream). A JSON message looks like this in the Rabbit admin UI:

priority:   0
delivery_mode:  2
headers:    
    contentType:    text/plain
    originalContentType:    application/json
content_type:   text/plain
Dave Syer
  • 56,583
  • 10
  • 155
  • 143
  • Can I configure NOT_NULL serialization? – wst Feb 22 '16 at 03:34
  • You can annotate your DTOs any way you like. Jackson will respect your wishes, I should think. Is that what you mean? Is it relevant to the original question? – Dave Syer Feb 22 '16 at 09:56
  • Isn't it a matter of object mapper rather than annotation? AFAIK using annotation in order to filter out null values is deprecated and you should do it via mapper configuration. Therefore, I assume it as a part of question. You should be able to provide your instance of object mapper somehow, as a part of configuring serialization strategy. Unless I am mistaken. – wst Feb 22 '16 at 10:23
  • I didn't know that annotations for deserializers were deprecated (do you have a link for that?). If you need to you can configure the `ObjectMapper` that is used to do the conversion, but I think that's a separate question really. – Dave Syer Feb 22 '16 at 10:53
  • Ah you got me there. `@JsonSerialize` has been deprecated but there is `@JsonInclude` instead. OK, I'll go and use that one. Could you please take a look at my 2nd question above - what headers should I set for message to be accepted by `input` configured with `content-type: application/json`. So far I tried "content_type: application/json" which gave me null pointer here: `MessageChannelBinderSupport.java:532` – wst Feb 22 '16 at 11:45
  • Are you sending messages yourself to this stream (not using Spring Cloud Stream)? Only you shouldn't really need to care about it. – Dave Syer Feb 22 '16 at 13:27
  • Yes because I am cooperating with different system. Between the steps it's OK, but first input and last output comes from/to external system. – wst Feb 22 '16 at 22:52