From 12159b98a2653041a40ca7b3c39f0f43d21fee0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Tue, 26 Sep 2023 12:26:39 +0200 Subject: [PATCH] Provide best-effort toString for Lazy resolved message Previously, MessagingMessageListenerAdapter or any adapter relying on the default MessagingMessageConverter would log an incoming message with a toString of the Message that does not provide any extra information. This is due to the default implementation providing a lazy resolution message that only attempts to extract the payload when necessary. This commit implements a toString method that uses the raw JMS message if the payload is not available. If it is, the payload is used instead. Closes gh-21265 (cherry picked from commit a37abd5e54ff66ad6784f2ff1e6c6cae6354a547) --- .../AbstractAdaptableMessageListener.java | 29 +++++++++++-- .../MessagingMessageListenerAdapterTests.java | 42 ++++++++++++++++++- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java index e4b9cd442617..e8d8fb8ce199 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -304,8 +304,8 @@ protected void handleResult(Object result, Message request, @Nullable Session se * @see #setMessageConverter */ protected Message buildMessage(Session session, Object result) throws JMSException { - Object content = preProcessResponse(result instanceof JmsResponse - ? ((JmsResponse) result).getResponse() : result); + Object content = preProcessResponse(result instanceof JmsResponse ? + ((JmsResponse) result).getResponse() : result); MessageConverter converter = getMessageConverter(); if (converter != null) { @@ -553,6 +553,29 @@ public MessageHeaders getHeaders() { } return this.headers; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + if (this.payload == null) { + sb.append(" [rawMessage=").append(this.message); + } + else { + sb.append(" [payload="); + if (this.payload instanceof byte[]) { + sb.append("byte[").append(((byte[]) this.payload).length).append(']'); + } + else { + sb.append(this.payload); + } + } + if (this.headers != null) { + sb.append(", headers=").append(this.headers); + } + sb.append(']'); + return sb.toString(); + } + } } diff --git a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java index 4e0d7bfa363c..20de38040740 100644 --- a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.MessageType; +import org.springframework.jms.support.converter.MessagingMessageConverter; import org.springframework.messaging.Message; import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory; @@ -340,6 +341,45 @@ public TextMessage testReplyWithJackson(String methodName, String replyContent) return responseMessage; } + @Test + void lazyResolutionMessageToStringProvidesBestEffortWithUnresolvedPayload() throws JMSException { + MessagingMessageListenerAdapter adapter = getSimpleInstance("echo", Message.class); + MessagingMessageConverter messagingMessageConverter = adapter.getMessagingMessageConverter(); + assertThat(messagingMessageConverter).isNotNull(); + TextMessage message = new StubTextMessage(); + assertThat(messagingMessageConverter.fromMessage(message)).isInstanceOfSatisfying(Message.class, msg -> + assertThat(msg.toString()).contains("rawMessage=").contains(message.toString()) + .doesNotContain("payload=").doesNotContain("headers=")); + } + + @Test + void lazyResolutionMessageToStringWithResolvedPayload() throws JMSException { + MessagingMessageListenerAdapter adapter = getSimpleInstance("echo", Message.class); + MessagingMessageConverter messagingMessageConverter = adapter.getMessagingMessageConverter(); + assertThat(messagingMessageConverter).isNotNull(); + TextMessage message = new StubTextMessage("Hello"); + assertThat(messagingMessageConverter.fromMessage(message)).isInstanceOfSatisfying(Message.class, msg -> { + msg.getPayload(); // force resolution + assertThat(msg.toString()).contains("payload=Hello") + .doesNotContain("rawMessage=").doesNotContain("headers="); + }); + } + + @Test + void lazyResolutionMessageToStringWithResolvedPayloadAndHeaders() throws JMSException { + MessagingMessageListenerAdapter adapter = getSimpleInstance("echo", Message.class); + MessagingMessageConverter messagingMessageConverter = adapter.getMessagingMessageConverter(); + assertThat(messagingMessageConverter).isNotNull(); + TextMessage message = new StubTextMessage("Hello"); + message.setJMSPriority(7); + assertThat(messagingMessageConverter.fromMessage(message)).isInstanceOfSatisfying(Message.class, msg -> { + msg.getPayload(); + msg.getHeaders(); // force resolution + assertThat(msg.toString()).contains("payload=Hello").contains("headers=").contains("jms_priority=7") + .doesNotContain("rawMessage="); + }); + } + protected MessagingMessageListenerAdapter getSimpleInstance(String methodName, Class... parameterTypes) { Method m = ReflectionUtils.findMethod(SampleBean.class, methodName, parameterTypes);