JMS 消息侦听器执行失败 - ClassNotFoundException

问题描述 投票:0回答:1

我有两个完全独立的应用程序。一个应用程序向 ActiveMQ 代理(ActiveMQ 版本 5.18.2)上的队列发送一条消息,另一个应用程序应该接收该消息。这两个应用程序都使用 Spring Boot 版本 2.4.1。

我可以看到消息已被代理接收,然后被消费者应用程序消费。问题是消费者无法转换 JMS 消息,因为它首先没有找到用于构建消息的类。

我的生产者应用程序的粗略实现:

@SpringBootApplication
public class MyProducerApplication implements ApplicationRunner{

    private static Logger log = LoggerFactory.getLogger(MyProducerApplication.class);
    
    @Autowired
    private FooMessageSender fooMessageSender;
    
    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        log.info("Spring Boot Embedded ActiveMQ Configuration Example");
        
        final MyObjectMessage msg =  new MyObjectMessage(MyObjectMessage.type);
        ...
        //msg setter methods here
        ...

        fooMessageSender.send("remotingQueue", msg);
    }

FooMessageConverter:

它使用以下 ObjectMapper 类导入:

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class FooMessageConverter implements MessageConverter {

    private static final Logger LOGGER =
              LoggerFactory.getLogger(FooMessageConverter.class);

          ObjectMapper mapper;
          
          public FooMessageConverter() {
                mapper = new ObjectMapper();
              }
          
          @Override
          public Message toMessage(Object object, Session session)
              throws JMSException {
              final Message toSend = session.createObjectMessage((Serializable) object);

                return toSend;
          }

        @Override
        public Object fromMessage(Message message) throws JMSException, MessageConversionException {
            MyObjectMessage msg = null;
            if (message instanceof ActiveMQObjectMessage) {
            
                ObjectMessage objMessage = (ObjectMessage) message;
                msg = (MyObjectMessage) objMessage.getObject()
                }

            return msg;
        }

FooMessage:-不再使用

public class FooMessage implements Serializable {
    ...
    Message implementation here
    ...
}

我的消费者应用程序的实现:

@SpringBootApplication
public class myConsumer implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // TODO Auto-generated method stub
    }

FooMessageConverter
与 Producer 应用程序相同

QueueConsumer类:

@Component
public class QueueConsumer {
    private static Logger log = LoggerFactory.getLogger(QueueConsumer.class);

    @JmsListener(destination = "remotingQueue")
    public void receiveMessage(
            @Payload MyObjectMessage myMessage) {
        log.info("Q Message received: <" + myMessage + ">");
    }
}

FooMessageSender 类:

@Service
public class FooMessageSender {
private static Logger log = LoggerFactory.getLogger(FooMessageSender.class);
    
    @Autowired
    private JmsTemplate jmsTemplate;

    public void send(String queue, MyObjectMessage msg) {
        log.info("sending with convertAndSend() to queue <" + msg + ">");
        jmsTemplate.convertAndSend(queue, msg);
    }
}

我不确定应该如何配置

MessageConverter
才能正确发送和使用对象消息。我希望 FooMessageConverter 类是关键。

堆栈跟踪:(注意,我不允许将任何内容列入白名单,因此 ActiveMQ 建议将可以使用 ObjectMessages 交换的包列入白名单,但不适用于我的情况)

<WARN> [DefaultMessageListenerContainer-1] [2023-09-18 15:22:17,113] Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.package2.api.service.QueueConsumer.receiveMessage(com.otherpackage.MyObjectMessage)' threw exception; nested exception is org.springframework.jms.support.converter.MessageConversionException: Could not convert JMS message; nested exception is javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.otherpackage.MyObjectMessage! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:122) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318) [spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257) [spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189) [spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179) [spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076) [spring-jms-5.3.2.jar:5.3.2]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_291]
Caused by: org.springframework.jms.support.converter.MessageConversionException: Could not convert JMS message; nested exception is javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.otherpackage.MyObjectMessage! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:256) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter.extractPayload(AbstractAdaptableMessageListener.java:475) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.unwrapPayload(AbstractAdaptableMessageListener.java:542) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.getPayload(AbstractAdaptableMessageListener.java:524) ~[spring-jms-5.3.2.jar:5.3.2]
    at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:116) ~[spring-messaging-5.3.2.jar:5.3.2]
    at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:117) ~[spring-messaging-5.3.2.jar:5.3.2]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:148) ~[spring-messaging-5.3.2.jar:5.3.2]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-5.3.2.jar:5.3.2]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:114) ~[spring-jms-5.3.2.jar:5.3.2]
    ... 10 common frames omitted
Caused by: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.otherpackage.MyObjectMessage! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
    at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36) ~[activemq-client-5.16.0.jar:5.16.0]
    at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:213) ~[activemq-client-5.16.0.jar:5.16.0]
    at com.package2.api.service.FooMessageConverter.fromMessage(FooMessageConverter.java:61) ~[classes/:na]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:251) ~[spring-jms-5.3.2.jar:5.3.2]
    ... 18 common frames omitted
Caused by: java.lang.ClassNotFoundException: Forbidden class com.otherpackage.MyObjectMessage! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
    at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.checkSecurity(ClassLoadingAwareObjectInputStream.java:111) ~[activemq-client-5.16.0.jar:5.16.0]
    at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:56) ~[activemq-client-5.16.0.jar:5.16.0]
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1984) ~[na:1.8.0_291]
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848) ~[na:1.8.0_291]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158) ~[na:1.8.0_291]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665) ~[na:1.8.0_291]
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501) ~[na:1.8.0_291]
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459) ~[na:1.8.0_291]
    at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:211) ~[activemq-client-5.16.0.jar:5.16.0]
    ... 20 common frames omitted
classnotfoundexception spring-jms jmstemplate
1个回答
0
投票

如果您无法将任何包列入白名单以进行

ObjectMessage
反序列化,那么您根本无法使用
ObjectMessage
。必须配置
ObjectMessage
反序列化权限的全部原因是因为它本质上是不安全的。多年来,已经为此开放了多个 CVE,用于各种 JMS 实现。 更多避免的理由

ObjectMessage


Java(反)序列化速度很慢。
  • 它强制客户端和生产者在其类路径上具有相同的类(即
  • Object
  • 中的
    ObjectMessage
    )。
    此类消息与使用其他语言和/或协议的消费者不兼容,从而限制了应用程序的灵活性。
© www.soinside.com 2019 - 2024. All rights reserved.