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

MergedAnnotation swallows IllegalAccessException for attribute method #27182

Closed
mikereiche opened this issue Jul 15, 2021 · 5 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@mikereiche
Copy link

AnnotationBasedPersistentProperty.validateAnnotation NullPointerException on project-specific annotations.

    <groupId>org.springframework.data.build</groupId>
    <artifactId>spring-data-parent</artifactId>
    <version>2.6.0-SNAPSHOT</version>

I hit this when running the tests of spring-data-couchbase project with JDK11 and adding a java-module.java. I assume there is some sort of introspection failure.

mergedAnnotation passed into validateAnnotation and the NPE occurs when candidate is dereferenced.

https://github.com/spring-projects/spring-data-commons/blob/db8431ee41b3b73dd87364de9c6cff158790452e/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java#L125

It's the .orElse((Object)null) that gets returned.

return !AnnotationFilter.PLAIN.matches(annotationType) && !AnnotationsScanner.hasPlainJavaAnnotationsOnly(element) ? (Annotation)getAnnotations(element).get(annotationType, (Predicate)null, MergedAnnotationSelectors.firstDirectlyDeclared()).synthesize(MergedAnnotation::isPresent).orElse((Object)null) : element.getDeclaredAnnotation(annotationType);
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 15, 2021
@mikereiche
Copy link
Author

mikereiche commented Jul 15, 2021

Down in the bowels of AttributeMethods:

  boolean isValid(Annotation annotation) {
    this.assertAnnotation(annotation);

    for(int i = 0; i < this.size(); ++i) {
      if (this.canThrowTypeNotPresentException(i)) {
        try {
          this.get(i).invoke(annotation);
        } catch (Throwable var4) {
          return false;
        }
      }
    }

    return true;
  }

The exception thrown here is swallowed, but it gives the exact action necessary to avoid it.

class org.springframework.core.annotation.AttributeMethods (in module spring.core) cannot access interface org.springframework.data.couchbase.core.mapping.id.GeneratedValue (in module spring.data.couchbase) because module spring.data.couchbase does not export org.springframework.data.couchbase.core.mapping.id to module spring.core

@mikereiche
Copy link
Author

mikereiche commented Jul 16, 2021

Exception looks like this:

Caused by: java.lang.NullPointerException: null
	at spring.data.commons@2.6.0-20210713.121642-36/org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.validateAnnotation(AnnotationBasedPersistentProperty.java:164)
	at spring.data.commons@2.6.0-20210713.121642-36/org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.lambda$populateAnnotationCache$10(AnnotationBasedPersistentProperty.java:144)
	at java.base/java.util.Optional.ifPresent(Optional.java:183)
	at spring.data.commons@2.6.0-20210713.121642-36/org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.populateAnnotationCache(AnnotationBasedPersistentProperty.java:137)
	at spring.data.commons@2.6.0-20210713.121642-36/org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.<init>(AnnotationBasedPersistentProperty.java:103)
	at spring.data.couchbase/org.springframework.data.couchbase.core.mapping.BasicCouchbasePersistentProperty.<init>(BasicCouchbasePersistentProperty.java:58)

@sbrannen
Copy link
Member

The exception thrown here is swallowed, but it gives the exact action necessary to avoid it.

What happens if you add a suitable --add-opens declaration?

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Jul 18, 2021
@mikereiche
Copy link
Author

Then it works fine. But because the original exception is swallowed and results in an NPE, what should be a trivial diagnosis becomes an extended session in the debugger.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jul 18, 2021
@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Nov 11, 2021
@jhoeller jhoeller changed the title AnnotationBasedPersistentProperty.validateAnnotation NullPointerException on project-specific annotations MergedAnnotation lookup swallows IllegalAccessException for attribute method Jan 6, 2024
@jhoeller jhoeller self-assigned this Jan 6, 2024
@jhoeller jhoeller added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 6, 2024
@jhoeller jhoeller added this to the 6.1.3 milestone Jan 6, 2024
@jhoeller jhoeller changed the title MergedAnnotation lookup swallows IllegalAccessException for attribute method MergedAnnotation swallows IllegalAccessException for attribute method Jan 6, 2024
@jhoeller jhoeller added the for: backport-to-6.0.x Marks an issue as a candidate for backport to 6.0.x label Jan 6, 2024
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.0.x Marks an issue as a candidate for backport to 6.0.x labels Jan 6, 2024
@jhoeller jhoeller added the for: backport-to-5.3.x Marks an issue as a candidate for backport to 5.3.x label Jan 6, 2024
@github-actions github-actions bot removed the for: backport-to-5.3.x Marks an issue as a candidate for backport to 5.3.x label Jan 6, 2024
@jhoeller
Copy link
Contributor

jhoeller commented Jan 6, 2024

The given scenario has effectively been addressed through #29448 already, avoiding reflection for annotation attribute retrieval to begin with. Even non-exported annotation types can be introspected for certain purposes that way, not leading to IllegalAccessExceptions in regular scenarios. I have nevertheless revised IllegalAccessException handling for the fallback reflection code path there.

As a bonus, we also avoid reflection for TypeVariable comparisons now (which typically happen during annotation retrieval on common classes and methods), and we log a clearer-worded message for annotation attribute retrieval failure at info level (e.g. on Google App Engine in case of a late-occurring TypeNotPresentException, logged at the same level as an early-occurring TypeNotPresentException on a regular JVM now).

jhoeller added a commit that referenced this issue Jan 6, 2024
Includes TypeVariable bypass for reflection-free annotation retrieval.
Includes info log message for annotation attribute retrieval failure.

Closes gh-27182

(cherry picked from commit 70247c4)
jhoeller added a commit that referenced this issue Jan 6, 2024
Includes TypeVariable bypass for reflection-free annotation retrieval.
Includes info log message for annotation attribute retrieval failure.

Closes gh-27182

(cherry picked from commit 70247c4)
@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Jan 7, 2024
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) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants