chain scheduled tasks java spring - java

Every 5 minutes, 2 tasks run, one that updates, one that calculates.
The one that updates should always run first, but doesn't have to know anything about the calculator and visa versa.
Is there any way to manage this in a clean way without calling the other task from within.
After advice, this is my solution.
#PostConstruct
public void scheduleRunnableWithTrigger() {
logger.info("init scheduler");
scheduleTasks.schedule(() -> {
if(init.getIsInitialzed()) {
databaseUpdater.updatePrices();
for (ITechnicalAnalysis technicalAnalysis: adviser.getITechnicalAnalysis()) {
try {
CandleStick lastAddedCandleStickByCurrencyPair = candleStickService.getLatestByCurrencyPair(technicalAnalysis.getCurrencyPair());
technicalAnalysis.updateAlgorithms(lastAddedCandleStickByCurrencyPair);
logger.info(technicalAnalysis.getCurrencyPair() + " has candlesticks");
}catch (NullPointerException e) {
logger.warn(technicalAnalysis.getCurrencyPair() + " has no candlesticks");
}
}
adviser.calculateAnalyses();
}
}, periodicTrigger);
}
#Bean
public PeriodicTrigger periodicTrigger() {
PeriodicTrigger periodicTrigger = new PeriodicTrigger(TIME_TO_WAIT_FOR_DATABASE_TO_FILL, TimeUnit.MINUTES);
periodicTrigger.setInitialDelay(1);
return periodicTrigger;
}

According to the documentation. Be default there will be only one thread for scheduler.
So what you can do is you can schedule the tasks one after the other may be a second apart. This way second task will always run after first task.
Even if first task is not completed and schedule time for second task has reached, second task will have to wait for the thread from first task to be released.
You can also explicitly set the thread count for the scheduler with a bean declaration like this
#Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(THREAD_COUNT);// use 1 for this use case
return threadPoolTaskScheduler;
}

Related

Async scheduling with Spring ScheduledTaskRegistrar

