Dynamic change Timer service or Quartz - java

We need a schedule job in a Java EE server and we know how to use Quartz or the Timer service.
But our question is, if we want to change the schedule on production or manually trigger the batch, how to do it?
In the traditional solution, we use a servlet to run the job. And then use a cronjob with a http client (i.e. lynx) to trigger the servlet. It's easy to implement and could change on production.

I have never found Timers to entirely satisfactory because of this exact problem: you can't really monitor their status or modify them.
What I recommend is a second layer job manager class. When you call this class, it schedules a Java EE timer for time 'X', and it also records the fact that you want to execute a 'job' at time 'X'. When that time arrives, the Java EE timer calls this job manager class, which finds the job, and calls the job.
What this allows you to do is to write an "unschedule" function. Calling unschedule would remove the job. When the Java EE timer calls at time 'X' this class does not find any job, and so ignores it.
You can also implement a "change schedule" function that removes the old entry, and create a new entry at time 'Y' scheduling a Java EE timer for time 'Y'. The Java EE timer will arrive at both time 'X' and another at time 'Y' but only the time 'Y' will have effect.
Thus manual triggering is a matter of having a servlet that call "change schedule" to be right now.
The one other detail to be careful of: because timer events are not completely reliable, we implement this class to find all the jobs that had been scheduled before the current time, and run all of them at that moment. We then schedule extra Java EE timer events for every 5 minutes or so. Those timers will pick up any jobs that for one reason or another had been left behind. This is important if your job queue is persistent, then it might be that while restarting the server, it is down at exactly the moment that the timer was supposed to go off. No problem: Java EE Timer events themselves have no meaning, they just serve to wake up the job handler, so it can run all the outdated jobs.

Related

Running Only Once A Schedule Job Across Multiple Instances

I have a schedule job that run every end of the month. After running it saves some data to database.
When i scale the app(for example with 2 instances) both instances run the schedule job and both save the data and at the end of day my database has the same data.
So i want the schedule job only run one time regardless of instances numbers at cloud.
In my project, I have maintained a database table to hold a lock for each job which needs to be executed only once in the cluster.
When a Job gets triggered then it first tries to acquire lock from the database and if it gets that lock only then it will get executed. If it fails to acquire the lock then job will not get executed.
You can also look at the clustering feature of Quartz job.
http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/introduction.html
I agree with the comments. If you can utilize a scheduler that's going to be your best, most flexible option. In addition, a scheduler should be executing your job as a "task" on Cloud Foundry. The task will only run on one instance, so you won't need to worry about how many instances your application is using (the two are separate in that regard).
If you're using Pivotal Cloud Foundry/Tanzu Cloud Foundry there is a scheduler you can ask your operations team to install. I don't know about other variants of CF, but I assume there are other schedulers.
https://network.pivotal.io/products/p-scheduler/
If using a scheduler is not an option then this is a concern you'll need to handle in your application. The solution of using a shared lock is a good one, but there is also a little trick you can do on Cloud Foundry that I feel is a little simpler.
When your application runs, certain environment variables are set by the platform. There is one called INSTANCE_INDEX which has a number indicating the instance on which the app is running. It's zero-based, so your first app instance will be running on instance zero, the second instance one, etc.
In your code, simply look at the instance index and see if it's zero. If the index is non-zero, have your task end without doing anything. If it's zero, then let the task proceed and do its work. The task will execute on every application instance, but it will only do work on the first instance. It's an easy way to guarantee something like a database migration or background job only runs once.
One final option would be to use multiple processes. This is a feature of Cloud Foundry that enables you to have different processes running, like your web process and a background worker process.
https://docs.cloudfoundry.org/devguide/multiple-processes.html
The interesting thing about this feature is that you can scale the different processes independently of each other. Thus you could have as many web processes running, but only one background worker which would guarantee that your background process only runs once.
That said, the downside of this approach is that you end up with separate containers for each process and the background process would need to continue running. The foundation expects it to be a long-running process, not a finite duration batch job. You could get around this by wrapping your periodic task a loop or something which keeps the process running forever.
I wouldn't really recommend this option but I wanted to throw it out there just in case.
You can use #SnapLock annotation in your method which guarantees that task only runs once. See documentation in this repo https://github.com/luismpcosta/snap-scheduler
Example:
Import maven dependency
<dependency>
<groupId>io.opensw.scheduler</groupId>
<artifactId>snap-scheduler-core</artifactId>
<version>0.3.0</version>
</dependency>
After importing maven dependency, you'll need to create the required tables tables.
Finally, see bellow how to annotate methods which guarantees that only runs once with #SnapLock annotation:
import io.opensw.scheduler.core.annotations.SnapLock;
...
#SnapLock(key = "UNIQUE_TASK_KEY", time = 60)
#Scheduled(fixedRate = 30000)
public void reportCurrentTime() {
...
}
With this approach you also guarantee audit of the tasks execution.

