Announcement Announcement Module
Collapse
No announcement yet.
Passing multiple Payload arguments to JMS Gateway Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Passing multiple Payload arguments to JMS Gateway

    We would like to expose services in the form :

    Code:
    public interface AccountGateway {
    
        @Gateway(...)
        List<Account> getUserAccounts(Customer customer, AccountFilter accountFilter);
    
    }
    It appears that we can send just one @Payload argument - we get runtime errors when passing more than one.

    I'd like to avoid passing in a Map or one of the alternative options for this interface, or using @Header parameters, as this forces restrictions on the API - namely that subsequent arguments must be String.

    An alternative is to use wrappers but this detracts from the simplicity spring integration provides. I've tried using expressions but wasn't able to make this work and in any case would like to avoid this type of complexity and favour compile time support. Finally I did consider an aspect to intercept, however the runtime proxies that implement spring integration cannot be subject to AOP - or seemingly the classes they instantiate directly. Inspecting the code at runtime it appears that the JmsTemplate and MessageConverter classes are hardwired into the GatewayProxy class, providing no hooks to override the behaviour of SimpleMessageConverter.

    Ideally would like the api to not expose the internals of JMS marshalling (by this i mean the requirement that only one 'parent' object can be passed in as the payload) and support multi parameter interface methods as part of JMS Gateways. If I've missed a trick please let me know; I'd like a generic solution rather than plumbing that becomes required for each method.

    New to this but have looked at the docs. I am keen to avoid creating either a layer of DTO classes to wrap individual messages or having to create an extra layer of BusinessDelegate classes to expose the public API we want.

    Not sure why the framework can't reflect on the argument list, convert to a map, pass across the gateway, unroll the map and call the service based on signature, with some disambiguation to avoid confusion with direct map inputs. Although some complexity implies by the implementation would produce and some runtime cost with reflection, this would be small in relation to the messaging IO and allow framework clients using the gateway interface to provide a simple and expressive APIs.

    Suggestions appreciated.

    Thanks,

    Alex

  • #2
    The @Payload annotation can be used at method-level rather than parameter-level, like so:

    Code:
    @Payload("#args[0] + #args[1])
    void someGatewayMethod(String a, String b);
    (also the SpEL expression can reference any bean with @beanname syntax)

    Maybe that helps?

    Comment


    • #3
      Mark - many thanks for this. Will plug it in on Tuesday.

      Comment


      • #4
        Just in case it's not obvious, you can use...

        Code:
        	@Payload("new Object[] {#args[0], #args[1]}")
        	public String multiArgs(String foo, Integer bar);
        or

        Code:
        	@Payload("T(java.util.Arrays).asList(new Object[] {#args[0], #args[1]})")
        	public String multiArgs(String foo, Integer bar);

        Comment


        • #5
          And, for completeness, if you don't want framework dependencies (@Payload) in your interface, you can configure it in the XML instead...

          Code:
          <int:gateway id="gw"
          	    service-interface="foo.MyGateway"
          	    default-request-channel="input">
          	<int:method name="multiArgs" payload-expression="T(java.util.Arrays).asList(new Object[] {#args[0], #args[1]})"/>
          </int:gateway>

          Comment


          • #6
            Gary

            This latter options seems the most attractive as this simplifies the Gateway interface to clients and hides the integration details. We'll do it this way. Thanks for the reply.

            Alex

            Comment

            Working...
            X