Mr.Tr33
Mr.Tr33

Reputation: 868

Spring Boot run controller without request

Is there a way to run a controller for initializing some data before Spring Boot starts the Tomcat?

My current code looks like that:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Controller controller = (Controller) context.getBean("controller");
        controller.start();
        context.close();

        SpringApplication.run(Application.class, args);
    }
}

@Controller
@Component("controller")
public class Controller {
    @Autowired
    private Runner runner;

    public void start() {
        runner.test();
    }
}

@Configuration
@PropertySource("classpath:config.properties")
@Component("runner")
public class Runner {
    @Value("${name}")
    private String name;

    public void test() {
        System.out.println("hello " + name)
    }

    public String getName() {
        return name;
    }
}

@Controller
public class HelloController {
    @Autowired
    private Runner runner;

    @RequestMapping("/hello")
    public CalenderCollection data(@PathVariable("name")String name, Model model) {
        model.addAttribute("name", runner.getName());
        return "hello";
    }
}

@Configuration
@ComponentScan(basePackages = "com.test")
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

This prints the correct name into the console. But when I visit the url then runner is null. Then I thought about to change the Application and Controller class to this:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@Controller
@Component("controller")
public class Controller {
    @Autowired
    private Runner runner;

    public Controller() {
        runner.test();
    }
}

But now I have the problem that runner is null right in the beginning. What would be a right way to collect some data in the beginning and then continue with the process?

Upvotes: 2

Views: 3807

Answers (4)

Akli REGUIG
Akli REGUIG

Reputation: 562

If this is something that affects only that class you can use

@PostConstruct 

on a method of your controller class.

If this is something that is linked to the whole application, you should consider creating an application listener on ApplicationReadyEvent

Upvotes: 2

akuma8
akuma8

Reputation: 4691

If you want to initialize some values you can do something like this :

@SpringBootApplication
public class Application implements CommandLineRunner {

  @Override
  public void run( String... args ) throws Exception {
    //initialise your value here
  }
}

Upvotes: 1

zafrost
zafrost

Reputation: 576

Usually you use ApplicationRunner or CommandLineRunner to run some code before application started.

From documentation

If you need to run some specific code once the SpringApplication has started, you can implement the ApplicationRunner or CommandLineRunner interfaces. Both interfaces work in the same way and offer a single run method which will be called just before SpringApplication.run(…​) completes.

The CommandLineRunner interfaces provides access to application arguments as a simple string array, whereas the ApplicationRunner uses the ApplicationArguments interface discussed above.

import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

    public void run(String... args) {
        // Do something...
    }

}

Upvotes: 3

geoand
geoand

Reputation: 64099

If you are just trying to run some code when the application has started, then there is no need to use Controller. Spring provides various application lifecycle hooks for such use cases.

The code would most likely look like this

@Component
public class MyListener 
        implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private Runner runner;

    public void onApplicationEvent(ContextRefreshedEvent event) {
        runner.test();
    }
}

Check out this blog post and this part of the documentation for more information

Upvotes: 3

Related Questions