Reputation: 2426
I have a Java Spring Boot application which has a Scheduler which calls a async task from a Service The task takes a few minutes (usually 3-5mins) to complete.
The same async method from the Service can also be called trough a UI Application, by calling the API from the Spring Boot Controller.
Code:
Scheduler
@Component
public class ScheduledTasks {
@Autowired
private MyService myService;
@Scheduled(cron = "0 0 */1 * * ?")
public void scheduleAsyncTask() {
myService.doAsync();
}
}
Service
@Service
public class MyService {
@Async("threadTaskExecutor")
public void doAsync() {
//Do Stuff
}
}
Controller
@CrossOrigin
@RestController
@RequestMapping("/mysrv")
public class MyController {
@Autowired
private MyService myService;
@CrossOrigin
@RequestMapping(value = "/", method = RequestMethod.POST)
public void postAsyncUpdate() {
myService.doAsync();
}
}
The scheduler runs the async task every hour, but a user can also run it manually from the UI.
But, I do not want the async method to run again if it is already in the middle of execution.
In order to do that, I have created a table in DB which contains a flag which goes on when the method is running and then it is turned off after the method completes.
Something like this in my service class:
@Autowired
private MyDbRepo myDbRepo;
@Async("threadTaskExecutor")
public void doAsync() {
if (!myDbRepo.isRunning()) {
myDbRepo.setIsRunning(true);
//Do Stuff
myDbRepo.setIsRunning(false);
} else {
LOG.info("The Async task is already running");
}
}
Now, the problem is that the flag sometimes gets stuck due to various reasons (app restarting, some other application error etc.)
So, I want to reset the flag in DB each time the spring boot application is deployed and whenever is restarts.
How can I do that? Is there some way to run a method just after the Spring Boot Application starts, from where I can call a method from my Repo to un set the flags in the database?
Upvotes: 9
Views: 25862
Reputation: 6206
In your particular case , you need to reset the database after application deployment, so the best way for you to do that is to use the Spring CommandLineRunner .
Spring boot provides a CommanLineRunner interface with a callback run() method which can be invoked at application startup after the Spring application context is instantiated.
CommandLineRunner beans can be defined within the same application context and can be ordered using the @Ordered interface or @Order annotation.
@Component
public class CommandLineAppStartupRunnerSample implements CommandLineRunner {
private static final Logger LOG =
LoggerFactory.getLogger(CommandLineAppStartupRunnerSample .class);
@Override
public void run(String...args) throws Exception {
LOG.info("Run method is executed");
//Do something here
}
}
Answer referred from site : https://www.baeldung.com/running-setup-logic-on-startup-in-spring
Upvotes: 0
Reputation: 1863
If you want to do some stuff after whole application booted and ready use below sample from
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationStartup
implements ApplicationListener<ApplicationReadyEvent> {
/**
* This event is executed as late as conceivably possible to indicate that
* the application is ready to service requests.
*/
@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
// here your code ...
return;
}
} // class
If it is enough to hook after a single bean creating use @PostConstruct
as suggested by @loan M
Upvotes: 2
Reputation: 1207
Check for the @PostConstruct for e.g here https://www.baeldung.com/running-setup-logic-on-startup-in-spring
Upvotes: 12