ActiveMQBytesMessage读取报错:Message body is write-only问题咨询
解决ActiveMQBytesMessage的"Message body is write-only"异常
问题重现
编写JUnit测试断言ACK消息时,创建ActiveMQBytesMessage作为输出消息,调用messageHandlerBean.onMessage()后读取消息内容抛出异常。调试可见消息体已填充,但无法读取。
测试代码:
@ExtendWith(MockitoExtension.class) class MessageHandlerBeanTest { //... @Mock @InjectMocks MessageHandlerBean messageHandlerBean; private BytesMessage inputMsg; private BytesMessage outputMsg; void setMessageContent(String xml) { try { inputMsg.clearBody(); inputMsg.writeBytes(xml.getBytes(StandardCharsets.UTF_8)); // for some reason writeUTF() does not encode correctly } catch (JMSException e) { throw new RuntimeException(e); } } @BeforeEach void setUp() { //... inputMsg = new ActiveMQBytesMessage(); setMessageContent(envelope); outputMsg = new ActiveMQBytesMessage(); Mockito.when(currSession.createBytesMessage()).thenReturn(outputMsg); } @Test void valid_msg_returns_ok() throws Exception { messageHandlerBean.onMessage(inputMsg); Assertions.assertThat(outputMsg.getBodyLength()).isNotZero(); Assertions.assertThat(outputMsg.readUTF()).isEqualTo("<xml>...<xml>"); } }
抛出的异常:
javax.jms.MessageNotReadableException: Message body is write-only at org.apache.activemq.command.ActiveMQBytesMessage.checkWriteOnlyBody(ActiveMQBytesMessage.java:819) at org.apache.activemq.command.ActiveMQBytesMessage.initializeReading(ActiveMQBytesMessage.java:824) at org.apache.activemq.command.ActiveMQBytesMessage.getBodyLength(ActiveMQBytesMessage.java:182)
原因分析
ActiveMQBytesMessage存在写模式和读模式的切换机制:
- 刚创建的消息处于写模式,此时可以调用
writeBytes()等写入方法填充内容; - 写入完成后,消息仍保持写模式,直接调用
getBodyLength()、readUTF()等读取方法会触发"write-only"异常; - 必须显式切换到读模式才能读取消息体内容。
解决方案
在读取outputMsg之前,调用reset()方法将消息切换到读模式,并重置读取指针到消息体开头:
修改后的测试方法:
@Test void valid_msg_returns_ok() throws Exception { messageHandlerBean.onMessage(inputMsg); // 切换到读模式 outputMsg.reset(); Assertions.assertThat(outputMsg.getBodyLength()).isNotZero(); Assertions.assertThat(outputMsg.readUTF()).isEqualTo("<xml>...<xml>"); }
reset()方法会完成以下操作:
- 将消息从写模式切换为读模式;
- 重置消息体的读取指针到起始位置;
- 清除任何未完成的写入操作标记。
内容的提问来源于stack exchange,提问作者anat0lius
相关产品推荐
相关产品推荐