create multithreaded java ee

Is it possible to create a multithreaded Java EE Glassfish container?
My intention is to create an application where users can capture data launch a social network, then each user would launch a new thread with the parameters he wants to retrieve information from the social network.
all these threads would be limited in number to avoid memory server.
As I can create multiple threads in java ee and that these once the user exits the application to remain running in the background until the user closes them?
One solution may be the job of glassfish?
Your question is pretty broad, but in general I understand you need to execute a thread for each user, which runs in background even when user stops using the application (logs out), does some repetitive task, and is terminated by user when required.
First, I would point out that this can be accomplished in cleaner way using timer service - you can schedule a periodical background job, which will do everyting you need. It can read the list of user and their tasks, perform them at a given interval. Then, a user may request to cance their tasks - they will remove their task from the list.
In this way, the number of users having the background task running would not be limited. They also can run sequentially in a single thread, but you may tweak that, see the rest of my answer.
More into on shceduling a timer in Java EE tutorial: https://docs.oracle.com/javaee/7/tutorial/ejb-basicexamples004.htm.
In case you really need a separate thread per user, there are several ways how to execute a thread separately from the request-handling thread. You might use asynchronous EJB method invocation, using #Asynchronous annotation. You may also inject ManagedExecutorService and use it to execute a Runnable asynchrnously using submit method. In both ways, you would not loose context and dependency injection will continue to work.
See more details about asynchronous eecution in Java EE tutorial about Concurrency utilities
You may also execute runnables asynchronously from a timer, but you may not need that, if you execute only a single task from within a timer handler, as timer handler will be executed when timer triggers in a new thread, if the previous handler did not complete yet.

Implementing a timer for an auto-logoff feature in an embedded system (Java)

I'll try my best to explain the situation at hand. I'm developing an auto-logoff feature for an authentication application that runs in an embedded system and should work cooperatively with its own internal auto-logout system. First I'll briefly explain the native auto logoff. If I set it to 60 seconds and I'm in one of the system's screens, it will monitor and reset the timer upon user interaction. After being idle for 60 seconds, the system will call the Java authentication application and it logs off. This is easily done. Once an user logs in, the application starts a thread that just waits. When the application is brought back (upon timeout), a call for the notify() method is made, releasing the thread and executing the logout proccess. Relatively simple, right?
Now things get ugly. This embedded system supports multiple Java applications, as it is expected. But the system built-in auto logout will only keep track of things should the user be interacting with one of the system's native screens, if he's using another Java application, it will do nothing. So, in order to counter that, I need to come up with some way to implement an internal timer that works in conjunction with the workings described above.
In other words, should the system be in "Java mode" I need to use a coded timer, anything else I use the timer described in the first paragraph. The system itself doesn't help much, since there's no support to check in which state the machine is, so I'm pretty much left with only Java to do the job.
I've given it a lot of thought today but I'm just stuck. Any fresh ideas?
BTW, it supports only Java up to 1.4 so no advanced concurrency classes for me.
Edit: I forgot to mention that I can't just code a regular timer, since I can't capture native events from the system (I can capture events from other Java applications though) and a Java timer overrides the native timer function. That's why I need some "coordinate work" between them.

Task scheduling for multiple tasks in java?

i have build a java clock with using timer,which works fine for a single task to alarm on next given/setted time, but i am having problem in scheduling multiple tasks(alarms for diff. times) with this timer, as two times can clash each other(same times for two different works) how to synchronize between such conditions, please help....
Thanks and Regards
Alok Sharma
I'm not sure what you're trying to do, but if you use quartz scheduler, you can resolve just about any scheduling/synchronisation task:
http://www.quartz-scheduler.org/
I agree with Lukas that you can use quartz. It is the best, scalable and robust solution.
But if you need something relatively small you can continue using timer based solution. As javadoc of Timer class indicates your tasks should take very few time. In this case you can forget about time clash. If your tasks take more then 0.1 seconds run them in separate thread. I mean use Timer as a trigger that just makes task to start in separate thread.
The thread may be done as following:
Create thread yourself. If you are in J2EE container it is bad practice. If you are in Tomcat it is ... not so bad.
Use thread pool. Comments about container are relevant here too.
Use JMS: Timer just pushes message to JMS. MDB or its equivalent receives message and performs task.
Using Timer itsef in J2EE container is a bad practice too. If you are there and wish to be "clean" use JCA to to run Timer.

Running a regular background event in Java web app

