Spring, Run task once when application started
Asked Answered
M

3

7

My application is based on spring boot. I want to create a task which should be run only once after application has been started.

Currently, I am looking into two solutions:

  1. Using @Scheduled and boolean property which should determine whether the logic shold be run or not.

    @Scheduled public void method(){ if(method_run_propery){ //do something; } }

  2. Using Quartz. But I have not used before.

Please, tell me what is the best approach to use in this case.

Micrometeorite answered 10/8, 2016 at 6:57 Comment(2)
See spring.io/blog/2015/02/11/… - I don't any reason why you need scheduling for a run once taskHankhanke
@shachar. After application has started, I am cheking if I have any data in In-memory data grid. In case it's empty I am going to getch the data and store it. That is why i want to do that only once.Micrometeorite
B
8

If it has to be run once immediately after application is initialized, I would simply start it from the init method of a singleton bean. Spring ensures that at be time it will be run all dependant beans will have been initialized.

For example, assuming a Java annotation Spring configuration you could use something like:

@Bean(init_method="init")
class TaskLauncher {

    @Autowired DependantBeanClass dependant Bean;
    ...

    public void init() {
        // execute or start the task, eventually using the autowired dependant beans
        ...
    }
}

When the context is refreshed, Spring autowire everything, initializes the dependant beans and then will call once the init method of the TaskLauncher bean.

No need for @Scheduler nor Quartz if you only need to start something at Spring initialization time

Benilda answered 10/8, 2016 at 7:8 Comment(1)
Could you please described more detailed your approach?Micrometeorite
M
15

Spring has a @PostConstruct annotation to do exactly that. Runs once the bean has been initialized and all dependencies added.

Mcduffie answered 10/8, 2016 at 8:9 Comment(4)
Is it good approach, to perform request to another api, in the post construct?Micrometeorite
Depends on what the application requires to start. If the data from that other api is needed to hydrate a cache before finalizing the startup of the application then I don't see how you get around it. If it is just a one-off request then you might want to make some sort of non-blocking call so that the @PostConstruct method can return and allow the application to finish starting up.Mcduffie
Ok. I will try you approach. And come with resultsMicrometeorite
PostConstruct is good if all you intend to wait for is this one bean (and its dependencies) is ready. OP asked about the application being started, which means ALL beans ready and everything fully initialized. If the latter is actually the intent, @Shirish Singh's answer is preferable.Fatwitted
B
8

If it has to be run once immediately after application is initialized, I would simply start it from the init method of a singleton bean. Spring ensures that at be time it will be run all dependant beans will have been initialized.

For example, assuming a Java annotation Spring configuration you could use something like:

@Bean(init_method="init")
class TaskLauncher {

    @Autowired DependantBeanClass dependant Bean;
    ...

    public void init() {
        // execute or start the task, eventually using the autowired dependant beans
        ...
    }
}

When the context is refreshed, Spring autowire everything, initializes the dependant beans and then will call once the init method of the TaskLauncher bean.

No need for @Scheduler nor Quartz if you only need to start something at Spring initialization time

Benilda answered 10/8, 2016 at 7:8 Comment(1)
Could you please described more detailed your approach?Micrometeorite
P
1

One of the ways is to implement ApplicationListener

Once spring context is initialized, Your class which implements ApplicationListener which will then have onApplicationEvent method will be invoked, your logic can go in this method.

Prince answered 22/5, 2021 at 5:33 Comment(1)
I'll add that the ApplicationReadyEvent is probably the one you want for this case. The interface is takes the event type as a generic typearg, so you implement ApplicationListener<ApplicationReadyEvent>.Fatwitted

© 2022 - 2024 — McMap. All rights reserved.