I've the problem, that I want to create a scheduled task during runtime. The scheduled task should be triggered with a fixed rate. But now I'm having the problem that the manual setup schedules are not triggered in an async way.
The main problem is, that we do not have any fix point were we can start the scheduler. It should get created when I read a specific value (1) and gets destroyed when the value changes back (0). Otherwise we could use the annotation configuration described in test 1 below.
What I have tried so far:
1. Schedule with #Scheduled(fixedRate = 500L) and #Async
Code
#Async
#Scheduled(fixedRate = 500L)
public void annotationTest() {
UUID id = UUID.randomUUID();
log.warn("Hello from Thread {} going to sleep", id);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.warn("Finished Thread {}", id);
}
Also having the #EnableAsync and #EnableScheduling annotations on class level.
Result
09:56:24.855 [task-5] : Hello from Thread 3b5514b2-3b80-4641-bf12-2cd320c4b6e5 going to sleep
09:56:25.355 [task-6] : Hello from Thread e98514a7-e193-422b-9569-f7635deb33f8 going to sleep
09:56:25.356 [task-4] : Finished Thread d86f5f24-bffb-4ddd-93fe-2334ed48cf91
09:56:25.854 [task-7] : Hello from Thread cfc2ab03-4e7e-4a4a-aa08-41d696cb6df7 going to sleep
09:56:25.855 [task-5] : Finished Thread 3b5514b2-3b80-4641-bf12-2cd320c4b6e5
09:56:26.355 [task-6] : Finished Thread e98514a7-e193-422b-9569-f7635deb33f8
Comment
This works as expected, but we are not able to use it, because we have to create the scheduler during runtime and destroy it after a specific time/input.
2. Setting up a ScheduledTaskRegistrar
Code
//#Configuration
#Bean
public ScheduledTaskRegistrar scheduledTaskRegistrar() {
ScheduledTaskRegistrar scheduledTaskRegistrar = new ScheduledTaskRegistrar();
scheduledTaskRegistrar.setScheduler(threadPoolTaskScheduler());
return scheduledTaskRegistrar;
}
#Bean
public TaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(20);
return scheduler;
}
//#Component
public void printMessages() {
scheduledTaskRegistrar.scheduleFixedRateTask(new FixedRateTask(new OwnRunnable(), 500L, 0L));
}
The OwnRunnable will also sleep 1 second and print the finish Text afterwards
Result
10:13:56.983 [TaskScheduler-1] : Finished Thread 73f70de9-35d9-47f0-801b-fb2857ab1c34
10:13:56.984 [TaskScheduler-3] : Hello from Thread 7ab16380-8dba-49e1-bf0d-de8235f81195 going to sleep
10:13:57.984 [TaskScheduler-3] : Finished Thread 7ab16380-8dba-49e1-bf0d-de8235f81195
10:13:57.984 [TaskScheduler-2] : Hello from Thread cc152d2e-f93b-4770-ac55-853a4dd6be97 going to sleep
10:13:58.985 [TaskScheduler-2] : Finished Thread cc152d2e-f93b-4770-ac55-853a4dd6be97
10:13:58.985 [TaskScheduler-4] : Hello from Thread 8d4510a4-773d-49f3-b51b-e58e425b0b68 going to sleep
Comment
As we can see the tasks run in a synchronous way and will not fit to our requirement.
3. Other tests
All other tests are similar to the test described in 2 but will use some other configurations of the ScheduledTaskRegistrar. The results are the same as in test 2.
ConcurrentTaskScheduler instead of ThreadPoolTaskScheduler
ConcurrentTaskScheduler with SimpleAsyncTaskExecutor as ConcurrentExecutor
ConcurrentTaskScheduler with ThreadPoolTaskExecutor as ConcurrentExecutor
Question(s)
How can I use the configuration described in test 2 but get the result of test 1? Is there a way to use the #Async annotation with solution described in test 2? Or does anyone have a better/ another solution for my problem?
Yes, it is possible. Assume that your class that implemented SchedulingConfigurer has a method, doMyJob(). You can annotate that method with Async and use the reference in FixedRateTask. Also notice the class level annotation
#Configuration
#EnableAsync
public class MyJobConfig implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.scheduleFixedRateTask(new FixedRateTask(this::doMyJob, 500L, 0L));
}
#Async
public void doMyJob() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Hope it helps
EDIT
I provided the code without testing. Recently when I tried to recreate this scenario, I noticed that if doMyJob is within SchedulingConfigurer, it will not be truly async (if delay is 5seconds and job takes 10seconds, next job runs only after 10seconds). But moving the method to a service class helped.

Spring - how to kill endless cycle

In my Spring application, there is a scheduler for executing some task. Scheduled annotation is not used there because the schedule is quite complicated - it is dynamic and it used some data from the database. So simple endless cycle with thread sleeping is used. And sleeping interval is changed according to some rules. Maybe all this can be done with Scheduled annotation, but the question is not about that.
Below is simple example:
#Service
public class SomeService {
#PostConstruct
void init() {
new Thread(() -> {
while (true) {
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println("end");
return;
}
}
}).start();
}
}
The code works fine but there is some trouble with killing that new thread. When I stop the application from Tomcat this new thread is continuing to run. So on Tomcat manage page I see that application is stopped, but in Tomcat log files I still see the output from the thread.
So what the problem? How I should change the code so the thread would be killed when the application is stopped?
Have you tried to implement a #PreDestroy method which will be invoked before WebApplicationContext is closed to change a boolean flag used in your loop? Though it seems strange that your objects are not discarded even when application is stopped...
class Scheduler {
private AtomicBoolean booleanFlag = new AtomicBoolean(true);
#PostConstruct
private void init() {
new Thread(() -> {
while (booleanFlag.get()) {
// do whatever you want
}
}).start();
}
#PreDestroy
private void destroy() {
booleanFlag.set(false);
}
}

