Search code examples
activemq-classicspring-jmsactivemq-artemis

Upgrading From ActiveMQ "Classic" to ActiveMQ Artemis - class java.util.ArrayList is not a valid property type


I am upgrading ActiveMQ "Classic" to ActiveMQ Artemis while maintaining client code. I have multiple places code looking like this.

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);

    }

}

How do I fix below error coming from above code.

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)

In ActiveMQ "Classic" we can set trusted packages in connection factory. How do I do it in ActiveMQ Artemis?


Solution

  • This problem has nothing to do with setting the trusted packages on the JMS ConnectionFactory.

    The problem is that your application is implicitly using this JMS "extension" provided by ActiveMQ "Classic." As the documentation states:

    This JMS extension feature allows you to attach Map and List properties to any JMS Message or to use nested Maps and Lists inside a MapMessage. [emphasis mine]

    When you pass the Map<String, Object> variable map to JmsTemplate.convertAndSend it uses the default SimpleMessageConverter to convert that Map into a javax.jms.MapMessage. As the JavaDoc for MapMessage states:

    The names are String objects, and the values are primitive data types in the Java programming language. [emphasis mine]

    In other words, according to the JMS specification the values in the MapMessage can only be primitive data types. However, ActiveMQ "Classic" provides an extension which allows using List implementations. Code which uses this extension is not portable to other JMS brokers since it does not adhere to the JMS specification. This is why ActiveMQ Artemis throws the error ActiveMQPropertyConversionException: class java.util.ArrayList is not a valid property type.

    You will either have to change your application code to adhere to the JMS specification (i.e. use primitive data types in the values of your Map) or this same extension will have to be implemented by ActiveMQ Artemis.