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

com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation() method does not return annotation for a Record field #3974

Open
mumukiller opened this issue Jun 9, 2023 · 2 comments
Labels
Record Issue related to JDK17 java.lang.Record support

Comments

@mumukiller
Copy link

mumukiller commented Jun 9, 2023

Sorry if it's duplicate but i did not find anything like that

Describe the bug
When using custom annotation, Annotated.getAnnotation() method does not return annotation for a field marked with this annotation.

Version information
2.15.0

To Reproduce
This simple test can help:

class AnnotationIssueApplicationTests {

    @Test
    void mask() {
        var entity = new TestEntity("Secret", "Doe");

        ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(
                AnnotationIntrospectorPair.pair(
                        mapper.getSerializationConfig().getAnnotationIntrospector(),
                        new MaskSensitiveDataAnnotationIntrospector()));
        try {
            assertNotNull("Should be not null", mapper.writeValueAsString(entity));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SensitiveField {}

    private record TestEntity(
            @SensitiveField String mySecretFieldPassword,
            String name) {}


    private static class MaskSensitiveDataAnnotationIntrospector extends NopAnnotationIntrospector {

        @Override
        public Object findSerializer(Annotated am) {
            SensitiveField annotation = am.getAnnotation(SensitiveField.class);
            //When i use jackson-core:2.14.1 the test below passes successfully
           //When i use jackson-core:2.15.0 the test fails
            if (am.getName().equals("mySecretFieldPassword") && annotation == null){
                throw new RuntimeException("This should not happen");
            };
            return null;
        }
    }
}

Expected behavior
When i use jackson-core:2.14.1 the test below passes successfully
When i use jackson-core:2.15.0 the test fails

Additional context
This happened when i updated Spring Boot from 3.0.2 to 3.1.0
This is my graddle build

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
implementation 'com.fasterxml.jackson.core:jackson-annotations'
implementation 'com.fasterxml.jackson.core:jackson-core'
//this fixes the issue    implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.1'

    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}
@mumukiller mumukiller added the to-evaluate Issue that has been received but not yet evaluated label Jun 9, 2023
@mumukiller mumukiller changed the title com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation() method does not return annotation for 2.14.1 com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation() method does not return annotation for 2.15.0 Jun 9, 2023
@yihtserns
Copy link
Contributor

yihtserns commented Jun 9, 2023

Fix/workaround

Include ElementType.METHOD in your annotation:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveField {}

...so that the accessor method will get the annotation directly, instead of getting it from the field during "annotation merging" process.


Caused by #3737, specifically:

final boolean inferMutators = !isRecordType()
&& _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS);

...leading to the fields being removed by:

if (!inferMutators || (_getters == null)) {
_fields = _removeNonVisible(_fields);

When I created #3894 to refine/partially revert #3737, I did not also propagate the changes to _removeUnwantedAccessor because I don't understand what it is doing.

@cowtowncoder
Copy link
Member

One more suggestion: while it may not make a difference, it's probably worth checking if this still occurs with 2.15.2, given there are a few changes related to Record annotation handling.

@cowtowncoder cowtowncoder added the Record Issue related to JDK17 java.lang.Record support label Jun 19, 2023
@cowtowncoder cowtowncoder changed the title com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation() method does not return annotation for 2.15.0 com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation() method does not return annotation for a Record field Jun 19, 2023
@cowtowncoder cowtowncoder removed the to-evaluate Issue that has been received but not yet evaluated label May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Record Issue related to JDK17 java.lang.Record support
Projects
None yet
Development

No branches or pull requests

3 participants