When running actuator on a different port we create a new child application context. This currently doesn't work with AOT.

Comment From: philwebb

Structure 101 of the actuator autoconfigure packages: Screen Shot 2022-05-24 at 8 10 43 PM

Comment From: philwebb

Analysis

ManagementContextFactory currently creates the context, registers web server factory related beans and registers some configuration classes that are passed in. This is fine for AOT processing, but for an AOT processed application we only need the context to be created, the beans should be registered programmatically.

I think we can use the following signature:

@FunctionalInterface
public interface ManagementContextFactory<C extends ConfigurableWebServerApplicationContext & AnnotationConfigRegistry> {

    C createManagementContext(ApplicationContext parent, boolean registerWebServerFactoryBeans);

}

We can then use the factory to create the context either with or without web server factory beans and we can use AnnotationConfigRegistry.register directly to register more configurations. We could also guard ...ManagementContextAutoConfiguration with @ConditionalOnManagementPort(ManagementPortType.DIFFERENT) because it's only used by DifferentManagementContextConfiguration.

AFAICT DifferentManagementContextConfiguration doesn't need to be a @Configuration class. We could make it a regular bean. We'll need to change the way the bean works depending on what it's doing.

For a regular run onApplicationEvent should do what it currently does.

For an AOT processing run, we need to:

  • Create the management context (with web server factory beans)
  • Load the configuration classes
  • Call refreshForAotProcessing on the context
  • Call ApplicationContextAotGenerator to generate an initializer

For an AOT processed run, we need to:

  • Create the management context (without web server factory beans)
  • Apply the previously generated initializer

We might be able to use BeanRegistrationAotProcessor for the generation and BeanRegistrationCodeFragmentsCustomizer to change the way the bean is registered. One slight problem at the moment is that BeanDefinitionMethodGeneratorFactory.isImplicitlyExcluded will remove the bean definition if it implements BeanRegistrationAotProcessor. We might want to change that in Framework perhaps using a default method and checking the aotProcessors instances rather than the bean type.

We'll probably also need to change BeanRegistrationAotProcessor so that it returns the name of initializer class.