首页 文章

为什么messageConverter.fromMessage()没有转换arraylist? java.lang.ClassCastException:java.lang.String无法强制转换

提问于
浏览
-2

我想发送一条包含销售清单的JMS消息,并通过 onMessage() 接收它 . 据我所知, springframework.jms.support.converter.MessageConverter 应该扮演转换或转换消息的角色,所以我不必创建XSD或额外的映射类 . 我的意思是,我期待测试波纹管发送一条消息,并且 (SalesMessage) messageConverter.fromMessage(message) 足以转换并实现 SalesMessage 的对象 .

基本上,错误是 java.lang.ClassCastException: java.lang.String cannot be cast to ...SalesMessage .

我的考试

AnnotationConfigApplicationContext context;
MyMessageSender ms;
JmsListenerEndpointRegistry bean;

@Before
public void setUpBeforeClass() throws Exception {

    context =  new AnnotationConfigApplicationContext(AppConfig.class);
    ms = context.getBean(MyMessageSender.class);
}

@Test
public void test2() {

    Sale s = new Sale("product_type", 1L);
    List<Sale> l = new ArrayList<Sale>();
    l.add(s);

    SalesMessage sm = new SalesMessage(l, 1);

    ms.sendMessage(sm.toString());

    bean = context.getBean(JmsListenerEndpointRegistry.class);
    for (MessageListenerContainer listenerContainer : bean.getListenerContainers()) {
        DefaultMessageListenerContainer container = (DefaultMessageListenerContainer) listenerContainer;
        container.shutdown();
    }

}

MyJmsListener

@Component
    public class MyJmsListener {

         @Autowired
         private MessageConverter messageConverter;

        @JmsListener(destination = AppConfig.QUEUE_NAME)
        public void handleMessage(Message message) {
            try {
                System.out.println("received: "+message);
//this prints received: ActiveMQTextMessage {commandId = 5, ..., jmsXGroupFirstForConsumer = false, text = SalesMessage [sales=[Sale [product_type=produ...ssageType=1]}
                SalesMessage salesMessage = (SalesMessage) messageConverter.fromMessage(message); // <<< here is the focus of my question
                System.out.println("salesMessage: "+salesMessage);
            }
            catch(JMSException e) {
                 e.printStackTrace();
            }

        }
    }

Spring Config

@Configuration
@ComponentScan
@EnableJms
public class AppConfig {
    public static final String QUEUE_NAME = "example.queue";

    @Bean
    public ConnectionFactory connectionFactory() {
        ConnectionFactory connectionFactory =
                new ActiveMQConnectionFactory("vm://localhost");
        return connectionFactory;
    }

    @Bean
    public JmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        //core poll size=4 threads and max poll size 8 threads
        factory.setConcurrency("4-8");
        return factory;
    }

    @Bean
    MessageConverter converter(){
        return new SimpleMessageConverter();
    }
}

SalesMessage类

public class SalesMessage  implements Serializable{
    List<Sale> sales = new ArrayList<Sale>();
    int messageType;
    //getters/setters/toString()

销售课程

public class Sale  implements Serializable{
    private String product_type;
    private Long value;
//getters/setters/toString()

发送消息

@Component
public class MyMessageSender {

    @Autowired
    private ConnectionFactory connectionFactory;
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void init() {
        this.jmsTemplate = new JmsTemplate(connectionFactory);
    }

    public void sendMessage(String message) {
        System.out.println("sending: " + message);
        jmsTemplate.send(AppConfig.QUEUE_NAME, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(message);
            }
        });
    }
}

***编辑了Spring Config updqted

@Configuration
@ComponentScan
@EnableJms
public class AppConfig {
    public static final String QUEUE_NAME = "example.queue";

    @Bean
    public ConnectionFactory connectionFactory() {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
        return connectionFactory;
    }

    @Bean
    public JmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        // core poll size=4 threads and max poll size 8 threads
        factory.setConcurrency("4-8");
        return factory;
    }

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

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

