I have next task: I need to load the same file into my web app several times, for example - twice a day! Suppose in that file I have information, that changes, and I need to load this info into my app to change the statistics for example.
How can I load file several times (twice an hour, or twice a day)?
What should I use? Is any algorithm to do that?
I am not allowed to use external libraries like Quartz Scheduler. So I need to do it with Thread and/or Timer. Can anybody give me some example or algorithm how to do it. Where can I create the entry point to my Thread, can I do it in managed bean or I need some sort of filter/listener/servlet. I works with jsf and richFaces. Maybe in this technologies there are some algorithms to solve my problem.
Any ideas?
Thanks very much for help!
If you cannot use a scheduler, then use a servlet and Timer.
In this article it is described how to do that. It's exactly what you need.
Check java.util.Timer, it should be just enough for what you need
how about this:
http://www.quartz-scheduler.org/overview/index.html
I'd use the Quartz Scheduler. I don't know the architecture of your app so I can't really say if Spring configuration or just code configuration is better. You could use a SimpleTrigger, or even a CronTrigger if you want a more expressive scheduling.
I would expose entry point to 'load' functionality as a servlet in your webapp and then use external scheduler (cron on Unix, Scheduled Tasks on Windows) to call that servlet via wget or any other command line http client.
This approach has advantages of not depending on any third party libraries (adding Qurtz just for one task seems like overkill for me) and also has flexibilty of changing schedule without touching your code as well as triggering 'load' manually if desired.
Thanks all for help - I do this task with help of Timer, TimerTask and ServletContextListener:
servletContext = event.getServletContext();
// create the timer and timer task objects
Timer timer = new Timer();
// get a calendar to initialize the start time
Date startTime = Calendar.getInstance().getTime();
List<Company> companies = CompanyUtils.getInstance().getCompanies();
if (companies.size() == 0)
return;
for (int i = 0; i < companies.size(); i++)
{
FileUpdater task = new FileUpdater(companies.get(i).getUrl());
// schedule the task to run hourly
timer.scheduleAtFixedRate(task, startTime, companies.get(i).getUpdatePeriod());
}
// save our timer for later use
servletContext.setAttribute("timer", timer);
Once more thanks!
With best wishes!
Related
I have a Spring Boot application that uses a #Scheduled annotation with a fixed delay. The annotation is used in different classes with different delays. However, at midnight every day all scheduled tasks stop running.
Does anyone know why this might be happening? I can't find any explanation online.
(I am using version 2.0.2.RELEASE of Spring Boot and 5.0.6.RELEASE of Spring Core.)
Thanks in advance!
I'm not sure what do you mean about stopping running.
But the first work you need to do is starting your schedules on different threads and put them into a queue.
If stopping means suspending for a while,then you create a new schedule that make other schedules sleep some time at midnight.Maybe the new schedule should have be started when the thread are sleeping,and the way to prevent is to make sure only one schedule(I mean same kind of schedule) could be put in the queue at the same time.
If you just mean kill all other schedule at midnight,you just need to start your midnight schedules and kill others.
So sorry about my poor English,hope this could help you.
#Scheduled(fixedDelay = 1000)
void scheduleFixedDelayTask() {
System.out.println(
"Fixed delay task - " + System.currentTimeMillis() /
1000);
}
In this case, the duration between the end of last execution and the start of next execution is fixed. The task always waits until the previous one is finished.
This option should be used when it’s mandatory that the previous execution is completed before running again.
So maintain the delay such a way that the previous execution completed.
Hope it helps.
Thanks to everyone who replied.
As it turns out, this was not an issue with Spring. It appeared the tasks stopped because the logs stopped. What really happened was that our scripts that tail the logs were not smart enough to handle log files that roll at midnight (face palm).
I have run into a case where I have to use a persistent Scheduler, since I have a web application that can crash or close due to some problems and might lose it job details if this happens . I have tried the following:
Use Quartz scheduler:
I used RAMJobStore first, but since it isn't persistent, it wasn't of much help. Can't setup JDBCJobStore because, this will require huge code changes to my existing code base.
In light of such a scenario,
I have the following queries:
If I use Spring's built in #Schedule annotation will my jobs be persistent..? I don't mind if the jobs get scheduled after the application starts. All I want is the jobs to not lose their details and triggers.?
If not, are there any other alternatives that can be followed , keeping in mind that I need to schedule multiple jobs with my scheduler.?
If yes, how can I achieve this.? My triggers are different each job. For e.g I might have a job that is scheduled at 9AM and another at 8.30AM and so on.
If not a scheduler, then can I have a mechanism to handle this.?
One thing, I found is that the documentation for Quartz isn't very descriptive. I mean it's fine for a top level config, but configuring it on your an application is a pain. This is just a side note. Nothing to do with the question.
Appreciate the help. :)
No, Spring's #Schedule-annotation will typically only instruct Spring at what times a certain task should be scheduled to run within the current VM. As far as I know there is not a context for the execution either. The schedule is static.
I had a similar requirement and created db-scheduler (https://github.com/kagkarlsson/db-scheduler), a simple, persistent and cluster-friendly scheduler. It stores the next execution-time in the database, and triggers execution once it is reached.
A very simple example for a RecurringTask without context could look like this:
final RecurringTask myDailyTask = ComposableTask.recurringTask("my-daily-task", Schedules.daily(LocalTime.of(8, 0)),
() -> System.out.println("Executed!"));
final Scheduler scheduler = Scheduler
.create(dataSource)
.startTasks(myDailyTask)
.threads(5)
.build();
scheduler.start();
It will execute the task named my-daily-task at 08:00 every day. It will be scheduled in the database when the scheduler is first started, unless it already exists in the database.
If you want to schedule an ad-hoc task some time in the future with context, you can use the OneTimeTask:
final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task",
(taskInstance, context) -> System.out.println("One-time task with identifier "+taskInstance.getId()+" executed!"));
scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
See the example above. Any number of tasks can be scheduled, as long as task-name and instanceIdentifier is unique.
#Schedule has nothing to do with the actual executor. The default java executors aren't persistent (maybe there are some app-server specific ones that are), if you want persistence you have to use Quartz for job execution.
I am using the Quartz Scheduler (version 1.8.3 due to project constraints) and I as assigned the task of creating an "MS Outlook-like" scheduler for Jobs specific to my project. Everything seems fine to work fine but I have a really huge problem with CronTriggers (this problem also exists in version 2.1 of Quartz):
I am using CronTriggers for recurrence patterns of DAILY, WEEKLY and MONTHLY. In addition to the recurrence pattern, I also provide an option for 'No. of occurrences'. This has become the bane of my life! CronTrigger does not provide an option for 'repeatCount' like SimpleTriggers do (bug: https://jira.terracotta.org/jira/browse/QTZ-242?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel). Apparently this may be fixed in version 2.2 but I cannot wait that long nor do I believe my problem is unique!
A few options that I deemed worthy of investigation:
Calculate the 'EndTime' for the CronTrigger but using my own logic - this fails to cover all possible cases and is only approximate at best even for simple cases.
Use a TriggerListener or JobListener to keep track of no. of iterations of the job since I just need the job to stop after 'N' iterations and I have a 1:1 mapping from Job instance to Trigger. This does not seem very feasible and/or efficient by any stretch of the imagination.
Could any of you who have used CronTriggers with the option of 'No. of occurrences' please give some insights on how to solve this conundrum?
It seems that Quartz have implemented something that can help: TriggerUtils.computeEndTimeToAllowParticularNumberOfFirings.
I haven't tested it yet, but this is the code I have wrote for now:
CronTrigger trigger = newTrigger()
.withSchedule(cronSchedule(cronExpression))
.build();
Date endDate = TriggerUtils.computeEndTimeToAllowParticularNumberOfFirings((OperableTrigger) trigger,
new BaseCalendar(Calendar.getInstance().getTimeZone()), 10);
trigger = trigger.getTriggerBuilder().endAt(endDate).build();
If this won't work, then as said here and here, you can't set a repeat count, and you should use TriggerListener.
In any case, version 2.2 doesn't have this feature.
Update
I've tested it, and it works.
Wy dont't you instead use the Simple Trigger? You would have the additional taks of calculating the time interval at the time of scheduling the job, but that will be a one time activity.
Hi all and thanks for reading this.
i have an application and i want to use multiple timers on it.
it will read from a list of instructions some instructions and will tell you what to do, keeping track of time for each instruction's time and notifying you when timer is over. instruction can include other instructions and goes on.
i m passing the time as : double minutes to each instruction.
So it should work like this.
start instruction1 - start timer1
if it includes other, start instruction1.1 - start timer1.1
start instruction2 - start timer2 .....etc.etc..
every time a timer goes of it should notify me
i would like to get suggestions on how to do this....
any tutorials, examples, links pseudocode, sample code are welcome. Thank you
Introducing a simple generalisation of the Java language's Timer class
How to Use Timers
Job Scheduling using Timer and Quartz
I have an application that runs in JBoss. I have an incoming web service request that will update an ArrayList. I want to poll this list from another class every 60 seconds. What would be the most efficient way of doing this?
Could anyone point me to a good example?
I would also recommend ScheduledExecutorService, which offers increased flexibility over Timer and TimerTask including the ability to configure the service with multiple threads. This means that if a specific task takes a long time to run it will not prevent other tasks from commencing.
// Create a service with 3 threads.
ScheduledExecutorService execService = Executors.newScheduledThreadPool(3);
// Schedule a task to run every 5 seconds with no initial delay.
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
System.err.println("Hello, World");
}
}, 0L, 5L, TimeUnit.SECONDS);
As abyx posted, Timer and TimerTask are a good lightweight solution to running a class at a certain interval. If you need a heavy duty scheduler, may I suggest Quartz. It is an enterprise level job scheduler. It can easily handle thousands of scheduled jobs. Like I said, this might be overkill for your situation though.
You can use Timer and TimerTask. An example is shown here.
See java.util.Timer. You'll need to start a robot in a separate thread when your app comes up and have it do the polling.
Check the answers to the question "How to run a task daily from Java" for a list of resources related to your problem.
The other answers are basically advising you do your own threads. Nothing wrong with that, but it isn't in conformance with the EJB spec. If that is a problem, you can use JBoss' timer facilities. Here is an example of how to do that.
However, if the EJB spec is at issue, storing state like an ArrayList isn't compliant as well, so if you are just reading some static variable anyway, specifically using a container Timer service is likely overkill.