Results 1 to 6 of 6

Thread: Issue with sending binary data as JMS messages using Spring Integration

  1. #1

    Default Issue with sending binary data as JMS messages using Spring Integration

    I have a Spring Integration (SI) application that extracts email attachments which can be either XML files or JPG images and sends it to a legacy system using WebSphere MQ for further downstream processing. I am using the SI jms:outbound-channel-adapter for the MQ messaging. My SI application context has the following definitions:

    <!-- Legacy Queue Connection Factory and Queue Name definitions -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingC onnectionFactory">
    <property name="targetConnectionFactory">
    <bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
    <property name="port" value="${legacyQMgrPort}"/>
    <property name="hostName" value="${legacyQMgrHost}"/>
    <property name="queueManager" value="${legacyQMgrName}"/>
    <property name="channel" value="${legacyQMgrClientChannel}"/>
    <property name="transportType" value="${transportTypeMQClient}"/>
    </bean>
    </property>
    <property name="sessionCacheSize" value="10"/>
    <property name="cacheProducers" value="false"/>
    </bean>

    <bean id="requestQueue" class="com.ibm.mq.jms.MQQueue" >
    <property name="baseQueueName" value="${legacyRequestQName}"/>
    <property name="TargetClient">
    <util:constant static-field="com.ibm.mq.jms.JMSC.MQJMS_CLIENT_NONJMS_MQ" />
    </property>
    </bean>

    <!-- Binary File to byte stream transformer for image files like .jpg, .gif etc -->
    <int:channel id="bytesChannel"/>
    <int-file:file-to-bytes-transformer input-channel="bytesChannel" output-channel="jmsOutChannel" delete-files="true"/>

    <!-- Text File to String transformer for XML messages with UTF-16 encoding -->
    <int:channel id="textChannel"/>
    <int-file:file-to-string-transformer input-channel="textChannel" output-channel="jmsOutChannel" delete-files="true" charset="UTF-16"/>

    <int:service-activator input-channel="jmsOutChannel"
    output-channel="mqChannel"
    ref="mqMessageHandler"/>
    <bean id="mqMessageHandler" class="gov.dhs.cbp.tecs.tipoff.MQMessageHandler"/>

    <int-jms:outbound-channel-adapter id="jmsOutboundAdapter" channel="mqChannel" connection-factory="connectionFactory" destination="requestQueue" extract-payload="true"/>

    The XML files are transmitted correctly as JMS Text Messages over MQ. The issue seems to be with the image files which are transformed to a byte array first with the file-to-bytes transformer and then sent as the payload of a JMS message. For some reason the outbound-channel-adapter is treating the binary data as text when it should be a JMS bytes message. The following logs show the output from some tracing within Spring Integration components.
    The JMSMessage Class: jms_text in the log output indicates that it is a text message when it should have been a jms_bytes message due to the binary payload.

    Has anyone encountered this issue? If so can you please let me know how you resolved it.


    12:30:08,890 INFO CachingConnectionFactory: Established shared JMS Connection: com.ibm.mq.jms.MQQueueConnection@1352367
    12:30:08,968 DEBUG CachingConnectionFactory: Creating cached JMS Session for mode 1: com.ibm.mq.jms.MQQueueSession@109da93
    12:30:08,984 DEBUG DynamicJmsTemplate: Executing callback on JMS Session: Cached JMS Session: com.ibm.mq.jms.MQQueueSession@109da93
    12:30:09,062 DEBUG DynamicJmsTemplate: Sending created message:
    JMSMessage class: jms_text
    JMSType: jms_bytes
    JMSDeliveryMode: 2
    JMSExpiration: 0
    JMSPriority: 4
    JMSMessageID: null
    JMSTimestamp: 0
    JMSCorrelationID: null
    JMSDestination: null
    JMSReplyTo: null
    JMSRedelivered: false
    correlationId: SAMPLE_Venky_Image.jpg
    fileName: SAMPLE_Venky_Image.jpg
    fileType: BINARY
    file_name: SAMPLE_Venky_Image.jpg
    timestamp: 1330623008406
    [B@58e2a1
    12:30:09,187 DEBUG DirectChannel: postSend (sent=true) on channel 'mqChannel', message: [Payload=[B@58e2a1][Headers={timestamp=1330623008406, id=4ee6d8ae-8ca1-451c-93bc-68fc8d483513, jms_type=jms_bytes, fileType=BINARY, correlationId=SAMPLE_Venky_Image.jpg, fileName=SAMPLE_Venky_Image.jpg,

  2. #2
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,844

    Default

    First, can you be sure to use [ CODE ] and [ /CODE ] (without the spaces) to wrap code/config excerpts in the future? It makes it much easier to read.

    From what you are showing, the default SimpleMessageConverter implementation would be in use, so that means a payload that is a byte array *should* cause creation of a javax.jms.BytesMessage. Are you positive that the routing logic is correct... that the image files are indeed going through the file-to-bytes-transformer?

  3. #3
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,844

    Default

    Actually looking at it again, what are you doing within the mqMessageHandler bean?

    That's most likely where something is changing (since the post-send log does show a bytes payload).

  4. #4

    Default

    Mark,
    Thanks for the quick response!! The mqMessageHandler bean is a service activator that intercepts the message and adds a correlation id (which is the file name) and the jms type (either jms_text or jms_bytes). Your response pointed me in the right direction and I took a closer look at the bean and found the subtle bug which I introduced with the line

    String msgPayload = msg.getPayload().toString();

    I have enclosed the bean implementation with the bug for your reference.

    This string ended up getting propagated as the message payload regardless of the original payload type. I fixed the issue and it work great now!! Thanks for your help!!

    Code:
        @ServiceActivator
        public Message handleMessage(@Header(FileHeaders.FILENAME) String fileName, Message msg) {            
          logger.info("Received Message: " + msg + " with original filename " + fileName);
          String msgPayload = msg.getPayload().toString();
               
          // Get the message header to examine the file type
          MessageHeaders msgHeaders = msg.getHeaders();
          
          String payloadType = (String) msgHeaders.get("fileType");      
          String jmsType = ("TEXT".equalsIgnoreCase(payloadType))? "jms_text" : "jms_bytes";
    
          // Set the correlation id to original fileName.
          return MessageBuilder.withPayload(msgPayload)
                  .setHeader(JmsHeaders.TYPE, jmsType)
                  .setCorrelationId(fileName)
                  .build();
        }
    After fixing the issue the response is as expected. Thanks again

    15:26:03,021 DEBUG DynamicJmsTemplate: Sending created message:
    JMSMessage class: jms_bytes
    JMSType: jms_bytes
    JMSDeliveryMode: 2
    JMSExpiration: 0
    JMSPriority: 4
    JMSMessageID: null
    JMSTimestamp: 0
    JMSCorrelationID: null
    JMSDestination: null
    JMSReplyTo: null
    JMSRedelivered: false
    correlationId: SAMPLE_Venky_Image.jpg
    fileName: SAMPLE_Venky_Image.jpg
    fileType: BINARY
    file_name: SAMPLE_Venky_Image.jpg
    timestamp: 1330633562678
    ffd8ffe000104a46494600010101009600960000ffdb004300 06040506050406060506070706080a
    100a0a09090a140e0f0c1017141818171416161a1d251f1a1b 231c1616202c20232627292a29191f
    2d302d283025282928ffdb0043010707070a080a130a0a1328 1a161a282828282828282828282828
    28282828282828282828282828282828282828282828282828 28282828282828282828282828ffc0
    001108011400dc03012200021101031101ffc4001f00000105 010101010101000000000000000001
    02030405060708090a0bffc400b51000020103030204030505 04040000017d010203000411051221
    31410613516107227114328191a1082342b1c11552d1f02433 627282090a161718191a2526272829
    2a3435363738393a434445464748494a535455565758595a63 6465666768696a737475767778797a
    838485868788898a92939495969798999aa2a3a4a5a6a7a8a9 aab2b3b4b5b6b7b8b9bac2c3c4c5c6
    c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2 f3f4f5f6f7f8f9faffc4001f010003
    ...

    15:26:03,115 DEBUG DirectChannel: postSend (sent=true) on channel 'mqChannel', message: [Payload=[B@186f3b3][Headers={timestamp=13306335626

  5. #5
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,037

    Default

    You may also want to consider using a <header-enricher/>; you will then need no custom Java code - it always raises an alarm with me when I see dependencies on SI in user classes Such dependencies can be avoided in many (if not most) cases.

    Code:
    <header-enricher input-channel="foo" output-channel="bar">
    	<correlation-id expression="headers[T(org.springframework.integration.file.FileHeaders).FILENAME]"/>
    	<header name="jms_type" expression="'TEXT'.equalsIgnoreCase(headers['fileType']) ? 'jms_text' : 'jms_bytes'"/>
    </header-enricher>
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #6

    Default

    Thanks for the tip. I will try this out.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •