Affects: 6.0.0-RC3

While looking at https://github.com/spring-projects/spring-boot/issues/32929, I have learned that @RegisterReflectionForBinding generates incomplete reflection hints when using Jackson's @JsonProperty. This app illustrates the problem:

package com.example.demo;

import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.example.demo.JsonPropertyApplication.Dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

@SpringBootApplication
@RegisterReflectionForBinding(Dto.class)
public class JsonPropertyApplication {

    public static void main(String[] args) {
        SpringApplication.run(JsonPropertyApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(ObjectMapper mapper) {
        return (args) -> {
            System.out.println(mapper.writeValueAsString(new Dto()));
        };
    }

    static class Dto {

        @JsonProperty
        private String field = "test";

        @JsonProperty
        String packagePrivate() {
            return "does it work?";
        }

    }

}

When run on the JVM, the following output if produced:

{"field":"test","packagePrivate":"does it work?"}

When run as a native image, the following output is produced:

{"field":"test"}

Looking at BindingReflectionHintsRegistrar, I think there are a couple of problems here:

  • Package-private (and private) methods are ignored
  • Methods with names that don't look like getters or setters are ignored

Comment From: sdeleuze

Thanks for raising this, I was expecting this kind of refinements being needed at some point.

The fact that BindingReflectionHintsRegistrar doesn't register private, package-private and non setters/record components methods is done on purpose since we walk on thin ice here. I previously attempted to register more by default but that ends up with far too much included in the native image due to the transitive inclusion of types used in return values/parameters.

To solve this issue, I am in favor of using the fact that those elements are annotated with @JsonProperty as a signal. I guess it will be useful to support other annotations, but we can maybe start by this one, see what other needs come later and potentially introduce a pluggable infrastructure for it if that grows too much.

Comment From: wilkinsona

Thanks, @sdeleuze. That sounds good to me. In my example above, Jackson only considered the field and method due to the presence of @JsonProperty. It would be good to look for @JsonValue too I think.

Comment From: sdeleuze

@wilkinsona I decided to add hints for every field and method annotated with a Jackson annotation since com.fasterxml.jackson.annotation.JacksonAnnotation makes that easy.