0

I have a Spring App working with JMS (ActiveMQ) and sending two types of messages.

  • Java objects that implements Serializable
  • json

About the latter messaging approach, the sender/receiver work with a MessageConverter configured for json

Until here the app works fine.

What I need is a way to get and print the json data when it is sent and received.

Thus:

  • Sender: use a Java Object -> transform to json -> print json data -> send json data
  • Receiver: receive json data -> print json data -> transform to Java Object -> do business logic

Of course that the transformation process happens automatically internally, but for report purposes I need the json data sent and received. Currently the app can work only 'directly' with the Java Object being sent and received.

How is possible to accomplish the bold part?

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158

1 Answers1

3

Just call the JSON message converter yourself to create a TextMessage and print it before sending; same thing on the consuming side, receive a text message, print it, and then use the converter in your code to convert to the object.

EDIT

Another alternative would be to subclass the converter and do the logging after/before conversion.

EDIT

Here's an example:

@SpringBootApplication
public class So51251864Application {

    public static void main(String[] args) {
        SpringApplication.run(So51251864Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template) {
        return args -> template.convertAndSend("foo", new Foo("baz"));
    }

    @Bean
    public MessageConverter converter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter() {

            @Override
            public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
                TextMessage message = (TextMessage) super.toMessage(object, session);
                System.out.println("outbound json: " + message.getText());
                return message;
            }

            @Override
            public Object fromMessage(Message message) throws JMSException, MessageConversionException {
                System.out.println("inbound json: " + ((TextMessage) message).getText());
                return super.fromMessage(message);
            }

        };
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("type");
        return converter;
    }

    @JmsListener(destination = "foo")
    public void listen(Foo foo) {
        System.out.println(foo);
    }

    public static class Foo {

        private String bar;


        public Foo() {
            super();
        }

        public Foo(String bar) {
            this.bar = bar;
        }

        public String getBar() {
            return this.bar;
        }

        public void setBar(String bar) {
            this.bar = bar;
        }

        @Override
        public String toString() {
            return "Foo [bar=" + this.bar + "]";
        }

    }

}

and

outbound json: {"bar":"baz"}
inbound json: {"bar":"baz"}
Foo [bar=baz]
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • I see, pass to manually mode. I thought through AOP or a special interceptor available within the current API, it would be done without remove the automatic conversion process. – Manuel Jordan Jul 10 '18 at 13:23
  • 1
    You can do it on the sending side with `JmsTemplate.convertAndSend()` with a `MessagePostProcessor` (extract the text after conversion). But there's no equivalent on the receiving side. I will add another alternative to the answer. – Gary Russell Jul 10 '18 at 13:30
  • Thank You. Seems the problem is now for the receiver, I have an interface that has declared a method with a parameter type (a `POJO` type), it is implemented for many listeners types, such as JMS and AMQP, thus I am not able to change the signature to JMS branch `TextMessage`. I could work around with `default` methods but ... – Manuel Jordan Jul 10 '18 at 16:10