【问题标题】:HornetQ - how to send and convert POJOHornetQ - 如何发送和转换 POJO
【发布时间】:2018-03-31 15:45:26
【问题描述】:

我在嵌入式模式下使用 HornetQ。

我正在尝试从发布者向消费者发送 POJO 对象:

public class Pojo implements Serializable {

    private Integer id;
    private String  name;
    private String  phone;

    // constructors, getters & setters
}

我的想法是将 POJO 转换为 Map 并通过 ClientMessage 发送每个属性。 (这样Consumer就可以通过POJO的属性来过滤消息了)

为了实现这一点,我正在使用 Jackson ObjectMapper。

出版商

ObjectMapper mapper = new ObjectMapper();
Map<String, Object> pojoMap = mapper.convertValue(new Pojo(13, "name", "phone"), new TypeReference<Map<String, Object>>() {});
pojoMap.forEach(message::putObjectProperty);
producer.send(message);

消费者

consumer.setMessageHandler(message -> {
    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    Pojo pojo = mapper.convertValue(mapJson, Pojo.class);
});

问题是在反序列化期间(在消费者中)ObjectMapper 抛出异常:

java.lang.IllegalArgumentException: Cannot deserialize instance of 'java.lang.String' out of START_OBJECT token
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: org.hornetq.core.example.Pojo["phone"])
...

据我了解,ObjectMapper 正在寻找“电话”值并想要一个字符串,但它找到了一个对象并崩溃了。

我该如何解决这个问题?

有其他选择吗?

我也尝试使用 Gson 代替 Jackson,但它返回相同的错误。

有趣的事实是,如果您发送一个没有任何字符串参数的对象,它可以正常工作。

(应该没有必要,但如果你愿意)在这里你可以找到以下的全部类:

【问题讨论】:

    标签: jackson gson pojo hornetq


    【解决方案1】:

    这并不是很明显,但是 Jackson 在反序列化 Jackson 不知道的 org.hornetq.api.core.SimpleString 时失败了。 Gson 也是如此,因为 SimpleString 不是标准类。

    你有两个选择:

    • 要么将传入的消息负载规范化为标准对象。
    • 或者实现一个自定义的SimpleString序列化器/反序列化器。

    选项 #1:标准化

    顺便说一句,Message.toMap() 也返回消息系统属性(PasteBin 中的代码似乎使用了它),因此它们可能与您的自定义对象属性发生冲突(我不使用 HornetQ,所以我可以使用错误的术语) . 我相信,属性应该像这样标准化:

    public static Map<String, Object> getNormalizedPropertiesFrom(final Message message) {
        return message.getPropertyNames()
                .stream()
                .collect(Collectors.toMap(
                        SimpleString::toString,
                        simpleString -> {
                            final Object objectProperty = message.getObjectProperty(simpleString);
                            if ( objectProperty instanceof SimpleString ) {
                                return objectProperty.toString();
                            }
                            return objectProperty;
                        }
                ));
    }
    

    这与Message.toMap() 不同,将丢弃durableaddressmessageIDexpirationtypeprioritytimestamp 等系统属性。 所以,你需要的是mapper.convertValue(getNormalizedPropertiesFrom(message), Pojo.class)

    选项 #2:自定义(反)序列化

    在这种情况下,您可以简化属性提取

    public static Map<SimpleString, Object> getPropertiesFrom(final Message message) {
        return message.getPropertyNames()
                .stream()
                .collect(Collectors.toMap(Function.identity(), message::getObjectProperty));
    }
    

    但是您的ObjectMapper 实例必须知道SimpleString 是如何(反)序列化的。 请注意ObjectMapper.convertValue()(我相信)在转换时使用中间对象,它需要用于这种情况的序列化程序(Message -> Map&lt;SimpleString, Object&gt; 通过自定义序列化 -> 一些中间表示 通过内置反序列化 -> Pojo)。

    final ObjectMapper objectMapper = new ObjectMapper()
            .registerModule(new SimpleModule()
                    .addSerializer(SimpleString.class, new JsonSerializer<SimpleString>() {
                        @Override
                        public void serialize(@Nonnull final SimpleString simpleString, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
                                throws IOException {
                            jsonGenerator.writeString(simpleString.toString());
                        }
                    })
            )
            .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    

    出于性能原因,您应该使用单个 ObjectMapper 实例。

    两个选项都会产生:

    Pojo{id=13, name=name, phone=phone}

    对于Pojo 类,

    {phone=phone, name=name, id=13}

    对于属性,以及类似的东西

    ClientMessage[messageID=8, durable=false, address=q49589558,userID=null,properties=TypedProperties[id=13,phone=phone,name=name]]

    用于客户端消息。

    【讨论】:

      猜你喜欢
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 2018-12-29
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      相关资源
      最近更新 更多