java 无法将类型的对象转换为 JMS 消息。支持的消息负载有:字符串、字节数组、Map<String,?>、Serializable 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41676959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:02:40  来源:igfitidea点击:

Cannot convert object of type to JMS message. Supported message payloads are: String, byte array, Map<String,?>, Serializable object

javajmsactivemq

提问by Hassen Bennour

I am developing Spring + ActiveMQ + JMSexample. In this example, I am facing the below error: I tried with Many options but not working at all.

我正在开发Spring + ActiveMQ + JMS示例。在此示例中,我面临以下错误:我尝试了许多选项,但根本不起作用。

I am looking to implement the following:

我正在寻求实施以下内容:

1) Queue should be keep reading messages (either using the Converter or listener)

1) 队列应该保持读取消息(使用转换器或侦听器)

2) Based on the InstructionMessage type I have to take decision on where to send it or not.

2) 根据 InstructionMessage 类型,我必须决定将其发送到何处。

The code uploaded at : https://github.com/test512/spring-mvc-jms-tutorials

代码上传于:https: //github.com/test512/spring-mvc-jms-tutorials

Sending person InstructionMessage [instructionType=10, productCode=10, quantity=10, uOM=10, timeStamp=10]
Exception in thread "main" org.springframework.jms.support.converter.MessageConversionException: Cannot convert object of type [com.jms.testing.spring.InstructionMessage] to JMS message. Supported message payloads are: String, byte array, Map<String,?>, Serializable object.
    at org.springframework.jms.support.converter.SimpleMessageConverter.toMessage(SimpleMessageConverter.java:78)
    at org.springframework.jms.core.JmsTemplate.createMessage(JmsTemplate.java:651)
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:593)
    at org.springframework.jms.core.JmsTemplate.doInJms(JmsTemplate.java:562)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484)
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:559)
    at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:648)
    at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:639)
    at com.jms.testing.spring.SpringJmsPersonProducer.sendMessage(SpringJmsPersonProducer.java:18)
    at com.jms.testing.spring.SpringJmsMessageConverterExample.main(SpringJmsMessageConverterExample.java:16)

appContextWithMessageConverter.xml

appContextWithMessageConverter.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jms="http://www.springframework.org/schema/jms"
    xsi:schemaLocation="http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:jms.properties" />

    <bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${jms.brokerURL}" />
    </bean>

    <bean id="pooledJmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
        <property name="connectionFactory" ref="jmsConnectionFactory" />
        <property name="maxConnections" value="50" />
    </bean>

    <jms:listener-container container-type="default" connection-factory="pooledJmsConnectionFactory" acknowledge="auto" >
        <!-- <jms:listener destination="messageDestination" ref="messageDestination" /> -->
        <jms:listener destination="messageDestination" ref="myListener" />
    </jms:listener-container>

    <bean id="instructionMessageConverter" class="com.jms.testing.spring.InstructionMessageConverter" />

    <bean id="myListener" class="com.jms.testing.spring.MyListener" />

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="pooledJmsConnectionFactory" />
        <property name="defaultDestination" ref="messageDestination" />
        <property name="receiveTimeout" value="${jms.receiveTimeout}" />
        <!-- <property name="messageConverter" ref="instructionMessageConverter" /> -->

    </bean>

    <bean id="springJmsPersonProducer" class="com.jms.testing.spring.SpringJmsPersonProducer">
        <property name="jmsTemplate" ref="jmsTemplate" />
    </bean>

    <bean id="springJmsPersonConsumer" class="com.jms.testing.spring.SpringJmsPersonConsumer">
        <property name="jmsTemplate" ref="jmsTemplate" />
    </bean> 

    <bean id="messageDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="messageQueue1" />
    </bean>
</beans>

MyListener.java

我的监听器

