Skip to content

AnnotationBasedPersistentProperty.validateAnnotation(…) compares declared annotations with merged annotations #2368

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
pcallahan-r7 opened this issue May 4, 2021 · 1 comment
Assignees
Labels
type: bug A general bug

Comments

@pcallahan-r7
Copy link

Declaring @table on a record class works fine, but @PrimaryKeyClass does not.

For instance:

    @PrimaryKeyClass
    record Key(
            @PrimaryKeyColumn(name = "a", ordinal = 0, type = PrimaryKeyType.PARTITIONED ) UUID a,
            @PrimaryKeyColumn(name = "b", ordinal = 1, type = PrimaryKeyType.PARTITIONED) String b,
            @PrimaryKeyColumn(name = "c", ordinal = 2, type = PrimaryKeyType.CLUSTERED) String c) {}

    @Table(value = "mytable")
    record SomeItem(@PrimaryKey Key id,
                                  ...) { }

throws this exception:

Caused by: org.springframework.data.mapping.MappingException: Ambiguous mapping! Annotation PrimaryKeyColumn configured on field customer and one of its accessor methods in class Key!
	at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.validateAnnotation(AnnotationBasedPersistentProperty.java:154) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.lambda$populateAnnotationCache$7(AnnotationBasedPersistentProperty.java:126) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at java.base/java.util.Optional.ifPresent(Optional.java:178) ~[na:na]
	at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.populateAnnotationCache(AnnotationBasedPersistentProperty.java:120) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.<init>(AnnotationBasedPersistentProperty.java:88) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentProperty.<init>(BasicCassandraPersistentProperty.java:80) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.cassandra.core.mapping.CachingCassandraPersistentProperty.<init>(CachingCassandraPersistentProperty.java:40) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.createPersistentProperty(CassandraMappingContext.java:403) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.createPersistentProperty(CassandraMappingContext.java:60) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:543) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:521) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:708) ~[spring-core-5.3.4.jar:5.3.4]
	at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:384) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.addPersistentEntity(CassandraMappingContext.java:337) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:333) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:462) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.initialize(CassandraMappingContext.java:117) ~[spring-data-cassandra-3.1.5.jar:3.1.5]
	at org.springframework.data.mapping.context.AbstractMappingContext.afterPropertiesSet(AbstractMappingContext.java:454) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.4.jar:5.3.4]
	... 74 common frames omitted

Changing just the Key class to a regular class works fine:

    @PrimaryKeyClass
    class Key {
        @PrimaryKeyColumn(name = "a", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
        UUID   a;
        @PrimaryKeyColumn(name = "b", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
        String b;
        @PrimaryKeyColumn(name = "c", ordinal = 2, type = PrimaryKeyType.CLUSTERED)
        String c;

        public Key(UUID a, String b, String c) {
            this.customer = a;
            this.appId = b;
            this.attackId = c;
        }
    }

    @Table(value = "mytable")
    record SomeItem(@PrimaryKey Key id,
                                  ...) { }
@mp911de mp911de transferred this issue from spring-projects/spring-data-cassandra May 5, 2021
@mp911de mp911de added the type: bug A general bug label May 5, 2021
@mp911de mp911de added this to the 2.3.10 (Neumann SR10) milestone May 5, 2021
@mp911de
Copy link
Member

mp911de commented May 5, 2021

Thanks for report. The issue is caused because we compare a merged annotation with the declared annotation and Spring's merged annotations hydrate also aliases. Furthermore, Java records copy annotations to their accessors and therefore the annotation gets declared twice as of the bytecode. We can fix the issue easily in Spring Data Commons.

@mp911de mp911de self-assigned this May 5, 2021
@mp911de mp911de changed the title @PrimaryKeyClass annotation fails on java record types with an "Ambiguous mapping" exception AnnotationBasedPersistentProperty.validateAnnotation(…) compares declared annotations with merged annotations May 5, 2021
mp911de added a commit that referenced this issue May 5, 2021
We now validate declared annotations by pre-processing these through AnnotatedElementUtils to ensure a proper comparison. Previously, we compared annotation in their declared form (AnnotatedElement.getAnnotations()) with merged annotations which could fail due to aliasing effects of merged annotations.

Closes #2368.
mp911de added a commit that referenced this issue May 5, 2021
We now validate declared annotations by pre-processing these through AnnotatedElementUtils to ensure a proper comparison. Previously, we compared annotation in their declared form (AnnotatedElement.getAnnotations()) with merged annotations which could fail due to aliasing effects of merged annotations.

Closes #2368.
@mp911de mp911de closed this as completed in ac9b127 May 5, 2021
mp911de added a commit that referenced this issue May 5, 2021
We now validate declared annotations by pre-processing these through AnnotatedElementUtils to ensure a proper comparison. Previously, we compared annotation in their declared form (AnnotatedElement.getAnnotations()) with merged annotations which could fail due to aliasing effects of merged annotations.

Closes #2368.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants