How #scheduled annotation works in Spring Boot - java

I have an Spring Boot application in which I have a class with two methods likes below.
#Component
public class ClassA {
#Scheduled(fixedDelay = 900000)
public void methodA(){
//do task "A"
}
#Scheduled(fixedDelay = 600000)
public void methodB(){
//do task "B"
}
}
As per my understanding methodA should execute every 15 minutes and methodB should execute every 10 minutes. But as soon as applications starts both the jobs get invoked. Is this the right behavior ? If yes, then how can I stop them from execution immediately after application startup and run methodB after methodA?

As form the documentation: Scheduled (Spring Framework 5.0.4.RELEASE API)
fixedDelay: Execute the annotated method with a fixed period in
milliseconds between the end of the last invocation and the start of
the next.
What you want is
initialDelay:
Number of milliseconds to delay before the first
execution of a fixedRate() or fixedDelay() task.

Related

how to create scheduler which triggers a job at every 13 hours in java

how to create scheduler which triggers a job at every 13 hours in java
for example if it starts at
12 am then triggers a job at 1 pm
1 pm then triggers a job at 2 am
what about using #Scheduled(cron="0 0 */13 * * * ")
EDIT:
you can check here the only difference is that spring has added the first place (first *) for seconds.
EDIT2:
you can actually use also fixedRate
#Scheduled(fixedRate="13", timeunit=TimeUnit.HOURS)
In Spring Boot, you can just annotate a method with the #Scheduled annotation and the main class with the #EnableScheduling.
Examples:
Main class in Spring application
#EnableScheduling
#SpringBootApplication
public class ScheduledDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduledDemoApplication.class, args);
}
}
and create a method in a separate class that will be triggered on a schedule:
#Scheduled(some cron exp here)
public void execute() {
// some logic that will be executed on a schedule
}
This should work fine.
Here is a good article on how to schedule a Spring Boot task.

How to schedule executing method for certain time during runtime