public class MyListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        MapMessage mapMessage = (MapMessage) message;

        try {
            int instructionType = Integer.parseInt(mapMessage.getString("instructionType"));
            int productCode = Integer.parseInt(mapMessage.getString("productCode"));
            int quantity = Integer.parseInt(mapMessage.getString("quantity"));
            int timeStamp = Integer.parseInt(mapMessage.getString("timeStamp"));
            int uOM = Integer.parseInt(mapMessage.getString("uOM"));
            InstructionMessage instructionMessage = new InstructionMessage(instructionType, productCode, quantity, uOM,
                    timeStamp);
            System.out.println(instructionMessage.toString());

        } catch (NumberFormatException | JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

InstructionMessage.java

指令消息.java

public class InstructionMessage implements Serializable{

private static final long serialVersionUID = 1L;
    private int instructionType;
    private int productCode;
    private int quantity;
    private int uOM;
    private int timeStamp;


    public InstructionMessage(int instructionType, int productCode, int quantity, int uOM, int timeStamp) {
        super();
        this.instructionType = instructionType;
        this.productCode = productCode;
        this.quantity = quantity;
        this.uOM = uOM;
        this.timeStamp = timeStamp;
    }

    public int getInstructionType() {
        return instructionType;
    }

    public void setInstructionType(int instructionType) {
        this.instructionType = instructionType;
    }

    public int getProductCode() {
        return productCode;
    }

    public void setProductCode(int productCode) {
        this.productCode = productCode;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public int getuOM() {
        return uOM;
    }

    public void setuOM(int uOM) {
        this.uOM = uOM;
    }

    public int getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(int timeStamp) {
        this.timeStamp = timeStamp;
    }

    @Override
    public String toString() {
        return "InstructionMessage [instructionType=" + instructionType + ", productCode=" + productCode + ", quantity="
                + quantity + ", uOM=" + uOM + ", timeStamp=" + timeStamp + "]";
    }
}

SpringJmsMessageConverterExample.java

SpringJmsMessageConverterExample.java

public class SpringJmsMessageConverterExample {
    public static void main(String[] args) throws URISyntaxException, Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "appContextWithMessageConverter.xml");

        try {
            SpringJmsPersonProducer springJmsProducer = (SpringJmsPersonProducer) context.getBean("springJmsPersonProducer");
            InstructionMessage m1 = new InstructionMessage(10,10,10,10,10);
            System.out.println("Sending person " + m1);
            springJmsProducer.sendMessage(m1);

            InstructionMessage m2 = new InstructionMessage(5,5,5,5,5);
            System.out.println("Sending person " + m2);
            springJmsProducer.sendMessage(m2);

            InstructionMessage m3 = new InstructionMessage(0,0,0,0,0);
            System.out.println("Sending person " + m3);
            springJmsProducer.sendMessage(m3);

            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

            SpringJmsPersonConsumer springJmsConsumer = (SpringJmsPersonConsumer) context.getBean("springJmsPersonConsumer");
            System.out.println("Consumer receives " + springJmsConsumer.receiveMessage());
        } finally {
            context.close();
        }
    }
}

SpringJmsPersonProducer.java

SpringJmsPersonProducer.java

public class SpringJmsPersonProducer {

    private JmsTemplate jmsTemplate;

    public JmsTemplate getJmsTemplate() {
        return jmsTemplate;
    }

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    public void sendMessage(final InstructionMessage instructionMessage) {
        getJmsTemplate().convertAndSend(instructionMessage);
    }
}

SpringJmsPersonConsumer.java

SpringJmsPersonConsumer.java

public class SpringJmsPersonConsumer {

    private JmsTemplate jmsTemplate;

    public JmsTemplate getJmsTemplate() {
        return jmsTemplate;
    }

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    public InstructionMessage receiveMessage() throws JMSException {
        InstructionMessage instructionMessage = (InstructionMessage) getJmsTemplate().receiveAndConvert();
        return instructionMessage;  
    }
}

回答by Hassen Bennour

simply add a generated serial Version ID and not default 1L!

只需添加一个生成的序列版本 ID 而不是默认的 1L!

public class InstructionMessage implements Serializable{

private static final long serialVersionUID = -295422703255886286L;

UPDATE :

更新 :

1)to make your listener working fine, you need to update destination="messageQueue1because with messageDestinationcontainer create this queue and your messages are sent to messageQueue1:

