如何在MappingJackson2MessageConverter中设置typeIdPropertyName

时间:2016-04-06 09:50:56

标签: activemq spring-jms

使用Spring4 + ActiveMQ,我想从队列接收JMS消息,并自动转换为POJO。 所以我将MappingJackson2MessageConverter添加到DefaultJmsListenerContainerFactory

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

    // some other config

    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("???");
    factory.setMessageConverter(converter);

    return factory;
}

这是我的听众配置

@JmsListener(destination = "queue.fas.flight.order", containerFactory = "jmsListenerContainerFactory")
public void processOrder(OrderRegisterDto registerParam) {
    System.out.println(registerParam.toString());
}

问题是,我不知道如何设置TypeIdPropertyName。队列不受我的控制,其他人则发送JSON

我想要一个通用转换器。所以我使用String接收消息,并手动将其转换为POJO。
@JmsListener(destination = "xxxx", containerFactory = "xxxxx") public void order(String registerParam) { try{ OrderRegisterDto dto = objectMapper.readValue(registerParam,OrderRegisterDto.class); }catch (IOException e){ // TODO } }
还有更好的方法吗?

3 个答案:

答案 0 :(得分:7)

转换器希望发件人在邮件属性中提供转换的类型信息。

String typeId = message.getStringProperty(this.typeIdPropertyName);

typeId可以是类名,也可以是typeId映射图中条目的键。

如果您的消息不包含任何类型信息,则需要对转换器进行子类化并覆盖getJavaTypeForMessage()以返回目标类的杰克逊JavaType,例如:

return TypeFactory.defaultInstance().constructType(Foo.class);

如果它是常量而不依赖于消息中的某些信息,则可以在子类中创建静态字段。

答案 1 :(得分:0)

这项工作:

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {

    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

    factory.setConnectionFactory(connectionFactory);


    factory.setConcurrency("3-10");


    // Este es el convertidor por defeto de Spring.
    SimpleMessageConverter s = new SimpleMessageConverter();

    MappingJackson2MessageConverter s2 = new MappingJackson2MessageConverter();
    s2.setTargetType(MessageType.BYTES);
    s2.setTypeIdPropertyName("DocumentType");

    factory.setMessageConverter(s2);  // or "s"

    return factory;
}

这是听众:

@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = ORDER_QUEUE)
@Payload final ) {
public void receiveMessage(Session ses, @Payload final Message<Product> message, @Headers final Map<String, Object> headers)  {


}

和Javascript STOMP客户端:

 var product = {
              productId : "111",
              name : "laptop",
              quantity: 2
            }
 var beforeSend = JSON.stringify(product);
 stompClient.send(destinationProductProd_02,{"DocumentType":"org.jms.model.Product"}, beforeSend);  // OK

注意我将“DocumentType”STOMP标头添加到要发送的消息中。您需要发送Java类的完整包路径。

答案 2 :(得分:0)

似乎没有简单的解决方案在 @JmsListener 中自动将JSON转换为POJO,而消息中没有“ type header”。但是可以使用Jackson的ObjectMapper在您的代码中明确地做到这一点:

@Autowired
private ObjectMapper objectMapper;

@JmsListener(destination = "...", containerFactory = "...")
public void processOrder(String payload) {
    OrderRegisterDto dto = objectMapper.readValue(payload, OrderRegisterDto.class);
    System.out.println(dto.toString());
}

别忘了在配置中删除 MappingJackson2MessageConverter

  

MappingJackson2MessageConverter转换器=新的MappingJackson2MessageConverter();    factory.setMessageConverter(converter);