Search code examples
javaspring-bootdependency-injectionjavabeans

Configure static field on boot with dependency injection Spring


I need to configure a static field of a class when my application is booted, using objects obtained using dependency injection.
In particular, I have a class that manages notification channels, and that class should have some "default channels" to use, like the following:

public class CustomerNotificationPreference {
    static List<NotificationChannel> defaults = List.of();
    Long id;
    List<NotificationChannel> channels;
}

Everything works fine for non-static field, but I can't find a way to configure that defaults using dependency injection.

What I've tried so far is the following:


@SpringBootApplication(scanBasePackages = {"com..."})
@EnableJpaRepositories("com...")
public class MyApp {

    @Bean
    void configureDefaultChannel(
        TelegramBot telegramBot,
        JavaMailSender javaMailSender,
        @Value("${telegram-bot.default-chat}") String chatId,
        @Value("${mail.default-receiver}") String to
    ){
        CustomerNotificationPreference.setDefaults(List.of(
            new TelegramNotificationChannel(telegramBot, chatId),
            new MailNotificationChannel(javaMailSender, to)
        ));
    }

}

But obviously Spring doesn't allow this since a Bean must not be void (Invalid factory method 'configureDefaultChannel': needs to have a non-void return type!)... are there ways to do this kind of things?


Solution

  • You can't autowire static field directly, but you can set static field after application is initialized using @PostConstruct or catching ApplicationReadyEvent

    public class MyApp {
    
        @Autowired
        TelegramBot telegramBot;
    
        @Autowired
        JavaMailSender javaMailSender
    
        @Value("${telegram-bot.default-chat}")
        String chatId;
    
        @Value("${mail.default-receiver}") 
        String to;
    
        @PostConstruct
        void setDefaults() {
            CustomerNotificationPreference.setDefaults(List.of(
                new TelegramNotificationChannel(telegramBot, chatId),
                new MailNotificationChannel(javaMailSender, to)
            ));
        }
    
        // OR
    
        @EventListener(ApplicationReadyEvent::class)
        void setDefaults() { 
            // same code as above
        }
        
    }