【问题标题】:How to send and receive data model object through Spring Integration message payload?如何通过 Spring Integration 消息负载发送和接收数据模型对象?
【发布时间】:2018-09-26 16:18:48
【问题描述】:

我正在尝试将数据模型 Java 对象发送到 Spring 集成消息通道。我有一个 jms 出站通道适配器。

这是我的 Java 代码。但它不起作用。

@Autowired
MessageChannel outputChannel;

@Override 
public void sendToOutputQueue() 
{
    Record record = new Record();
    Record.setId("123456789");
    Record.setSerialNum("10000000");
    Record.setCode("ABC");


    Map<String, Object> map = new HashMap<String, Object>();
    map.put("record", record);

    outputChannel.send(MessageBuilder.withPayload(map).build());

}

这是我的 Spring 集成配置

<int:channel id="outputChannel" />  

<int-jms:outbound-channel-adapter id="outboundChannelAdapter" channel="outputChannel" jms-template="outputQueueJmsTemplate" />

【问题讨论】:

  • does not work 表示的症状是什么?也许你在日志中有一些错误?也许你的Record 不是Serializable?
  • 我需要让我的记录可序列化吗?由于HashMap默认是可序列化的,我想我不需要让Record可序列化。
  • ???这不是 Java 中的工作方式。地图只是引用的容器。当然,键和值必须是 Serializable 才能传输到 JMS Broker 中。
  • 我使 Record 对象可序列化,并将对象传递给消息有效负载,而不将其转换为 Map。现在可以成功发送到MQ了。
  • 请不要为我复制 cmets。这听起来像是垃圾邮件。

标签: spring jms spring-integration spring-jms


【解决方案1】:

当您使用JmsTemplate 将Map 发送到JMS 时,它会被包装到MapMessage(默认情况下):

else if (object instanceof Map) {
    return createMessageForMap((Map<? ,?>) object, session);
}

您必须确保地图的所有键都是String 类型,值是primitivies。这是根据MapMessage JavaDocs:

/** A {@code MapMessage} object is used to send a set of name-value pairs.
  * The names are {@code String} objects, and the values are primitive 
  * data types in the Java programming language. The names must have a value that
  * is not null, and not an empty string. The entries can be accessed 
  * sequentially or randomly by name. The order of the entries is undefined. 
  * {@code MapMessage} inherits from the {@code Message} interface
  * and adds a message body that contains a Map.

这是来自 ActiveMQ MarshallingSupport 的 sn-p:

public static void marshalPrimitive(DataOutputStream out, Object value) throws IOException {
    if (value == null) {
        marshalNull(out);
    } else if (value.getClass() == Boolean.class) {
        marshalBoolean(out, ((Boolean)value).booleanValue());
    } else if (value.getClass() == Byte.class) {
        marshalByte(out, ((Byte)value).byteValue());
    } else if (value.getClass() == Character.class) {
        marshalChar(out, ((Character)value).charValue());
    } else if (value.getClass() == Short.class) {
        marshalShort(out, ((Short)value).shortValue());
    } else if (value.getClass() == Integer.class) {
        marshalInt(out, ((Integer)value).intValue());
    } else if (value.getClass() == Long.class) {
        marshalLong(out, ((Long)value).longValue());
    } else if (value.getClass() == Float.class) {
        marshalFloat(out, ((Float)value).floatValue());
    } else if (value.getClass() == Double.class) {
        marshalDouble(out, ((Double)value).doubleValue());
    } else if (value.getClass() == byte[].class) {
        marshalByteArray(out, (byte[])value);
    } else if (value.getClass() == String.class) {
        marshalString(out, (String)value);
    } else  if (value.getClass() == UTF8Buffer.class) {
        marshalString(out, value.toString());
    } else if (value instanceof Map) {
        out.writeByte(MAP_TYPE);
        marshalPrimitiveMap((Map<String, Object>)value, out);
    } else if (value instanceof List) {
        out.writeByte(LIST_TYPE);
        marshalPrimitiveList((List<Object>)value, out);
    } else {
        throw new IOException("Object is not a primitive: " + value);
    }
}

因此,您的Record 将不会被接受。

您需要考虑不要将Map 用于JMS 消息并将您的Record 设置为Serializable 以便能够通过JMS 发送它。或者考虑使用其他一些MessageConverter,而不是默认的SimpleMessageConverter。例如,对我来说,MappingJackson2MessageConverter 应该对你有好处。

【讨论】:

  • 我使 Record 对象可序列化,然后将其直接传递到消息负载中,而不将其转换为 Map。它以这种方式工作。现在我的问题转移到了接收方。如何从 Message 作为对象检索它。我是否需要编写一个转换器将其反序列化为 Record 对象?
  • 不确定您关心的是什么,但消费者也配置了相同的SimpleMessageConverter。因此,任何Serializable 都应按原样处理。
  • 我这样发送 outputChannel.send(MessageBuilder.withPayload(paeRecord).build()); 然后像这样接收 Record record = message.getPayload();但我得到异常说 Caused by: java.lang.ClassCastException: com.ibm.jms.JMSObjectMessage incompatible with com.noname.Record
  • outputChannel.send(MessageBuilder.withPayload(record).build());
  • 您需要显示您的接收方式,但请在您的问题中。在 cmets 中不可读
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 2017-01-19
  • 2016-07-16
  • 2022-12-09
  • 1970-01-01
  • 2015-02-03
相关资源
最近更新 更多