Skip to content
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

NullPointerException if passing an anonymous class to ReflectionsHint#registerType #29774

Closed
Artur- opened this issue Jan 5, 2023 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Milestone

Comments

@Artur-
Copy link

Artur- commented Jan 5, 2023

If you (accidentally in this case) pass an anonymous class to registerType it fails with

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "org.springframework.aot.hint.AbstractTypeReference.getCanonicalName()" is null
	at org.springframework.aot.hint.AbstractTypeReference.equals(AbstractTypeReference.java:93)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1214)
	at org.springframework.aot.hint.ReflectionHints.registerType(ReflectionHints.java:85)
	at org.springframework.aot.hint.ReflectionHints.registerType(ReflectionHints.java:98)
	at org.springframework.aot.hint.ReflectionHints.registerType(ReflectionHints.java:120)

This happened to us when trying to use

for (var c : reflections.getSubTypesOf(Converter.class)) {
     reflection.registerType(c, memberCategories);
}

and so it happens that Converter contains

public interface Converter<PRESENTATION, MODEL> extends Serializable {
...
    static <P, M> Converter<P, M> from(
            SerializableFunction<P, Result<M>> toModel,
            SerializableFunction<M, P> toPresentation) {
        return new Converter<P, M>() {
...

Seems like the org.reflections library returns Converter$2 as one of the sub types, which then fails when passed to registerType.

@Artur-
Copy link
Author

Artur- commented Jan 5, 2023

Well for some reason it seems like adding com.vaadin.flow.data.converter.Converter$1 works fine but when it gets to com.vaadin.flow.data.converter.Converter$2 then it fails

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 5, 2023
Artur- added a commit to vaadin/flow that referenced this issue Jan 5, 2023
Artur- added a commit to vaadin/flow that referenced this issue Jan 5, 2023
Artur- added a commit to vaadin/flow that referenced this issue Jan 9, 2023
@sdeleuze sdeleuze self-assigned this Jan 9, 2023
@sdeleuze sdeleuze added the theme: aot An issue related to Ahead-of-time processing label Jan 9, 2023
@sbrannen sbrannen added the type: bug A general bug label Jan 31, 2023
@sdeleuze sdeleuze added this to the 6.0.6 milestone Feb 9, 2023
@sdeleuze sdeleuze removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 9, 2023
@sdeleuze sdeleuze changed the title NullPointerException if passing an anonymous class to ReflectionsHints.registerType NullPointerException if passing an anonymous class to ReflectionsHint#registerType Feb 24, 2023
@sdeleuze
Copy link
Contributor

For this one, I think I would assert that the class passed to ReflectionTypeReference#of is not null and has a non null canonical name, in order to have a more meaningful exception earlier. That would also be consistent with the kind of checks done in SimpleTypeReference. cc @bclozel

@Artur- That will not change the fact you need to avoid passing such class to ReflectionHints in your code, I don't think silently ignoring such class-based type reference would be a reasonable behavior.

@jhoeller jhoeller added the in: core Issues in core modules (aop, beans, core, context, expression) label Feb 28, 2023
sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Mar 1, 2023
Before this commit, anonymous classes could throw an
unexpected NullPointerException in
ReflectionsHint#registerType and lambdas entries could
be created in the related generated reflect-config.json.

This commit refines how anonymous classes are handled by
explicitly checking for null class and canonical name in
ReflectionTypeReference#of, while skipping such class in
ReflectionHints#registerType in order to keep a lenient
behavior.

Closes spring-projectsgh-29774
sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Mar 1, 2023
Before this commit, anonymous classes could throw an
unexpected NullPointerException in
ReflectionsHint#registerType and lambdas entries could
be created in the related generated reflect-config.json.

This commit refines how anonymous classes are handled by
explicitly checking for null class and canonical name in
ReflectionTypeReference#of, while skipping such class in
ReflectionHints#registerType in order to keep a lenient
behavior.

Closes spring-projectsgh-29774
@sdeleuze
Copy link
Contributor

sdeleuze commented Mar 1, 2023

@Artur- I implemented a solution that should fix the NullPointerException you see, keep a lenient behavior at ReflectionHints#registerType level, and assert that the class and related canonical name are not null at ReflectionTypeReference#of level.

We have a planned release tomorrow, so when the build is finished, would be great if you could test Spring Framework 6.0.6-SNAPSHOT to confirm it works as expected for you.

@Artur-
Copy link
Author

Artur- commented Mar 2, 2023

I tried 6.0.6-SNAPSHOT but run into something that is already in 6.0.5

Exception in thread "main" java.lang.IllegalArgumentException: Code generation is not supported for bean definitions declaring an instance supplier callback : Root bean: class [null]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null

Need to figure that one out first..

@Artur-
Copy link
Author

Artur- commented Mar 2, 2023

Ok, Spring Boot vs Spring Framework conflict. With Spring Boot 3.0.3 + Spring Framework 6.0.6-SNAPSHOT everything works as expected, thanks!

mdeinum pushed a commit to mdeinum/spring-framework that referenced this issue Jun 29, 2023
Before this commit, anonymous classes could throw an
unexpected NullPointerException in
ReflectionsHint#registerType and lambdas entries could
be created in the related generated reflect-config.json.

This commit refines how anonymous classes are handled by
explicitly checking for null class and canonical name in
ReflectionTypeReference#of, while skipping such class in
ReflectionHints#registerType in order to keep a lenient
behavior.

Closes spring-projectsgh-29774
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) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants