You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 04:45:46