Spring Integration
  1. Spring Integration
  2. INT-3069

GatewayProxy does not keep track which method triggered the message flow

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 3.0 RC1
    • Component/s: Core
    • Labels:

      Description

      I want to try and avoid having to manually define each method in a gateway bean. My current setup is:

      gateway --> (a bunch of irrelevant stuff) --> http outbound gw

      Each gateway method is multiplexed to use the same HTTP outbound gw in order to unnecessarily create a bunch of HTTP gateways. To make this happen I need to pass along a URL which is unique per method. The usual way to do this would be to define each method in the XML config, setup a static header (there's no way to create a static header via annotation) and then read that off in the http outbound gateway but that would leave me defining each method which is messy.

      In my interface I want to be able to just say something like:
      @WebServiceCall("http://localhost/whatever")
      HeartBeat getHeartbeat();

      and in a later header enricher read that annotation off. There's only one thing missing: the gateway bean does not keep track which method trigged the message. If I had a

      {"originatingMethodCall": methodInvocation}

      reference then it would be trivial.

      Thoughts?

      Aside #1: I worked around it by making an aspect and storing what I wanted in a thread-local but that looks an unclean approach
      Aside #2: This would not have been necessary if it were possible to define static headers per method as an annotation.

        Issue Links

          Activity

          Hide
          Gary Russell added a comment - - edited

          Aside from possibly adding a @Headers method-level attribute...

          It shouldn't be too hard to add a header automatically ('gw_origin_method') regardless of whether an annotation or XML was used to configure the gateway (you could then use that as your key to map to a URL ...expression=@urlMap.get(headers['gw_origin_method'])...).

          However, a simple method name is probably not enough, it would need the return/argument types too

          String_foo(String), String_foo(Integer), void_bar(String,String) etc.

          Maybe we should make that the focus of this JIRA and open a second one to add a @Headers method-level annotation??

          Show
          Gary Russell added a comment - - edited Aside from possibly adding a @Headers method-level attribute... It shouldn't be too hard to add a header automatically ('gw_origin_method') regardless of whether an annotation or XML was used to configure the gateway (you could then use that as your key to map to a URL ...expression=@urlMap.get(headers ['gw_origin_method'] )... ). However, a simple method name is probably not enough, it would need the return/argument types too String_foo(String) , String_foo(Integer) , void_bar(String,String) etc. Maybe we should make that the focus of this JIRA and open a second one to add a @Headers method-level annotation??
          Hide
          Wallace Wadge added a comment -

          I was thinking of storing the Method reference (as in, the class) directly in the map, that way you can extract everything else via reflection. At least for the gateway code, this is already being done, it's just not storing it anywhere.

          In my case, my aspect is doing:

              @Around("execution(* com.foo.GatewayService*.*(..)) ")
              @Order(0)  // do our work before the @Gateway annotation
              public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
          
                  MethodSignature signature = (MethodSignature) pjp.getSignature();
                  Method method = signature.getMethod();  
                  TypeToken<?> typeToken = TypeToken.of(method.getGenericReturnType());
          

          I then store (guava's) typeToken and use that to access anything I need (generics included)

          Show
          Wallace Wadge added a comment - I was thinking of storing the Method reference (as in, the class) directly in the map, that way you can extract everything else via reflection. At least for the gateway code, this is already being done, it's just not storing it anywhere. In my case, my aspect is doing: @Around( "execution(* com.foo.GatewayService*.*(..)) " ) @Order(0) // do our work before the @Gateway annotation public Object invoke(ProceedingJoinPoint pjp) throws Throwable { MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); TypeToken<?> typeToken = TypeToken.of(method.getGenericReturnType()); I then store (guava's) typeToken and use that to access anything I need (generics included)
          Hide
          Gary Russell added a comment -

          Maybe both might be useful (text as well as Method object).

          Duplicate INT-3081

          Show
          Gary Russell added a comment - Maybe both might be useful (text as well as Method object). Duplicate INT-3081
          Hide
          Artem Bilan added a comment -

          I suggest to build String representation compatible with BeanUtils.resolveSignature, e.g. foo(java.lang.String). But it doesn't support 'return type'...

          Show
          Artem Bilan added a comment - I suggest to build String representation compatible with BeanUtils.resolveSignature , e.g. foo(java.lang.String) . But it doesn't support 'return type'...
          Show
          Gary Russell added a comment - PR: https://github.com/spring-projects/spring-integration/pull/929

            People

            • Assignee:
              Gary Russell
              Reporter:
              Wallace Wadge
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: