使用activeMQ发送ObjectMessage类型时,遇到javax.jms.JMSException: Failed to build body from bytes. Reason: java.io.IOException类型错误,经过一番折腾,终于解决。详情如下:
本项目所用的activeMQ版本为5.8.0,所要实现的publisher与subscriber分属两个不同的application。测试阶段,实现比较简单,publisher实现为java application,subscriber实现为web application。因为发送的消息内容比较复杂,所以采用ObjectMessage类型的消息。自己定义了AlarmMessage类,发送的消息是ArrayList<AlarmMessage>。AlarmMessage类实现比较简单,根据自己的需要,添加所需要传递的field。唯一需要注意的是:需要实现Serializable接口
消息发送端代码:
public void sendMsg(final ArrayList<AlarmMessage> list) {
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
ObjectMessage msg=session.createObjectMessage();
msg.setObject(list);
return msg;
}
});
}
消息接收端。因为实现了MessageListener接口,所以需要实现OnMessage方法。OnMessage方法的参数为Message类型,为了消息类型的一致而使得activeMQ能够识别,需要进行消息类型转换,具体代码如下:(如果使用了MessageListenerAdapter,需要自定义MessageConverter,实现类似OnMessage方法中的)
public void onMessage(Message message) {
// TODO Auto-generated method stub
if(!(message instanceof ObjectMessage)){
throw new MessageConversionException("Message isn't a ObjectMessage");
}
try {
ObjectMessage msg=(ObjectMessage) message;
ArrayList<AlarmMessage> list=(ArrayList<AlarmMessage>) msg.getObject();
// AlarmMessage alarmMsg=(AlarmMessage) msg.getObject();
System.out.println("The first Message Received:"+list.get(0).toString());
} catch (JMSException e) {
e.printStackTrace();
}
}
因为publisher和subscriber端都需要解析AlarmMessage类型的消息,所以把publisher端AlarmMessage的实现类直接复制到subscriber项目下。分别运行publisher和subscriber端,发送端没有问题,然后接收端运行到msg.getObject()方法时,抛出如下异常:
javax.jms.JMSException: Failed to build body from bytes. Reason: java.io.IOException: xxx.xxx.xxx.xxx.xxx.bean.AlarmMessage
经过一番google,尤其是在activeMQ官方forum中(http://activemq.2283324.n4.nabble.com/ActiveMQ-User-f2341805.html)终于找到了答案, 原来是subscriber端找不到AlarmMessage类。前面已经说过,subscriber端实现为web application,跑在tomcat下,而AlarmMessage类直接作为项目源代码的一部分,为什么会找不到AlarmMessage很不可理解。也没去深究, 直接把AlarmMessage编译后的类文件打成jar包,放在subscriber的lib文件夹下。再次运行,竟然可以了。