In podcast #15, Jeff mentioned he twittered about how to run a regular event in the background as if it was a normal function - unfortunately I can't seem to find that through twitter. Now I need to do a similar thing and are going to throw the question to the masses.
My current plan is when the first user (probably me) enters the site it starts a background thread that waits until the alloted time (hourly on the hour) and then kicks off the event blocking the others (I am a Windows programmer by trade so I think in terms of events and WaitOnMultipleObjects) until it completes.
How did Jeff do it in Asp.Net and is his method applicable to the Java web-app world?
I think developing a custom solution for running background tasks doesn't always worth, so I recommend to use the Quartz Scheduler in Java.
In your situation (need to run background tasks in a web application) you could use the ServletContextListener included in the distribution to initialize the engine at the startup of your web container.
After that you have a number of possibilities to start (trigger) your background tasks (jobs), e.g. you can use Calendars or cron-like expressions. In your situation most probably you should settle with SimpleTrigger that lets you run jobs in fixed, regular intervals.
The jobs themselves can be described easily too in Quartz, however you haven't provided any details about what you need to run, so I can't provide a suggestion in that area.
As mentioned, Quartz is one standard solution. If you don't care about clustering or persistence of background tasks across restarts, you can use the built in ThreadPool support (in Java 5,6). If you use a ScheduledExecutorService you can put Runnables into the background thread pool that wait a specific amount of time before executing.
If you do care about clustering and/or persistence, you can use JMS queues for asynchronous execution, though you will still need some way of delaying background tasks (you can use Quartz or the ScheduledExecutorService to do this).
Jeff's mechanism was to create some sort of cached object which ASP.Net would automatically recreate at some sort of interval - It seemed to be an ASP.Net specific solution, so probably won't help you (or me) much in Java world.
See https://stackoverflow.fogbugz.com/default.asp?W13117
Atwood: Well, I originally asked on Twitter, because I just wanted something light weight. I really didn't want to like write a windows service. I felt like that was out of band code. Plus the code that actually does the work is a web page in fact, because to me that is a logical unit of work on a website is a web page. So, it really is like we are calling back into the web site, it's just like another request in the website, so I viewed it as something that should stay inline, and the little approach that we came up that was recommended to me on Twitter was to essentially to add something to the application cache with a fixed expiration, then you have a call back so when that expires it calls a certain function which does the work then you add it back in to the cache with the same expiration. So, it's a little bit, maybe "ghetto" is the right word.
My approach has always been to have to OS (i.e. Cron or the Windows task scheduler) load a specific URL at some interval, and then setup a page at that URL to check it's queue, and perform whatever tasks were required, but I'd be interested to hear if there's a better way.
From the transcript, it looks like FogBugz uses the windows service loading a URL approach also.
Spolsky: So we have this special page called heartbeat.asp. And that page, whenever you hit it, and anybody can hit it at anytime: doesn't hurt. But when that page runs it checks a queue of waiting tasks to see if there's anything that needs to be done. And if there's anything that needs to be done, it does one thing and then looks in that queue again and if there's anything else to be done it returns a plus, and the entire web page that it returns is just a single character with a plus in it. And if there's nothing else to be done, the queue is now empty, it returns a minus. So, anybody can call this and hit it as many times, you can load up heartbeat.asp in your web browser you hit Ctrl-R Ctrl-R Ctrl-R Ctrl-R until you start getting minuses instead of pluses. And when you've done that FogBugz will have completed all of its maintenance work that it needs to do. So that's the first part, and the second part is a very, very simple Windows service which runs, and its whole job is to call heartbeat.asp and if it gets a plus, call it again soon, and if it gets a minus call it again, but not for a while. So basically there's this Windows service that's always running, that has a very, very, very simple task of just hitting a URL, and looking to see if it gets a plus or a minus and, and then scheduling when it runs again based on whether it got a plus or a minus. And obviously you can do any kind of variation you want on this theme, like for example, uh you could actually, instead of returning just a plus or minus you could say "Okay call me back in 60 seconds" or "Call me back right away I have more work to be done." And that's how it works... so that maintenance service it just runs, you know, it's like, you know, a half page of code that runs that maintenance service, and it never has to change, and it doesn't have any of the logic in there, it just contains the tickling that causes these web pages to get called with a certain guaranteed frequency. And inside that web page at heartbeat.asp there's code that maintains a queue of tasks that need to be done and looks at how much time has elapsed and does, you know, late-night maintenance and every seven days delete all the older messages that have been marked as spam and all kinds of just maintenance background tasks. And uh, that's how that does that.
We use jtcron for our scheduled background tasks.
It works well, and if you understand cron it should make sense to you.
Here is how they do it on StackOverflow.com:
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/

Categories