Should image be base64 encoded in a JSON message or returned as BytesMessage in Spring AMQP?

StackOverflow https://stackoverflow.com/questions/17255757

  •  01-06-2022
  •  | 
  •  

Question

I have setup basic Request/Reply Messaging via spring amqp using POJOs and these are exchanged over RabbitMQ via a JSON message converter.

My response pojo's payload so far has been simple strings but now I need to reply back with an image at times as well.

Q1) What would be the best way to handle this? Should the image be base64 encoded as the payload string for the JSON message?

Q2) Is it possible to simply return the image as a BytesMessage instead?

Q2.a) Would spring-amqp be able to handle two separate listeners, one that returns POJOs and another that returns BytesMessage? I would think not but here's some pseudo-code around what I'm asking:

<listener-container>
    <listener ref="requestHandlerA" method="handleMessage" queue-names="#{requestQueue.name}" />
    <listener ref="requestHandlerB" method="handleMessage" queue-names="#{requestQueue.name}" />
</listener-container>

public class RequestHandlerA {
    public ResponseDelegatePojo handleMessage(RequestDelegatePojo requestDelegate) {...}
}
public class RequestHandlerB {
    public BytesMessage handleMessage(RequestDelegatePojo requestDelegate) {...}
}

Q2.b) OR ... If the MessageListener returns an Object (may be a POJO sometimes, may be a BytesMessage at other times) ... would the spring-amqp framework be able to adjust accordingly at runtime to send back POJO serialized as json sometimes and the BytesMessage as-is at other times?

Was it helpful?

Solution

Two listeners like that won't work - it will simply create two competing consumers on the same queue. One solution would be to use different queues (and different listeners).

If you want to use the same queue for both request types, probably the simplest solution would be to have your listener POJO return Object (POJO or byte[]) (Q2b) and use a custom MessageConverter.

The custom messageConverter would be pretty simple; assuming you always get JSON on the inbound, it would always delegate to a JsonMessageConverter in fromMessage() and on the outbound side (toMessage) should delegate to either a JsonMessageConverter or a SimpleMessageConverter:

if (object instanceof byte[]) {
    return this.simpleMessageConverter.toMessage(object, messageProperties);
else {
    return this.jsonMessageConverter.toMessage(object, messageProperties);
}

The SimpleMessageConverter will set the contentType property to application/octet-stream but you can change that if you want after calling its toMessage method (message.getMessageProperties().setContentType(...);.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top