如何在Spring Boot中使用JMS和ActiveMQ“Classic”发送自定义对象?

How to send a custom object using JMS & ActiveMQ "Classic" in Spring Boot?

提问人:bro 提问时间:9/25/2023 最后编辑:Justin Bertrambro 更新时间:9/26/2023 访问量:71

问:

我正在尝试使用 ActiveMQ“Classic”发送。为此,我创建了两个 Spring Boot 项目 - customer 和 producer。我使用下面的代码从生产者发送。ObjectMessage

@GetMapping("/send-letter")
public String sendLetter() {
    var letter = new Letter("Hello " + UUID.randomUUID(), "Jack", "Jill");

    template.convertAndSend("test_letter", letter);
    return "Letter sent!";
}

然后,我使用下面的代码在客户中捕获该对象。

@JmsListener(destination = "test_letter")
public void getTest(Letter letter) {
    System.out.printf("From %s to %s with content %s", letter.getSender(), letter.getReceiver(), letter.getContent());
}

另外,这是我对文件的配置。我也尝试使用参数,但没有任何效果。application.yamltrust-all: true

spring:
  activemq:
    broker-url: tcp://localhost:61616
    user: admin
    password: admin
    packages:
      trusted: com.example.demo.Entities.Letter

完全相同的结构适用于字符串。

正如我从管理面板中看到的那样,我能够将它发送到 ActiveMQ,但是当我运行侦听器时,它会抛出一堆错误,我将这些错误放在下面:ObjectMessage

org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.example.demo.controller.MessageConsumer.getTest(com.example.demo.Entities.Letter)' threw exception
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:118) 
Caused by: org.springframework.jms.support.converter.MessageConversionException: Could not convert JMS message
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:255) 
Caused by: jakarta.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.example.demo.Entities.Letter! 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:49) ~[activemq-client-jakarta-5.18.2.jar:5.18.2]
Caused by: java.lang.ClassNotFoundException: Forbidden class com.example.demo.Entities.Letter! 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 

我通过阅读本教程编写了代码。我阅读并尝试了我能找到的所有答案(包括将对象转换为字节),但我无法使它们工作。

我期待在客户控制台中看到对象。

spring-boot JMS ActiveMQ

评论


答:

1赞 Justin Bertram 9/26/2023 #1

看起来您配置了受信任的包以使用名(即 )而不是名(即 )。请尝试改用它:com.example.demo.Entities.Lettercom.example.demo.Entities

spring:
  activemq:
    broker-url: tcp://localhost:61616
    user: admin
    password: admin
    packages:
      trusted: com.example.demo.Entities

也就是说,您应该尽可能避免使用 JMS。它们依靠 Java 序列化来封送和取消封送其对象有效负载。这不仅速度慢,而且通常也被认为是不安全的,因为恶意负载可以利用主机系统。为此已经创建了许多 CVE,这就是为什么您必须首先显式配置哪些包是受信任的。使用还限制了体系结构的灵活性,因为非 JMS 客户端无法使用它们。ObjectMessageObjectMessage

我强烈建议为您的消息使用其他格式,e.g. JSON、XML、Protobuf 等。这将更快、更安全,并且与其他语言和协议广泛兼容,使您的架构更加健壮。