`com.fasterxml.jackson.databind.introspect.Annotated.getAnnotation()` method does not return annotation for a Record field
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()
}
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: https://github.com/FasterXML/jackson-databind/blob/2cea7c9ce9cbdcb14e22838ea07937c376b7ab78/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java#L1012-L1013
...leading to the fields being removed by: https://github.com/FasterXML/jackson-databind/blob/2cea7c9ce9cbdcb14e22838ea07937c376b7ab78/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java#L954-L955
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.
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.