1

I have an active MQ factory in a Spring Boot app, type ActiveMQConnectionFactory. Right after instantiating it I set the trusted packages to just java.lang since I want to be able to send/receive just Strings via JMS in my app.

See also here:

SpringBoot + ActiveMQ - How to set trusted packages?

https://stackoverflow.com/a/36622567/2300597

    @Bean(name="jmsConnectionFactory")
    public ConnectionFactory getJMSConnectionFactory(){
        _factory = new ActiveMQConnectionFactory(active_MQ_BrokerURL);
        ActiveMQConnectionFactory fct = ((ActiveMQConnectionFactory)_factory);
        fct.setTrustAllPackages(false);
        fct.setTrustedPackages(Arrays.asList("java.lang"));
        return _factory;
    }

And yet I am able to send other objects (not from package java.lang)?!
I don't get an Exception of some sort when sending them.

Why is that? What am I doing wrong?

NOTE: I am using org.springframework.jms.core.JmsTemplate to send the messages
(in case that matters). The template is linked to that factory.

    public void sendObjectMessage(final Serializable msg) {
        try {
            this.jmsTemplate.send(this.queue, new MessageCreator() {
                public Message createMessage(final Session session) throws JMSException {
                    return session.createObjectMessage(msg);
                }
            });
            logger.info("Success sending Object MQ message [{}]", msg);
        } catch (Exception e) {
            logger.error("Error sending Object MQ message [{}]", msg, e);
        }
    }
peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • FWIW, `ObjectMessage` objects depend on Java serialization to marshal and unmarshal their object payload. This process is generally considered unsafe (hence the need to explicitly "trust" certain packages). There are also a number of [other issues](http://jmesnil.net/weblog/2012/07/27/on-jms-objectmessage-and-its-pitfalls/) with using JMS `ObjectMessage` not related to security that make it a poor choice for most use-cases. I would encourage you to avoid `ObjectMessage` if at all possible. Given that you just want to use `String` I suggest using `java.jms.TextMessage`. – Justin Bertram Sep 01 '21 at 13:24

1 Answers1

1

You can run the code below to validate that it is not an ActiveMQ issue.

What is the consumer side of your code?

How are you confirming messages are not sent?

There is a candidate if the messages are not being received-- if Spring JMS is using the JMS 2.0 API jar, there is a new API call for ObjectMessage that could be bombing out under the covers.

import java.io.Serializable;
import java.util.Arrays;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;

public class JmsUrlTest {

    private static String brokerUrl = "tcp://localhost:61616";
    private static ActiveMQConnectionFactory activemqConnectionFactory = new ActiveMQConnectionFactory("admin", "admin", brokerUrl);
    
    public static void main(String[] args) {
        
        try {
            activemqConnectionFactory.setTrustedPackages(Arrays.asList("java.lang"));
            
            Connection connection = activemqConnectionFactory.createConnection();
            connection.start();
            
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer = session.createProducer(session.createQueue("OBJECT.TEST"));
            
            Message message = session.createObjectMessage(new String("Test object"));
            message.setJMSType("java.lang.String");
            messageProducer.send(message);
            System.out.println("Sent message " + message.getJMSMessageID());
            
            MessageConsumer messageConsumer = session.createConsumer(session.createQueue("OBJECT.TEST"));
            
            boolean stop = false;
            int loopCount = 0;
            int maxLoops = 10;
            Message recvMessage = null;
            do {
                recvMessage = messageConsumer.receive(2000l);
                
                if(recvMessage != null || loopCount >= maxLoops) {
                    stop = true;
                }
            
            } while (!stop);
        
            
            if(recvMessage != null && ObjectMessage.class.isAssignableFrom(recvMessage.getClass())) {
                ObjectMessage recvObjectMessage = ObjectMessage.class.cast(recvMessage);
                Serializable recvSerializableBody = recvObjectMessage.getObject();
                
                if(recvSerializableBody.getClass().isAssignableFrom(String.class)) {
                    System.out.println("Recieved ObjectMessage w/ String body: " + String.class.cast(recvSerializableBody));
                } else {
                    System.out.println("Received body was not a String.class");
                }
            } else {
                System.out.println("No message received");
            }
            
        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            
        }
    }
}
Matt Pavlovich
  • 4,087
  • 1
  • 9
  • 17
  • What is the expected behavior? I thought I will get an exception? Are you saying the expected behavior is that messages are simply silently not sent (when they are outside the trusted packages)? – peter.petrov Sep 01 '21 at 14:04
  • I mean... I thought I will get an exception when sending the message. – peter.petrov Sep 01 '21 at 14:10
  • No, I would expect an exception as well. I'm saying, the code above can validate that it is not ActiveMQ. Spring / Spring JMS may be doing something problematic. – Matt Pavlovich Sep 01 '21 at 14:52