What would happen to the threads managed by ExecutorService when tomcat shutting down?

I have an web app(with Spring/Spring boot) running on tomcat 7.There are some ExecutorService defined like:
public static final ExecutorService TEST_SERVICE = new ThreadPoolExecutor(10, 100, 60L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
The tasks are important and must complete properly. I catch the exceptions and save them to db for retry, like this:
try {
ThreadPoolHolder.TEST_SERVICE.submit(new Runnable() {
#Override
public void run() {
try {
boolean isSuccess = false;
int tryCount = 0;
while (++tryCount < CAS_COUNT_LIMIT) {
isSuccess = doWork(param);
if (isSuccess) {
break;
}
Thread.sleep(1000);
}
if (!isSuccess) {
saveFail(param);
}
} catch (Exception e) {
log.error("test error! param : {}", param, e);
saveFail(param);
}
}
});
} catch (Exception e) {
log.error("test error! param:{}", param, e);
saveFail(param);
}
So, when tomcat shutting down, what will happen to the threads of the pool(running or waiting in the queue)? how to make sure that all the tasks either completed properly before shutdown or saved to db for retry?
Tomcat has built in Thread Leak detection, so you should get an error when the application is undeployed. As a developer it is your responsibility to link any object you create to the web applications lifecycle, this means You should never ever have static state which are not constants
If you are using Spring Boot, your Spring context is already linked to the applications lifecycle, so the best way is to create you executor as a Spring bean, and let Spring shut it down when the application stops. Here is an example you can put in any #Configuration class.
#Bean(destroyMethod = "shutdownNow", name = "MyExecutorService")
public ThreadPoolExecutor executor() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 100, 60L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000),
new ThreadPoolExecutor.CallerRunsPolicy());
return threadPoolExecutor;
}
As you can see the #Bean annotation allows you to specify a destroy method which will be executed when the Spring context is closed. In addition I have added the name property, this is because Spring typically creates a number of ExecutorServices for stuff like async web processing. When you need to use the executor, just Autowire it as any other spring bean.
#Autowired
#Qualifier(value = "MyExecutorService")
ThreadPoolExecutor executor;
Remember static is EVIL, you should only use static for constants, and potentially immutable obbjects.
EDIT
If you need to block the Tomcats shutdown procedure until the tasks have been processed, you need to wrap the Executor in a Component for more control, like this.
#Component
public class ExecutorWrapper implements DisposableBean {
private final ThreadPoolExecutor threadPoolExecutor;
public ExecutorWrapper() {
threadPoolExecutor = new ThreadPoolExecutor(10, 100, 60L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
}
public <T> Future<T> submit(Callable<T> task) {
return threadPoolExecutor.submit(task);
}
public void submit(Runnable runnable) {
threadPoolExecutor.submit(runnable);
}
#Override
public void destroy() throws Exception {
threadPoolExecutor.shutdown();
boolean terminated = threadPoolExecutor.awaitTermination(1, TimeUnit.MINUTES);
if (!terminated) {
List<Runnable> runnables = threadPoolExecutor.shutdownNow();
// log the runnables that were not executed
}
}
}
With this code you call shutdown first so no new tasks can be submitted, then wait some time for the executor finish the current task and queue. If it does not finish in time you call shutdownNow to interrupt the running task, and get the list of unprocessed tasks.
Note: DisposableBean does the trick, but the best solution is actually to implement the SmartLifecycle interface. You have to implement a few more methods, but you get greater control, because no threads are started until all bean have been instantiated and the entire bean hierarchy is wired together, it even allows you to specify in which orders components should be started.
Tomcat as any Java application will not end untill all non-daeon threads will end. ThreadPoolExecutor in above example uses default thread factory and will create non-daemon threads.

Apache Camel With Quartz - No Concurrent Execution

I want to use camel->quartz component to schedule some job to be done at specified time interval.
But I want that in synchronized manner. Means, Next execution of scheduled job should only start after completion of current execution.
I created Route and Scheduler Service for Servicemix.
QuartzRoute.java
public class QuartzRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("quartz://myGroup/myTimerName?cron=0/1+*+*+*+*+?").process(new SchedulerService());
}
}
SchedulerService.java
public class SchedulerService implements Processor {
public void process(Exchange exchange) throws Exception {
System.out.println("I'm running every 5 sec...");
Thread.sleep(5000);
System.out.println("Exiting iteration ");
}
}
Here, I want "I'm running every 5 sec..." and "Exiting iteration " to be printed in same order every time.
In sort i want this SchedulerService to be executed again only after completion of current execution.
Use the stateful=true option of the quartz component. See Scheduled with fixed delay in quartz scheduler?
"stateful jobs are not allowed to execute concurrently, which means new triggers that occur before the completion of the execute(xx) method will be delayed."