***编辑当我在Listener一侧打印消息时,我得到了

received:ActiveMQObjectMessage {commandId = 5,responseRequired = true,messageId = ID:win10-cha-51561-1509914170598-4:2:1:1:1,originalDestination = null,originalTransactionId = null,producerId = ID:win10-cha -51561-1509914170598-4:2:1:1,destination = queue://example.queue,transactionId = null,expiration = 0,timestamp = 1509914232995,arrival = 0,brokerInTime = 1509914232995,brokerOutTime = 1509914233010,correlationId = null ,replyTo = null,persistent = true,type = null,priority = 4,groupID = null,groupSequence = 0,targetConsumerId = null,compressed = false,userID = null,content = org.apache.activemq.util.ByteSequence@24f339bf ,marshalledProperties = null,dataStructure = null,redeliveryCounter = 0,size = 1346,properties = null,readOnlyProperties = true,readOnlyBody = true,droppable = false,jmsXGroupFirstForConsumer = false}

和SalesMessage salesMessage =(SalesMessage)messageConverter.fromMessage(message)引发此异常

org.springframework.jms.support.converter.MessageConversionException:无法在目标[queue:]上找到消息[ID:win10-cha-51561-1509914170598-4:2:1:1:1]的类型id属性[_type] //example.queue]

在发送方面,我打印消息

SalesMessage [sales=[Sale [product_type=product_type, value=1]], messageType=1]

并且,这是我更新的完整应用程序配置(我按照提供的建议)

@Configuration
@ComponentScan
@EnableJms
public class AppConfig {
    public static final String QUEUE_NAME = "example.queue";

    @Bean
    public ConnectionFactory connectionFactory() {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
        return connectionFactory;
    }

    @Bean
    public JmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setConcurrency("4-8");
        factory.setMessageConverter(jacksonJmsMessageConverter());
        return factory;
    }

    @Bean 
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");


        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        converter.setObjectMapper(objectMapper);
        return converter;
    }
}

并且,这是我在最后一个建议之后发送消息的方式(重大更改是从jmsTemplate.send到jmsTemplate.convertAndSend):

@Component
public class MyMessageSender {

    @Autowired
    private ConnectionFactory connectionFactory;
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void init() {
        this.jmsTemplate = new JmsTemplate(connectionFactory);
    }

    public void sendMessage(SalesMessage  message) {
        System.out.println("sending: " + message);
        jmsTemplate.convertAndSend(AppConfig.QUEUE_NAME, message);
    }
}

***编辑

enter image description here

2 回答

  • 2

    咦?

    ms.sendMessage(sm.toString()); java.lang.ClassCastException:java.lang.String无法强制转换为... SalesMessage .

    那个's because you'以JSON格式发送 Stringsm.toString() )而不是 SalesMessage .

    使用 jmsTemplate.convertAnsSend(destinationName, sm) .

    听众容器工厂也需要Jackson转换器 .

  • 1

    我看到你在这里尝试做什么,你可能试图遵循这个例子:

    https://spring.io/guides/gs/messaging-jms/

    但是,该示例是在Spring Boot上 . 我有一种预感,那里没有 @SpringBootApplication 注释 .

    如果我需要使用SimpleMessageConverter快速调用DefaultJmsListenerContainerFactory.setMessageConverter方法,那么您必须手动执行此操作 .

    所以,它应该看起来像:

    @Bean
        public JmsListenerContainerFactory jmsListenerContainerFactory() {
            DefaultJmsListenerContainerFactory factory =
                    new DefaultJmsListenerContainerFactory();
            factory.setConnectionFactory(connectionFactory());
            factory.setMessageConverter(converter());
            factory.setConcurrency("4-8");
            return factory;
        }
    

    您还需要确保您的对象是可序列化的,然后您可以使用对象本身执行 jmsTemplate.send . 转换器将为您执行必要的转换为消息有效负载类型 .

相关问题