Home > Net >  Spring boot register bean when application is started
Spring boot register bean when application is started

Time:02-01

Before a Spring boot application starts, I need to make a request for some credentials. I'm storing them in an object.

Is there a way to register this object as a bean before all other beans so that I can inject them in a configuration class?

I've tried like below but it's throwing exceptions:

SpringBootApplication(exclude = {MongoAutoConfiguration.class, 
SecurityAutoConfiguration.class, DataSourceAutoConfiguration.class})
public class BeanOnInitApplication {

    public static void main(String[] args) {

        System.out.println("Starting the app");

        MongoCredentials creds = makeARequestToExternalServiceAndGetCredentials();
    
    
        GenericApplicationContext appContext = (GenericApplicationContext) SpringApplication.run(BeanOnInitApplication.class, args);
        appContext.registerBean("mongoCredentials", MongoCredentials.class, () -> creds, bdc -> bdc.setLazyInit(false));
    }

}

And config class:

@Configuration
public class AppConfig {

    @Autowired
    MongoCredentials mongoCredentials;

    @Bean(name = "mongoTemplate")
    public MongoTemplate mt() {
        String url = "mongodb://"   mongoCredentials.getUsername()   ":"   mongoCredentials.getPassword()   "@localhost:27017/admin";
        MongoDatabaseFactory mdf = new SimpleMongoClientDatabaseFactory(url);
        return new MongoTemplate(mdf);
    }
 }

If this is not a solution what are the alternatives? The scope is to register a critical bean before anything else.

CodePudding user response:

Just make it an @Bean.

@Bean
public MongoCredentials mongoCredentials() {
  return makeARequestToExternalServiceAndGetCredentials();
}

Don't handle exceptions in the makeARequestToExternalServiceAndGetCredentials and just let them bubble up. If the request then fails the application will simply fail to start. If you want to retry wrap the call with a Spring Retry RetryTemplate and you have everything you want.

Another option is, which would allow for using auto configuration for Mongo as you appear to be using Spring Boot. Is to create an EnvironmentPostProcessor which loads the properties and adds them to the environment.

public class MongoCredentialsPostProcessor implements EnvironmentPostProcessor {
 public     void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  MongoCredentials credentials = makeARequestToExternalServiceAndGetCredentials();
  String url = "mongodb://"   mongoCredentials.getUsername()   ":"   mongoCredentials.getPassword()   "@localhost:27017/admin";

  Map<String, Object> props = Map.of("spring.data.mongodb.uri", url);
  MapPropertySource mps = new MapPropertySource("mongo-credentials", props):
}
}

Finally you could also modify your current code to do the same as the EnvironmentPostProcessor.

SpringBootApplication(exclude = {
SecurityAutoConfiguration.class, DataSourceAutoConfiguration.class})
public class BeanOnInitApplication {

    public static void main(String[] args) {

        System.out.println("Starting the app");

        MongoCredentials creds = makeARequestToExternalServiceAndGetCredentials();
      String url = "mongodb://"   mongoCredentials.getUsername()   ":"   mongoCredentials.getPassword()   "@localhost:27017/admin";
        
        SpringApplicationBuilder sab = new SpringApplicationBuilder(BeanOnInitApplication.class);
         sab.properties(Map.of("spring.data.mongodb.uri", url)).run(args);
    }
}

With both the latter and the EnvironmentPostProcessor you should be able to use the mongo autoconfiguration (which will provide the MongoTemplate for you.

  • Related