Dynamic parameters for #Schedule method in an EJB 3.x

I'm new to the #Schedule annotations in J2EE6
I want to run a job using EJB 3.x with Glassfish 3.1.
The javax.ejb.Schedule seems to be a good choice for us, so we could think of our custom time as something like:
#Singleton
public class CustomTimer {
#EJB
SettingsFacade settingsFacade;
#Schedule(second="someSecondParameter", minute="someMinuteParameter",hour="someHourParameter", persistent=false)
public void executeTimer(){
//Code executing something against database using the settingsFacade
}
}
Here, we want the parameters to be got from database, so they are changed every month. Any clean solution for this?
#Singleton
#Startup
public class ScheduleTimerService {
#Resource private TimerService timerService;
public void setTimerService(TimerService timerService) {this.timerService = timerService; }
#PostConstruct
private void postConstruct() {
timerService.createCalendarTimer(createSchedule());
}
#Timeout
public void timerTimeout(Timer timer) {
Add your code here to be called when scheduling is reached...
in this example: 01h:30m every day ;-)
}
private ScheduleExpression createSchedule(){
ScheduleExpression expression = new ScheduleExpression();
expression.dayOfWeek("Sun,Mon,Tue,Wed,Thu,Fri,Sat");
expression.hour("01");
expression.minute("30");
return expression;
}
}
No, there is no solution with #Schedule, because annotation attributes in general should be compile time constants.
When more flexibility is needed, programmatic timers can be used.
Also then polling database for changed configuration and removing existing and creating new timers must be implemented.
Well You need to created Two Scheduler
One Scheduler will run to update data from Database
Based On that You Can created Other Scheduler.
But for this Need to do it some what programmatic.
You also can see EJB Timers for the same what will help you in this case. which is also annotation based.
There is a simple way of doing this. I wanted to something that called a process every day but, the job itself should be done randomly over the same day. I managed to do that by adding a simple thread worker to run after the EJB timer service has been called. Then I would put it to sleep for a random amount of time during that day.
The following code is an example of a service that wakes up every 1 minute and waits for a thread to finish.
#Schedule(minute = "*/1", hour = "*", persistent = false)
public void runEveryMinute() throws InterruptedException {
log.log(Level.INFO, "Scheduling for every minute .. now it's: " + new Date().toString());
// Delay, in milliseconds before we interrupt adding a follower thread
//we can therefore garantee that it runs every day
long patience = 1000 * 5;
threadMessage("Starting forever alone no more thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for new thread to finish");
// loop until MessageLoop thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second for MessageLoop thread to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting! Adding new followers now!");
t.interrupt();
// Shouldn't be long now -- wait indefinitely
t.join();
}
}
threadMessage("Finally! You are not alone anymore!");
}
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = {
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
int max = 10;
int min = 2;
int randomTimer = 0 + (int) (Math.random() * ((max - min) + 1));
Thread.sleep(randomTimer * 1000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("Patience is not a virtue! Thread stopping for now!");
}
}
}

Categories

Resources