spring-integration
                                
                                 spring-integration copied to clipboard
                                
                                    spring-integration copied to clipboard
                            
                            
                            
                        MessagingMethodInvokerHelper should disregard synthetic methods
In what version(s) of Spring Integration are you seeing this issue?
5.5.14
Describe the bug
I have a service object written in Groovy that I'm providing to the handle instruction on a DSL integration flow. This service method has a single public method plus some private fields and closures; the presence of the closures causes the generation of some synthetic methods to access the private fields in the top-level class. The MessagingMethodInvokerHelper throws an exception claiming ambiguous methods because it's processing the synthetics as fallbacks.
To Reproduce
Pass a class that carries synthetic methods to handle.
Expected behavior
I expect synthetic methods to be excluded. Specifically, at MessagingMethodInvokerHelper:776, the existing condition
!Modifier.isPublic(method1.getModifiers())
should be logically equivalent to
Modifier.isSynthetic(method1.getModifiers()) || !Modifier.isPublic(method1.getModifiers())
Interesting...
You know, I'm going to port Spring Integration Groovy DSL into core project soon enough: https://github.com/spring-projects/spring-integration-extensions/tree/main/spring-integration-groovy-dsl, but your catch still makes sense.
I think we better look into this utility instead in org.springframework.util.ClassUtils:
	/**
	 * Determine whether the given method is declared by the user or at least pointing to
	 * a user-declared method.
	 * <p>Checks {@link Method#isSynthetic()} (for implementation methods) as well as the
	 * {@code GroovyObject} interface (for interface methods; on an implementation class,
	 * implementations of the {@code GroovyObject} methods will be marked as synthetic anyway).
	 * Note that, despite being synthetic, bridge methods ({@link Method#isBridge()}) are considered
	 * as user-level methods since they are eventually pointing to a user-declared generic method.
	 * @param method the method to check
	 * @return {@code true} if the method can be considered as user-declared; {@code false} otherwise
	 */
	public static boolean isUserLevelMethod(Method method) {
Any chances to see such a service in Groovy, which, as you said, comes with synthetic methods?
Thanks
Could you clarify? Are you asking for a code sample that produces the problem? I'm not at the office, but this should reproduce the error:
@CompileStatic
class MyService {
  @Autowired
  private Dependency dependency
  void perform(Command command) {
    command.list.forEach { dependency.process(it) }
    // ^ creates a `public static synthetic Dependency pfaccess$0(MyService instance)`
  }
}
...
IntegrationFlows.from(SomeInterface).handle(myService).get()
I have just confirmed that proposed ClassUtils.isUserLevelMethod() does the trick for such a Groovy class.
There are some other issues in other places which use that MessagingMethodInvokerHelper as well, but that's different story and I'll look into that in details when my PR for Groovy DSL is merged: https://github.com/spring-projects/spring-integration/pull/3914
Thank you!