-
Notifications
You must be signed in to change notification settings - Fork 38.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MethodInvokingFactoryBean
fails to invoke publicly exported methods overridden by internal classes when using JPMS
#34028
Comments
MethodInvokingFactoryBean
fails to invoke publicly exported methods overridden by internal classes when using JPMS
Hi @anandkarandikar, Congratulations on submitting your first issue for the Spring Framework! And thanks for the very detailed write up. Much appreciated.
I agree that's not ideal, but I must admit: that's a very clever way around the problem. 👍 That
That's correct. We have been making use of However, neither of those utilities take into account visibility restrictions imposed by the Java Module System. For example, in your use case As a side note, if In summary, I don't believe we have any method resolution logic in Spring Framework that takes module visibility constraints into account when determining which method to invoke. @jhoeller, thoughts? |
@sbrannen On other note
I believe this is reflected in the intent of the following comment within the getPubliclyAccessibleMethodIfPossible method:
However, this assumption appears to be invalid in cases where the class is public but resides in a package that is not exported. In such scenarios, even a public method within a public class cannot be invoked due to module visibility restrictions. Would it be possible to enhance ClassUtils to account for these module system restrictions? Additionally, since |
It believe it should be possible, but we will need to discuss this topic within the team.
The method resolution algorithm used in So, we would first need to decide if we want to modify that general algorithm. However, another option would be to override In any case feel free to open a separate ticket to suggest that |
@sbrannen Appreciate the feedback and a peek into the internals. |
Description
We encountered an issue while using Spring Framework (v5.3.29) in a Java 17 modular application. The problem arises when trying to invoke a public method from an exported class that is overridden by another class (within an internal package) using Spring's
MethodInvokingFactoryBean
. The method is not accessible due to Java Module System restrictions. This issue is reproducible in Java 17 and does not occur in Java 8.(Tested with: 5.3.29, 5.3.39, 6.2.0)
Steps to reproduce
Start with a simple maven project and choose Java 17 as the preferred JDK
1. Dependencies (pom.xml):
2. Custom Implementation
Extending
org.apache.logging.log4j.core.LoggerContext
to create a custom logger context class:3. Factory Class
A factory class
LoggerContextFactory
that provides an instance ofMyLoggerContext
:4. Module Configuration
The
module-info.java
file exports only thecom.example.api
package, keepingcom.example.impl
internal:5. Spring Configuration
Defined in
springApplicationContext.xml
:6. MainClass
Used to initialize the Spring
ApplicationContext
:Execution Output / Stacktrace
Observations
MethodInvokingFactoryBean
fails because theMethodInvoker
attempts to access a method inMyLoggerContext
via reflection, which is restricted due to Java Module System encapsulation.Ideally, staticMethod should not be used to invoke a non-static method.
Proposed Fix:
A similar issue was addressed previously in Spring EL (SpEL) by enhancing the
ReflectivePropertyAccessor
to locate accessor methods in public interfaces and public (super-)classes, defaulting to current logic if not found. (See #21385).We suggest implementing a comparable fix for Spring's
MethodInvokingFactoryBean
in the bean creation process to handle such cases.Related Issues
The text was updated successfully, but these errors were encountered: