Issue Description

When using Spring Boot 3.x with GraalVM native compilation, I have two classes:

class RSocketFeignRuntimeHints : RuntimeHintsRegistrar {
    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        // Register hints for RSocket Feign classes
    }
}
class RSocketClientsRegistrar : ImportBeanDefinitionRegistrar {
    override fun registerBeanDefinitions(metadata: AnnotationMetadata, registry: BeanDefinitionRegistry) {
        // Register RSocket client beans
    }
}

Expected Behavior

During native compilation: 1. RuntimeHintsRegistrar should be executed first to register necessary hints 2. Then ImportBeanDefinitionRegistrar should be executed to register beans

Actual Behavior

When running ./gradlew nativeCompile: 1. ImportBeanDefinitionRegistrar is executed first 2. The compilation fails because necessary hints are not registered 3. RuntimeHintsRegistrar is not executed at all

Configuration

# src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar
org.fu.common.feign.model.RSocketFeignRuntimeHints

# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.fu.common.feign.RSocketClientsRegistrar

Question

How can we ensure RuntimeHintsRegistrar is executed before ImportBeanDefinitionRegistrar during native compilation?

Environment

  • Spring Boot: 3.3.5
  • GraalVM CE: 21.0.2
  • Gradle: 8.5

This seems to be a timing issue in Spring's AOT processing pipeline. Any suggestions on how to control the execution order would be appreciated.

Comment From: bclozel

Have you seen the AOT section in the reference documentation? Maybe using a BeanFactoryInitializationAotProcessor instead of a runtime hints registrar is a better fit.

Comment From: yuri-li

Thank you, I tried BeanDefinitionRegistryPostProcessor, the source code is as follows:

@ConditionalOnClass(RSocketRequester::class)
class RSocketClientsRegistrar : BeanDefinitionRegistryPostProcessor, PriorityOrdered, EnvironmentAware {
    override fun getOrder() = Ordered.HIGHEST_PRECEDENCE
    override fun setEnvironment(environment: Environment) {
        this._environment = environment
    }

    private val log = LoggerFactory.getLogger(this::class.java)
    private lateinit var _environment: Environment

    override fun postProcessBeanDefinitionRegistry(registry: BeanDefinitionRegistry) {
           log.info("start loading RSocketClientsRegistrar")

          //others
        }
    }
}

The problem is not solved.

In addition, the current project is a basic project similar to apache open feign. I think other spring boot projects can automatically load related configurations after getting dependencies, so the following configuration is used as follows:

src/main/resources/
└── META-INF
    └── spring
        └── org.springframework.aot.hint.RuntimeHintsRegistrar
        └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

Comment From: bclozel

I'm not sure what's the context or use case here, but I believe I've pointed you to the right direction. The section in the docs says it all and Spring Framework has several implementations of this pattern for AOT support.

I think you should ask a question on StackOverflow and better explain what you're trying to do and what you mean by the problem is not solve.