Search code examples
javaspringspring-bootinversion-of-controlautowired

How to list all the managed @Component in Spring Boot?


I am trying to list all the managed Components in a Spring Boot application using a ListableBeanFactory interface as illustrated in How to Get All Spring-Managed Beans?

@SpringBootApplication
public class Application {
    private static ApplicationContext applicationContext;

    public static void main(String[] args) {
        applicationContext = SpringApplication.run(Application.class, args);
        displayAllBeans();
    }

    public static void displayAllBeans() {
        String[] allBeanNames = applicationContext.getBeanDefinitionNames();
        for(String beanName : allBeanNames) {
            System.out.println(beanName);
        }
    }
}

When running the application I get the following Exception indicating that the applicationContext object is null

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NullPointerException
    at mygroup.myapp.displayAllBeans(myapp.java:18)
    at mygroup.myapp.main(myapp.java:14)
    ... 5 more

What am I missing? Thanks in advance

UPDATE:

The code from the example works as expected. There was a mistake in my code that prevented the applicationContext variable to be set up correctly.


Solution

  • I think the problem is that the ApplicationContext instance was created by main thread, but then, for whatever reason, it was accessed by restartedMain thread.

    As applicationContext attribute is not synchronized, nor volatile, the restartedMain thread accessed the stale data - thats why java.lang.NullPointerException.

    To print out all of beans managed by Spring, you can use example from offical sources.

    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @Bean
        public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
            return args -> {
                System.out.println("Let's inspect the beans provided by Spring Boot:");
                String[] beanNames = ctx.getBeanDefinitionNames();
                Arrays.sort(beanNames);
                for (String beanName : beanNames) {
                    System.out.println(beanName);
                }
    
            };
        }
    }