我们将ActiveMQ 5.8.0与Spring JMS 3.2.3.RELEASE结合使用 . 应用程序使用Spring DefaultMessageListenerContainer
侦听队列,并使用Spring MappingJackson2MessageConverter
将对象存储在 ActiveMQTextMessage
中 .
我们还使用ActiveMQ代理重新传递插件,该插件在 activemq.xml
中配置 . 消息保存在Oracle数据库中,也在 activemq.xml
中配置 .
现在我们遇到以下问题:在重新传递的大约60%的消息中,缺少 MappingJackson2MessageConverter
在消息上设置的 javaClass
属性 . 这会导致以下堆栈跟踪:
org.springframework.jms.support.converter.MessageConversionException: Could not find type id property [javaClass]
at org.springframework.jms.support.converter.MappingJackson2MessageConverter.getJavaTypeForMessage(MappingJackson2MessageConverter.java:360)
at org.springframework.jms.support.converter.MappingJackson2MessageConverter.fromMessage(MappingJackson2MessageConverter.java:176)
在检查数据库中的持久消息时,我们发现 javaClass
属性确实丢失了 . 但是 RedeliveryPlugin
设置的 redeliveryDelay
和 AMQ_SCHEDULED_DELAY
属性存在 .
这可能是由ActiveMQ中的错误引起的吗?我看到 RedeliveryPlugin.scheduleRedelivery()
将 marshalledProperties
设置为null,这应该是正确的行为,以确保所有属性都在 Message.beforeMarshall()
中序列化 . 但是如果属性是懒惰地创建的,并且还没有调用创建它们的方法(即 getProperty()
或其他类似的东西),那么将 marshalledProperties
清除掉在重新传递插件之前设置的属性 .
以下单元测试证明,使用 org.apache.activemq.command.Message
的当前实现可以实现此方案:
@Test
public void testGetPropertyAfterUnmarshallAndNullMarshalledProperties() throws IOException {
ActiveMQTextMessage msg = new ActiveMQTextMessage();
msg.setProperty(TYPEID_PROPERTY, TEST_CLASS);
OpenWireFormat wireFormat = new OpenWireFormat(CommandTypes.PROTOCOL_VERSION);
msg.beforeMarshall(wireFormat);
ByteSequence byteSequence = wireFormat.marshal(msg);
ActiveMQTextMessage unmarshalled = (ActiveMQTextMessage) wireFormat.unmarshal(byteSequence);
// simulate RedeliveryPlugin behaviour
unmarshalled.setMarshalledProperties(null);
assertNull(unmarshalled.getProperty(TYPEID_PROPERTY));
}
使用代理重新传递插件时有没有人看到过这种行为?我们开始使用代理插件,因为我们遇到了客户端重新传递机制的问题,所以回到那个不是一个选项 .