Skip to content

AOT accessor generation does not consider nested types more than 1 level of depth #3530

Description

@notjoao1

Currently, in AOT generation, types that are 2 or more layers of generics deep, such as

  • V in Map<K, Map<K, V>>

do not have accessors generated for them ahead of time.

On the other hand

  • V in Map<K, V>

has an accessor generated for it ahead of time,

From my testing, it seems that the output of line 127 of DefaultAotRepositoryContext is where the issues starts at - when V is nested two layers of generics deep, it isn't a part of the return value of this call; while if it's only one layer of generics deep, it is.

Due to the fact that no generator is being generated in the first case of V being two layers of generics deep, it causes the following exception to be thrown in runtime of the generated native image, when calling the repository associated to the entity class that references type V:

java.lang.IllegalStateException: org.springframework.cglib.core.CodeGenerationException:
com.oracle.svm.core.jdk.UnsupportedFeatureError
-->
Classes cannot be defined at runtime by default when using ahead-of-time Native Image compilation.

Concrete example:

@Repository
public interface EntityRepository extends MongoRepository<EntityClass, String> {
}

@Document("entities")
@Data
public class EntityClass {
    @Id
    private String id;
    private Map<String, EntityChildOne> one;
    private Map<String, Map<String, EntityChildTwo>> two;
}

EntityChildOne and EntityChildTwo are both simple POJOs with a single field.
Running the following:

mvn clean compile spring-boot:process-aot && find target/ -iname "*Entity*Accessor*"

Returns the following output, which only contains __Accessor(s) for EntityClass and EntityChildOne, regardless of the fact that EntityChildTwo is being referenced.

target/spring-aot/main/classes/com/example/spring_data_accessor_generation_issue/EntityChildOne__Accessor_1po17f.class
target/spring-aot/main/classes/com/example/spring_data_accessor_generation_issue/EntityClass__Accessor_r2t2jh.class
target/classes/com/example/spring_data_accessor_generation_issue/EntityChildOne__Accessor_1po17f.class
target/classes/com/example/spring_data_accessor_generation_issue/EntityClass__Accessor_r2t2jh.class

Considering that the runtime code tries to generate the EntityChildTwo accessor (which fails when running in a native context), is this something that could be fixed?

In case someone else has the same issue -> my current workaround is adding a final field with no getters/setters and annotating it with @Transient, which allows it to be picked up by the AOT processing but completely ignored otherwise.

Reproducing

Feel free to use this sample repository for reproducing the issue. Versions used:

  • Java version: 25.0.4
  • spring-data-commons version: 4.0.7/4.1.1 (tested with both)
  • GraalVM version: 25.2.4

Thanks in advance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions