我有两个用于测试MQ事件的应用程序。其中一个用于发送消息,另一个用于接收消息。它们都是SpringBoot应用程序。发送者应用程序运行在port: 8000上,接收程序运行在port: 8050上。
pom.xml
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>mq-jms-spring-boot-starter</artifactId>
<version>2.5.0</version>
</dependency>这是发送者的应用程序。
@SpringBootApplication
@EnableJms
@RestController
public class MqTestApplication {
private static final String ISSUER = "254874125487";
private static final String ACCOUNT_NO = "1234567890123";
@Autowired
private JmsTemplate jmsTemplate;
public static void main(String[] args) {
SpringApplication.run(MqTestApplication.class, args);
}
public Event getEvent() {
Event event = new Event();
Map<String, Object> argument = new HashMap<>();
argument.put("key-accNo", ACCOUNT_NO);
event.setMessageId(String.valueOf(UUID.randomUUID()));
event.setIssuer(ISSUER);
event.setType(EventType.ACCOUNT);
event.setName(EventName.OPEN_ACCOUNT);
event.setArgument(argument);
event.setDateTime(LocalDateTime.now());
return event;
}
@GetMapping("send/event")
public void sendEvent() {
try {
jmsTemplate.convertAndSend("DESTINATION", getEvent());
} catch (JmsException ex) {
ex.printStackTrace();
}
}
}接收机应用
@SpringBootApplication
@EnableSwagger2
@EnableJms
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}@Service
public class MQServiceImpl{
private final JmsTemplate jmsTemplate;
@Autowired
public MQServiceImpl(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
@JmsListener(destination = "DESTINATION")
public void receiveEvent() {
Event event = (Event) jmsTemplate.receiveAndConvert("DESTINATION");
System.out.println(event.toString());
}
}但是当我运行接收应用程序时,我会快速而持续地面对下面的异常。
DefaultMessageListenerContainer-1] WARN o.s.j.l.DefaultMessageListenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void .service.MQServiceImpl.receiveEvent()' threw exception; nested exception is org.springframework.jms.MessageFormatException: JMSCC0053: An exception occurred deserializing a message, exception: 'java.lang.ClassNotFoundException: null class'.; nested exception is com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCC0053: An exception occurred deserializing a message, exception: 'java.lang.ClassNotFoundException: null class'.
It was not possible to deserialize the message because of the exception shown.
Examine the linked exception for details of the error.
Caused by: org.springframework.jms.MessageFormatException: JMSCC0053: An exception occurred deserializing a message, exception: 'java.lang.ClassNotFoundException: null class'.; nested exception is com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCC0053: An exception occurred deserializing a message, exception: 'java.lang.ClassNotFoundException: null class'.
It was not possible to deserialize the message because of the exception shown.
Examine the linked exception for details of the error.我查了一下日志,但没有一个答案对我有帮助。如果有人想办法解决这个问题,我很感激。
更新
在发送方和接收方应用程序中,事件类都是这样的。
@Data
public class Event implements Serializable {
private static final long serialVersionUID = 2529600986924604571L;
private String messageId;
private String issuer;
private EventType type;
private EventName name;
private Map<String, Object> argument;
private LocalDateTime dateTime;
}发布于 2021-10-11 19:16:04
过了几天,我找到了答案。我应该将事件对象转换为JSON,然后从发送方应用程序发送它,并从发送方接收JSON,并将其转换为事件对象。实际上,我们不能通过MQ直接发送或接收对象。
发件人
String stringEvent = objectMapper.writeValueAsString(EVENT_OBJ);
jmsTemplate.convertAndSend(SEND_QUEUE_NAME, stringEvent);接收机
@Override
@JmsListener(destination = "${mq.receive_queue}")
public void receive(Message message) {
try {
String jsonEvent = ((TextMessage) message).getText();
Event event = objectMapper.readValue(jsonEvent, Event.class);
} catch (JMSException | IOException e) {
e.printStackTrace();
}
}发布于 2021-10-05 09:12:24
正如在注释中所暗示的那样,您的Event类需要是可序列化的,它看起来是可序列化的,侦听器代码应该如下所示:
@JmsListener(destination = "DESTINATION")
public void receiveEvent(Event event) {
...Spring将负责将对象序列化为@JmsListener注释的一部分。
尽管硬编码目标不是很好,但是您应该从application.properties中提取它。
如果您仍然得到一个
更新,那么正在触发的序列化将无法找到类。如果您的代码正在编译,那么您的类路径中可能有一个类
Event,但由于某种原因,它无法与接收应用程序所期望的对象兼容。
从表面上看,似乎您的Event对象是正确的,但是具有相同属性和相同serialVersionUID的类需要同时出现在发送方和接收方代码中。如果你改变了其中一种,那就必须存在于另一种。强制执行此操作的最简单方法是将类放入两个应用程序都使用的.jar中。如果对于发送方和接收方来说,Event类位于不同的包中,那么它将被视为不同的类。
如果您添加了@data注释,spring将为您处理大量的序列化锅炉板。例如:
import lombok.Data;
@Data
public class Event implements Serializable {
... 如果这仍然不起作用,那么您可以选择接收ObjectMessage并自己执行序列化。您可能会发现spring自动序列化失败的原因。
例如:
import javax.jms.ObjectMessage;
import java.io.Serializable;
@JmsListener(destination = "DESTINATION")
public void receiveEvent(ObjectMessage message) {
Serializable serObj = message.getObject();
try {
Event event = (Event) serObj;
...
} catch (ClassCastException e) {
...
}
...https://stackoverflow.com/questions/69436096
复制相似问题