代码之家  ›  专栏  ›  技术社区  ›  Imran

原因:org.springframework.jms.support.converter。MessageConversionException:在消息上找不到类型id属性[_type]

  •  7
  • Imran  · 技术社区  · 7 年前

    我正在尝试这个spring JMS示例,它给出了错误。 https://spring.io/guides/gs/messaging-jms/ 原因: org.springframework.jms.support.converter.MessageConversionException: Could not find type id property [_type] on message from destination [queue://mailbox]

     @Bean // Serialize message content to json using TextMessage
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }
    

    4 回复  |  直到 7 年前
        1
  •  23
  •   Danylo Zatorsky    7 年前

    TypeIdPropertyName 是标识实体的属性的名称。Jackson映射器应该知道在反序列化传入的JSON时要使用什么实体。

    请求应如下所示:

    {  
       "_type" : "hello.Email",
       "to" : "Imran",
       "from" : "dzatorsky"
    }
    

    以下是更健壮的配置:

    @EnableJms
    @Configuration
    public class JmsListenerConfig implements JmsListenerConfigurer {
    
        @Bean
        public DefaultMessageHandlerMethodFactory handlerMethodFactory() {
            DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
            factory.setMessageConverter(messageConverter());
            return factory;
        }
    
        @Bean
        public MessageConverter messageConverter() {
            return new MappingJackson2MessageConverter();
        }
    
        @Override
        public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
            registrar.setMessageHandlerMethodFactory(handlerMethodFactory());
        }
    }
    

    /**
     * Used to convert JMS messages from/to JSON. Registered in Spring-JMS automatically via auto configuration
     */
    @Component
    public class JsonMessageConverter implements MessageConverter {
    
        @Autowired
        private ObjectMapper mapper;
    
        /**
         * Converts message to JSON. Used mostly by {@link org.springframework.jms.core.JmsTemplate}
         */
        @Override
        public javax.jms.Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
            String json;
    
            try {
                json = mapper.writeValueAsString(object);
            } catch (Exception e) {
                throw new MessageConversionException("Message cannot be parsed. ", e);
            }
    
            TextMessage message = session.createTextMessage();
            message.setText(json);
    
            return message;
        }
    
        /**
         * Extracts JSON payload for further processing by JacksonMapper.
         */
        @Override
        public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
            return ((TextMessage) message).getText();
        }
    }
    

    使用此配置,您可以跳过消息中恼人的“_type”字段。

        2
  •  3
  •   MattC Holger    7 年前

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

    Spring将自动将这个messageConverter与JmsTemplate一起使用(如果您正在使用的话)。“U型”可以是任何东西,但两边应该是一样的。

        3
  •  1
  •   Michail Alexakis    7 年前

    自定义(即应用程序级)“\u type”属性必须是(由其生产者)在消息上设置的JMS属性。消息负载中没有类型元数据。要了解JMS消息属性,应该访问 https://docs.oracle.com/javaee/7/api/javax/jms/Message.html

    与JSON属性混淆,JSON属性可以替代使用,并且必须配置基于Jackson的注释(例如多态反序列化)。在这种情况下,实际的消息负载(JSON字符串)被更改,并在顶级对象中包含一个“_type”属性。

        4
  •  0
  •   bushrat    4 年前

    @Component
    public class JsonMessageConverter implements MessageConverter {
    
        private final ObjectMapper mapper;
    
        public JsonMessageConverter(ObjectMapper mapper) {
            this.mapper = mapper;
        }
    
        @Override
        public javax.jms.Message toMessage(Object object, Session session) throws MessageConversionException {
            try {
                // send class=<json content>
                return session.createTextMessage(object.getClass().getName() + "=" + mapper.writeValueAsString(object));
            } catch (Exception e) {
                throw new MessageConversionException("Message cannot be serialized", e);
            }
        }
    
        @Override
        public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
            try {
                Matcher matcher = Pattern.compile("^([^=]+)=(.+)$").matcher(((TextMessage) message).getText());
                if (!matcher.find())
                {
                    throw new MessageConversionException("Message is not of the expected format: class=<json content>");
                }
                return mapper.readValue(matcher.group(2), Class.forName(matcher.group(1)));
            } catch (Exception e) {
                throw new MessageConversionException("Message cannot be deserialized", e);
            }
        }
    }