ActiveMQ Classic升级Artemis遇ArrayList属性错误及信任包配置问题
问题描述
在保留客户端代码的前提下将ActiveMQ Classic升级到ActiveMQ Artemis,现有客户端代码如下:
import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jms.core.JmsTemplate; public class TestV { public static void main(String[] args) throws IOException { ApplicationContext ctx = new ClassPathXmlApplicationContext("root.xml"); JmsTemplate jms = ctx.getBean(JmsTemplate.class); Map<String, Object> map = new HashMap<>(); List<Integer> ids = new ArrayList<>(); ids.add(10); ids.add(20); map.put("ids", ids); map.put("updated", true); jms.convertAndSend("mytest", map); } }
运行代码时出现如下错误:
Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException: class java.util.ArrayList is not a valid property type at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:311) at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:185) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:507) at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:584) at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:661) at com.mycompany.adhoc.TestV.main(TestV.java:33) Caused by: javax.jms.JMSException: org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException: class java.util.ArrayList is not a valid property type at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:54) at org.apache.activemq.ActiveMQConnection.syncSendPacket(ActiveMQConnection.java:1404) at org.apache.activemq.ActiveMQConnection.syncSendPacket(ActiveMQConnection.java:1437) at org.apache.activemq.ActiveMQConnection.syncSendPacket(ActiveMQConnection.java:1324) at org.apache.activemq.ActiveMQSession.send(ActiveMQSession.java:1981) at org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:288) at org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:223) at org.apache.activemq.ActiveMQMessageProducerSupport.send(ActiveMQMessageProducerSupport.java:241) at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:634) at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:608) at org.springframework.jms.core.JmsTemplate.lambda$send$3(JmsTemplate.java:586) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:504)
需解决两个问题:
- 如何修复上述运行错误?
- ActiveMQ Classic中可在连接工厂设置信任包,ActiveMQ Artemis中该如何操作?
解决方案
1. 修复运行错误
错误根源是Spring的JmsTemplate.convertAndSend默认会把Map里的键值对转成JMS消息的属性(Properties),但ActiveMQ Artemis对JMS属性的类型限制严格——JMS规范里属性仅支持基本类型、String及其数组,ArrayList不属于合法的属性类型。
无需修改TestV类的业务逻辑,只需调整Spring配置中的JmsTemplate,让它把整个Map作为**消息体(Message Body)**发送,而非拆分为属性。具体配置如下:
方案1:使用SimpleMessageConverter
在Spring XML配置文件(root.xml)中给JmsTemplate配置消息转换器:
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="messageConverter"> <bean class="org.springframework.jms.support.converter.SimpleMessageConverter"/> </property> </bean>
方案2:使用Jackson做JSON序列化(推荐)
如果需要更好的跨语言兼容性,可配置Jackson转换器:
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="messageConverter"> <bean class="org.springframework.jms.support.converter.MappingJackson2MessageConverter"> <property name="targetType" value="TEXT"/> <property name="objectMapper" ref="objectMapper"/> </bean> </property> </bean> <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
配置后,convertAndSend会将整个Map序列化为消息体,不会触发Artemis的属性类型校验错误。
2. ActiveMQ Artemis设置信任包
ActiveMQ Artemis的信任包配置分客户端和服务端两种场景:
客户端配置
若客户端需要信任特定包的序列化类,可在连接工厂配置中设置:
- Spring XML配置方式:
<bean id="connectionFactory" class="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory"> <constructor-arg value="tcp://localhost:61616"/> <!-- 信任所有包(测试环境可用) --> <property name="trustAllPackages" value="true"/> <!-- 或指定具体信任的包 --> <!-- <property name="trustedPackages" value="java.util,com.mycompany.model"/> --> </bean>
- 编程式创建连接工厂方式:
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); factory.setTrustAllPackages(true); // 或指定具体包:factory.setTrustedPackages(Arrays.asList("java.util", "com.mycompany.model"));
服务端配置
若服务端需要信任特定包以反序列化消息,修改Artemis核心配置文件broker.xml,在<core>节点下添加配置:
<core> <!-- 其他原有配置 --> <serialization-enabled>true</serialization-enabled> <!-- 指定信任的包 --> <trusted-packages> <package>java.util</package> <package>com.mycompany.model</package> </trusted-packages> <!-- 或信任所有包(生产环境不推荐) --> <!-- <trust-all-packages>true</trust-all-packages> --> </core>
内容的提问来源于stack exchange,提问作者chege
相关产品推荐
相关产品推荐

