Skip to content

Revise ClassUtils.isPresent for exposing resolution exceptions in jlinked modules [SPR-17018] #21556

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

Closed
spring-projects-issues opened this issue Jul 6, 2018 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jul 6, 2018

J. Pablo Fernández opened SPR-17018 and commented

I know this is not a bug in 5.0.7 because it's modular Java is not supported, but I think this will be a bug once it is. I'm using the ModiTect maven plugin to inject many of the Spring jars with a definition of their module (module-info.java). I'm happy to share the results as it might help speed things up for others.

One of the issues I run into is this exception:

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect not found.
Could not configure Spring Data JPA auditing-feature because spring-aspects.jar is not on the classpath!
If you want to use auditing please add spring-aspects.jar to the classpath.
        at spring.data.jpa@2.0.8.RELEASE/org.springframework.data.jpa.repository.config.JpaAuditingRegistrar.registerBeanConfigurerAspectIfNecessary(JpaAuditingRegistrar.java:124)
        at spring.data.jpa@2.0.8.RELEASE/org.springframework.data.jpa.repository.config.JpaAuditingRegistrar.registerBeanDefinitions(JpaAuditingRegistrar.java:88)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromRegistrars$1(ConfigurationClassBeanDefinitionReader.java:358)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:357)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:145)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:328)
        at spring.context@5.0.7.RELEASE/org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:233)
        at spring.context@5.0.7.RELEASE/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)
        at spring.context@5.0.7.RELEASE/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93)
        at spring.context@5.0.7.RELEASE/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694)
        at spring.context@5.0.7.RELEASE/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532)
        at spring.boot@2.0.3.RELEASE/org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
        at spring.boot@2.0.3.RELEASE/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395)
        at spring.boot@2.0.3.RELEASE/org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
        at spring.boot@2.0.3.RELEASE/org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)
        at spring.boot@2.0.3.RELEASE/org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)
        at tech.flexpoint.dashmanserver/tech.flexpoint.dashmanserver.DashmanServerApplication.main(DashmanServerApplication.java:13)

I don't think this is an access problem because I already defined the module this way (being on the side of making it work at all costs):

module spring.aspects {
    exports org.springframework.beans.factory.aspectj;
    opens org.springframework.beans.factory.aspectj;
}

and of course spring.core requires spring.aspects.

I think the problem is that the actual code won't work with the ClassLoader when jlinked. This wouldn't be the first time I found class loaders behaving differently on Java 9 or 10:

https://stackoverflow.com/questions/49702287/getresourceasstream-returning-null-in-java-10

One of the issues is that I cannot replicate this problem while I can attach a debugger, so, I can't figure exactly what's going on. I'm reporting this here in case someone that's much more familiar with the code can point me in the right direction on how to figure out what's happening here and maybe coming up with a fix.

 


Affects: 5.0.7

Reference URL: https://stackoverflow.com/questions/51207237/class-not-found-in-spring-when-using-java-modules-and-jlink

Issue Links:

Referenced from: commits 833343f

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

cc ogierke since this is originating in Spring Data JPA...

@spring-projects-issues
Copy link
Collaborator Author

J. Pablo Fernández commented

BTW, I'm intending on exploring this issue and maybe find a solution. I tried to build and install spring-core on my computer but I run into problems building the javadocs. I will be investigating that shortly.

@spring-projects-issues
Copy link
Collaborator Author

J. Pablo Fernández commented

I made isPresent log out the exception that caused it to return false, and in this case it was returning:

java.lang.IllegalAccessError: superinterface check failed: class org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect (in module spring.aspects) cannot access class org.springframework.beans.factory.DisposableBean (in module spring.beans) because module spring.aspects does not read module spring.beans

Can isPresent return false on ClassNotFoundException but let every other exception bubble up instead of silently swallowing? or something like that?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

We're specifically handling IllegalAccessError now, in ClassUtils.isPresent as well as in ClassUtils.resolveClassName, throwing a corresponding IllegalStateException. After all, this is notably different not only from ClassNotFoundException but also from NoClassDefFoundError in that all the pieces are there in the deployment layout, with just misconfigured readability access preventing it from being resolvable.

@spring-projects-issues
Copy link
Collaborator Author

J. Pablo Fernández commented

Yay! Thank you very much Juergen Hoeller.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants