Announcement Announcement Module
Collapse
No announcement yet.
How to convert payload and headers on JMS outbound message? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to convert payload and headers on JMS outbound message?

    hi,

    We're trying to send a file via an si:channel which will be converted to a JMS message. We'd rather not use the s-i API's directly in our code. The following code/config works exactly as we'd like;

    Code:
    Message<byte[]> m = MessageBuilder.withPayload("this could be a real file".getBytes())
        .setHeader("file.name", "target/file/name.txt")
        .build();
            
    MessageChannel out = (MessageChannel) context.getBean("gw-out");
    out.send(m);
    Code:
    <si:channel id="gw-out"/>
    <jms:outbound-channel-adapter
        connection-factory="connectionFactory"
        channel="gw-out"        
        destination-name="queue.dataupload.new"/>
    In the above example, a JMS BytesMessage with an appropriate JMSProperty for the 'file.name' header is placed on the queue. So far, so good - the consumer on that queue gets exactly what it needs from the above setup.

    Now, when I try to further this by removing the dependencies on Spring API's, I create a gateway interface..
    Code:
    public interface Gateway {
        void send(Object o);
    }
    .. add the following XML snippet..
    Code:
    <si:gateway 
        id="gateway"
        service-interface="test.Gateway" 
        default-request-channel="gw-out"/>
    .. and begin to amend the client code..
    Code:
    Gateway g = (Gateway) context.getBean("gateway");
    Object o = ?? // what goes here to replace the Spring MessageBuilder above?
    g.send(o);
    What do I replace the MessageBuilder with?

    Cheers!
    Darren.


    NB:
    Even if I leave the MessageBuilder in place, but still use the gateway, I have a new problem in that the actual GenericMessage instance gets serialized through the gateway. No longer do I have a BytesMessage on my JMS queue with a JMSProperty set with the 'file.name' value.. I have an ObjectMessage and a classname that the consumer knows nothing about. This appears to contradict the current ref docs that suggest the payload should be extracted.. I may have read this bit wrong of course.

  • #2
    For the line to replace the builder, you should be able to do something like this:
    Code:
    g.send("this could be a real file".getBytes(), "target/file/name.txt");
    Where the gateway's interface defines a method like this:
    Code:
    void send(byte[] payload, @Header("file.name") String fileName);
    Let me know if that works.

    (I might need a bit more clarification on the question in your NB)

    Comment


    • #3
      thanks for the quick reply Mark.

      Yes, your solution works, but I still have a Spring API in the code (the @Header annotation). Is this unavoidable? Any way, say, to pass a Map that will be treated as headers automagically?

      Cheers,
      Darren.

      Comment


      • #4
        You can use @Headers and a map:
        Code:
        void send(byte[] payload, @Headers Map headerMap);
        Yes, either annotation (@Header or @Headers) is going to introduce a Spring import. I guess we could consider auto-detecting 2 arguments where one is a Map and therefore headers. The only problem is that you could pass a Map payload as well (e.g. send(Map payload, Map headers)) in which case we would have to rely on the order, and that seems pretty ugly.

        Comment


        • #5
          yes, reflection's inability to access parameters by name curses us again

          No better in many ways than the solution you proposed, but an alternative might be to check a Map for a key named "payload", treating all other keys as headers.

          We'll go with the annotation for now I guess.

          Cheers!
          Darren.

          Comment

          Working...
          X