Lets say I have some rest api where arguments are time when to execute method and second argument is name of the method in class. What is the best way for invoking call of this method in certain time (just once) in spring-boot application ?
First, enable scheduling in your spring-boot application:
#SpringBootApplication
#EnableScheduling
public class Application {
// ...
Then, inject the TaskScheduler bean and schedule the task programmatically every time the user invokes the REST method:
public class MyScheduler {
#Autowired
private TaskScheduler scheduler;
public void scheduleNewCall(Date dateTime) {
scheduler.schedule(this::scheduledMethod, dateTime);
}
public void scheduledMethod() {
// method that you wish to run
}
}
However, you should also think about limiting the amount of calls to this method, otherwise the malicious user could schedule a lot of tasks and overflow the task pool.

Implement background process in Spring

I need to implement Spring process which checks database table for new rows and makes calculations. I'm thinking to implement infinite loop which is triggered every 10 minutes.
Is there someway to implement this with Spring Boot? I can always use Java Thread but it's for sure it's better to let Spring to manage this.
You can try scheduling with Spring Schedule
Here is a official example
Technically, you enable scheduling with #EnableScheduling and annotated your task with #Scheduled(fixedRate=600000).
Another config you can used to tune your scheduler:
fixedRate: Execute the annotated method with a fixed period in milliseconds between invocations.
fixedDelay: Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.
cron: A cron-like expression, extending the usual UN*X definition to include triggers on the second as well as minute, hour, day of month, month and day of week.
find the below sample code
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class AppScheduler {
#Scheduled(fixedRate = 10000)
public void myScheduler() {
System.out.println("Test print");
}
}
It looks like this questions is old, but I would like to answer.
See, you can make an object of ThreadPoolTaskExecutor and assign the background process to it.
Here is my detailed code if anyone wants to see.
https://github.com/xbox2204/SpringBoot-JPA-Swagger-Angular
First thing to do would be, add these two annotation in your application starter class.
#EnableAsync
#EnableScheduling
Now, create you TaskExceutor in the same class and assign it to bean with a name, so that background tasks can be created anywhere in your application and attached with this bean.
#Bean(name="thPlExectr")
public Executor getExecutor(){
return new ThreadPoolTaskExecutor();
}
Now create a component class somewhere in the project, where you you will create the background task.
Here, you will mention the frequency with which you want your task to be exceuted. I wanted to print a statement every 5 second, you can choose your own frequency and give your own method definiton. Also, make it async and attach it with the TaskExecutor bean mentioned above, so that it doesn't interrupt the normal flow of your application.
#Component
public class BackgroundTasks {
private static final Logger log= LoggerFactory.getLogger(BackgroundTasks.class);
#Async("thPlExectr")
#Scheduled(fixedRate = 5000)
public void backTask(){
log.info("Hi Vineet! I am a background task");
}
}

A Sync Scheduled method runs an Async method - Spring #Scheduled, #Async

I'm using #Scheduled and #Async annotation of Spring.
My purpose
To schedule a sync method - which runs a for loop and this loop will run an async method, so the next value in the loop doesn't need to wait until the method is finished.
See my code below:
/**
* Explanation: Scheduling async task for getting new hired candidates from the Lumesse Queue and saving the received data.
*/
#LoggableDebug
#Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
for(EnvironmentContext environmentContext: context) {
if(environmentContext.isActive()) {
environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
}
}
}
/**
* #param environmentContext
* Explanation: Async task for getting new hired candidates from the Lumesse Queue and saving the received data.
*/
#LoggableDebug
#Async
public void environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(EnvironmentContext environmentContext) {
CandidateLumesse candidateLumesse;
candidateLumesse = lumesseConnectorService.getNewHiredCandidateDataFromQueue(environmentContext);
}
Problem:
My async method does't run on different tasks. It only works when I put the #Async annotation also on my scheduled method. But then my scheduled method will runs asyncronuos to and that's not what I want.
The scheduled method needs to run synchronous but the called method in the for loop needs to run asynchronous.
Tries
I tried a workaround like this one:
Spring #Async method call inside #Scheduled method
-> putting my async methods in another class.
Like this:
#LoggableDebug
#Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
for(EnvironmentContext environmentContext: context) {
if(environmentContext.isActive()) {
asyncServiceExecutor.environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
}
}
}
problem now is that my scheduled task get executed twice ...
Update
I did some more logging and my object only gets created once:
2018-02-06 13:17:19.053 WARN 13144 --- [ main]
c.d.l.c.s.LumesseConnectorScheduler : #### SCHEDULER CLASS CONSTRUCTOR
My fixedRate is 3000 -> 3 seconds
Someone requested "increase it to 30 sec to see the flow", but still it is executing twice:
So after 3 or 30 seconds or whatever the fixed rate has been set to, it will execute it twice instead of once..
2018-02-06 13:17:26.388 WARN 13144 --- [pool-7-thread-1]
c.d.l.c.s.LumesseConnectorScheduler : #### START SCHEDULING
2018-02-06 13:17:26.397 WARN 13144 --- [pool-7-thread-1]
c.d.l.c.s.LumesseConnectorScheduler : #### START SCHEDULING
-> Time between the two executions is just some very low miliseconds .. I just don't understand ..
Any thoughts ?
-> Async is working with my "Tries":
Tries
I tried a workaround like this one:
Spring #Async method call inside #Scheduled method
, but I had a new issue with scheduler executing twice :
Solution
#user27149 Try remove #ConfigurationProperties(prefix="environment")
or #Component
So I changed
#Component
#ConfigurationProperties(prefix="environment")
public class LumesseConnectorScheduler {
private List<EnvironmentContextImpl> context;
To:
#Component
public class LumesseConnectorScheduler {
#Autowired
EnvironmentContextList environmentContextList;
Thanks for the answers !

Spring Scheduled task does not start on application startup

I have a #Scheduled task in my application which is setup using CRON and run every 4 hours. The problem I face is that the CRON job does not start immediately after application startup but it starts only 4 hours after the application startup.
I tried to use a #PostConstruct method inside the task to invoke it, but that results in an error due to an uninitialized Spring context.
Please tell me how I can make the Scheduled task run immediately on application deployment and then on every 4 hours after the deployment.
EDIT:
I would not use a #PostConstruct since my scheduled method depends on other Beans , which are not initialized when this PostConstruct method runs for some reason.
By 0 */4 * * * you specify "At minute 0 past every 4th hour (0:00, 4:00, 8:00 etc.)", which is not at startup time and then every 4 hours as I think you want.
You can specify initial delay and rate by:
#Scheduled(initialDelay=0, fixedRate=4*60*60*1000)
If you are worried about hard-coded values, you can still provide config value:
#Scheduled(initialDelay=0, fixedRateString = "${some.config.string}")
I had #EnableScheduling in my app config. I had
#Scheduled(fixedDelay=5000) in my scheduled task class. Even then it didn't work.
I added #Service to my scheduled task class and everything worked fine.
I was having the same situation. I need to run cron scheduler every 1st day of the month and also when the application starts.
This is how I achieved using ApplicationListener.
import org.springframework.context.ApplicationListener;
import org.springframework.boot.context.event.ApplicationReadyEvent;
#Component
public class ApplicationReadyListner implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// callYourTask();
}
}
I'm not sure if you have tried this but you can use #Scheduled with an initialDelay
For fixed-delay and fixed-rate tasks, an initial delay may be specified indicating the number of milliseconds to wait before the first execution of the method.
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-scheduled
#Scheduled(initialDelay=0, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
I assume this will execute your scheduled method when the application is run.
If is not possible to use initialDelay attribute with the cron rule and your intention is execute this Job after every restart, you can implement a CommandLineRunner on your application class:
#SpringBootApplication
public class MyApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Autowired
private TaskService taskService;
#Override
public void run(final String... args) throws Exception {
taskService.run();
}
}
It's not the best strategy, but works.
Just specify the method you want to run in the init_method attribute of the bean.
Java config: #Bean(init_method="methodWhichStartsTask")
XML config: <bean id="someId" class="com.example.Clazz" init-method="methodWhichStartsTask"/>
This will invoke the method just after the bean is properly initialized and if the method is scheduled, then it will be called afterwards every 4 hours.
Instead of cron inside #Scheduled, use fixedRate like below. By default initialDelay is -1, which will start immediately or you can set 0.
#Scheduled(fixedRate=4*60*60*1000)
public void test() {
System.out.println("helloworld");
}
user #EnableScheduling annotation on your class which contains you1 scheduled method:
see spring document:
To enable support for #Scheduled and #Async annotations add
#EnableScheduling and #EnableAsync to one of your #Configuration
classes:
#Configuration
#EnableAsync
#EnableScheduling
public class AppConfig {
}
link : https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
#EnableScheduling annotation should be added in the main class for the Spring application.
Example :
#SpringBootApplication
#EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
and above the method where the actual scheduling needed we need to add
#Scheduled(initialDelay = 1000, fixedDelay = 4*60*60*1000)
Example:
#Scheduled(initialDelay = 1000, fixedDelay = 4*60*60*1000)
public void schleduleWork() {
/* Code Here */
}
For the above scheduler the first hit will be at 1000 milli second and subsequest hits will be at the interval of 4 hrs

Categories