1)为了使您的侦听器正常工作,您需要更新destination="messageQueue1因为使用messageDestination容器创建此队列并将您的消息发送到messageQueue1

<jms:listener-container container-type="default"
    connection-factory="pooledJmsConnectionFactory" acknowledge="auto">
    <jms:listener destination="messageQueue1" ref="myListener" />
</jms:listener-container>

and update MyListener

并更新MyListener

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

public class MyListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {
            ObjectMessage mapMessage = (ObjectMessage) message;
            InstructionMessage instructionMessage = (InstructionMessage) mapMessage.getObject();
            System.out.println(instructionMessage.toString());
        } catch (NumberFormatException | JMSException e) {
            e.printStackTrace();
        }
    }
}

2) conditional send

2) 条件发送

import org.springframework.jms.core.JmsTemplate;

public class SpringJmsPersonProducer {

    private JmsTemplate jmsTemplate;

    public JmsTemplate getJmsTemplate() {
        return jmsTemplate;
    }

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    public void sendMessage(final InstructionMessage instructionMessage) {
        if (canSend(instructionMessage)) {
            getJmsTemplate().convertAndSend(instructionMessage);
        } else {
            throw new IllegalArgumentException("message");
        }
    }

    private boolean canSend(InstructionMessage instructionMessage) {
        return instructionMessage.getQuantity() > 0;
    }
}

回答by Jacek Cz

JMS moves data to different JVM. Cannot be done with ordinary objects. Must be serialised, so require to implement interface Serializable Suppose such can be done, ask main architect

JMS 将数据移动到不同的 JVM。不能用普通物体完成。必须序列化,所以需要实现接口Serializable 假设可以做到,请教主架构师

import java.io.Serializable;
...
public class InstructionMessage implements Serializable {

 private static final long serialVersionUID = 7526472295622776147L;

....
}

Background: network don't understand Java objects, can only transfer bytes. Is is basic for Java development, any book can be helpful (Thinking in Java by Eckel)

背景:网络不懂Java对象,只能传输字节。是 Java 开发的基础,任何书都可以提供帮助(Thinking in Java by Eckel)

EDIT: partial answer (try to answer) to You changed (with Serializable) code. Now ClassCastExceptionexception says: sending and receiving part are mutual not compatible. Framework or server made conversion InstructionMessage -> HashMap, I guess on early stages.

编辑:部分回答(尝试回答)您更改了(使用Serializable)代码。现在ClassCastException异常说:发送和接收部分是相互不兼容的。框架或服务器进行了转换 InstructionMessage -> HashMap,我猜是在早期阶段。

I guess too, but here I'm almost sure, HashMap content is functionally the same.

我想也是,但在这里我几乎可以肯定,HashMap 内容在功能上是相同的。

Your simplest, but not elegant way is to leave InstructionMessage and work with HashMap on both side (change sender), or debug a problem.

您最简单但不优雅的方法是离开 InstructionMessage 并在两侧使用 HashMap(更改发送者),或者调试问题。

If I remember, You remove Converter class java, but remain in XML. I'm NOT a big Spring fan (personally hate "xml programming"), I guess some correction in XML can help

如果我记得,您删除了 Converter 类 java,但保留在 XML 中。我不是 Spring 的忠实粉丝(个人讨厌“xml 编程”),我想在 XML 中进行一些更正会有所帮助

回答by New Bee

Use Hymanson conversion instead, handy in an event driven system where multiple event's objects need to trigger

改用 Hymanson 转换,在需要触发多个事件对象的事件驱动系统中很方便

@Bean
public JmsTemplate jmsTemplate() {
    JmsTemplate template = new JmsTemplate();
    template.setConnectionFactory(connectionFactory());
    template.setMessageConverter(HymansonJmsMessageConverter());
    template.setPubSubDomain(true);
    return template;
}

@Bean
public MessageConverter HymansonJmsMessageConverter() {
    MappingHymanson2MessageConverter converter = new MappingHymanson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_type");
    return converter;
}

and then set

然后设置

containerFactory.setMessageConverter(HymansonJmsMessageConverter());

containerFactory.setMessageConverter(HymansonJmsMessageConverter());

that's it.

而已。