0
votes

I am trying to send a data model Java object to a Spring Integration Message Channel. I have a jms outbound channel adapter.

Here is my Java code. But it does not work.

@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());

}

Here is my Spring Integration config

<int:channel id="outputChannel" />  

<int-jms:outbound-channel-adapter id="outboundChannelAdapter" channel="outputChannel" jms-template="outputQueueJmsTemplate" />
1
What are symptoms you indicate as does not work? Maybe you have some error in logs? Maybe your Record is just not Serializable?Artem Bilan
Do I need to make my Record serializable ? Since HashMap is serializable by default, I thought I don't need to make Record serializable.user2208990
??? That’s not how things work in Java. A map is just a container of references. Of course, keys and values must be Serializable to be able to be transferred into JMS Broker.Artem Bilan
I made Record object serializable and passed the object to message payload without converting it to a Map. Now it can be sent successfully to MQ.user2208990
Please, don't duplicate comments for me. That sounds like a spam.Artem Bilan

1 Answers

0
votes

When you send a Map into JMS using JmsTemplate, it is wrapped to the MapMessage (by default):

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

And you has to be sure that all the key of the map are of String type and values are primitivies. That's according a 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.

And here is a snippet from the ActiveMQ MarshallingSupport:

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);
    }
}

So, your Record won't be accepted.

You need to consider do not use Map for JMS message and make your Record as Serializable to be able to send it over JMS. Or consider to use some other MessageConverter, not SimpleMessageConverter which is default. For example it seems for me a MappingJackson2MessageConverter should be good for you.