I have multiple executable JARs, let's call them task1.jar, task2.jar, task3.jar, etc...
They mainly access the database and do housekeeping tasks on the server.
They are run by cron jobs, one after another, early in the morning everyday. The crob jobs are set about 15 minutes apart.
The crob jobs simply just call:
java -jar taskX.jar
Depending on the data on the database, their durations to finish will vary.
The task executions must not overlap. Otherwise when they access the database at the same time, the server will crash. It has happened before when one task takes too long to run and hasn't finished before another task has started.
So my question is... is there anyway to check a JAR has started or finished so that the next JAR can be delayed?
I would preferably resolve this with Java methods over changing any configs on server which I have limited access on.
Edit: #mksmanjit Sorry, I didn't mention before. There is also one complication - not all of them are run everyday. For example, task1.jar and task3.jar may be run everyday, task2.jar may be run every two days and task4.jar may be run every Mon, Wed, Fri, etc... So the situation can get quite complicated.
Couple of ways as I see it !
Let all JAR (or tasks) write Logs in a common or a separate log file. (Usually feasible if you only want to capture minor details such as start time , stop time, result etc) Assuming format you keep is manually readable.
As per above suggestion, create a Table in DB to keep a track of task activity along with task name, it's details such as trigger by, start time, end time, result etc
Alternatively, create database Triggers to monitor event (such as write or read) on DB table and whenever your task executes, trigger will also execute depending on what DB actions you want your trigger to perform such as sending e-mail, writing to table, printing simple log
Let JARs (or tasks) also print logs on console just in case assuming they are designed to view from any console or UI at runtime !
Related
I am currently working on a scheduled task that runs behind the scenes of my Spring web application. The task uses a cron scheduler to execute at midnight every night, and clean-up unused applications for my portal (my site allows users to create an application to fill out, and if they don't access the form within 30 days, my background task will delete it from our DB and inform the user to create a new form if needed with an email). Everything works great in my test environment, and I am ready to move to QA.
However, my next environment uses two load balanced servers to process requests. This is a problem, as the cron scheduler and my polling task run concurrently on both servers. While the read/writes to the DB won't be an issue, the issue lies with sending the notification email to the application user. Without any polling locks, two emails have the possibility to be generated and sent, and I would like to avoid this. Normally, we would use a SQL stored procedure and have a field in our DB for a lock, and then set/release whenever the polling code is called, so only one instance of the polling will be executed. However, with my new polling task, we don't have any fields available, so I am trying to work on a SPRING solution. I found this resource online:
http://www.springframework.net/doc-latest/reference/html/threading.html
And I was thinking of using it as
Semaphore _pollingLock = new Semaphore(1);
_pollingLock.aquire();
try {
//run my polling task
}
finally {
//release lock
}
However, I'm not sure if this will just ensure the second instance executes after, or it skips the second instance and will never execute. Or, is this solution not even appropriate, and there is a better solution. Again, I am using Spring java framework, so any solution that exists there would be my best bet.
Two ways that we've handled this sort of problem in the past both start with designating one of our clustered servers as the one responsible for a specific task (say, sending email, or running a job).
In one solution, we set a JVM parameter on all clustered servers identifying the server name of the one server on which your process should run. For example -DemailSendServer=clusterMember1
In another solution, we simply provided a JVM parameter in the startup of this designated server alone. For example -DsendEmailFromMe=true
In both cases, you can add a tiny bit of code in your process to gate it based on the value or presence of the startup parameter.
I've found the second option simpler to use since the presence of the parameter is enough to allow the process to run. In the first solution, you would have to compare the current server name against the value of the parameter instead.
We haven't done much with Spring Batch, but I would assume there is a way to configure Batch to run a job on a single server within a cluster as well.
I have not yet coded a potential solution to this, so before anyone asks I have zero code to back this up as I am trying to get a firm grip on the processing behind what needs to happen.
My problem is that I have an Oracle database that will be firing off jobs constantly (every 10 minutes or so) and I need a safe way (security wise and data integrity wise), to terminate these jobs and prevent them from executing while a nightly back up takes place. For the sake of discussion this will be done via a cron job. The way I think it should work is that the cron job will fire off at a time of 1 am (or some other low usage time, by low I mean < .001% of the user base will be interacting with the system). The java process will need to execute some PL/SQL function on the database that does the following things:
1) A force terminate on all running jobs
2) A snapshot of data that is to be written to an arbitrary directory
3) Restart all jobs (mark them as enabled instead of disabled)
My question is this:
How can this be accomplished with the minimum amount of permissions and does this loose architecture facilitate the ability to prevent data corruption, assuming Oracle is correctly generating undo/redo logs? IF this is an insecure/poor way of doing this, any other suggestions are appreciated.
In Oracle 10+ DBMS_Scheduler has a window definition that does exactly what you want. When the window ends, processing of running jobs can be terminated.
http://docs.oracle.com/cd/E14072_01/appdev.112/e10577/d_sched.htm
I have a Java/Database project in Netbeans that I would like to run once a day at a set time. I am using Derby for the database driver. I am trying to automate a process.
How can I 'schedule' this program to run at specified times?
How can I customize this to keep running until a certain criteria is met?
Say my criteria is that It has to populate 500 rows in the database. (So say at the scheduled time it runs it can only populate 400 rows, then maybe 2 hours later it tries running again to fill the last 100 rows)
Lastly, what are the best practices of automation and scheduled tasks?
How can I 'schedule' this program to run at specified times?
This can be done one of two ways, depending on your operating system - write a job that kicks off the java program at the intervals you need. You may then hook up the job to be started off on start up.
In Linux you can accomplish this with a cron job or so. On windows you may refer to this http://support.microsoft.com/kb/308569.
You may also program the scheduler into your java program using http://quartz-scheduler.org or http://www.sauronsoftware.it/projects/cron4j/ .
How can I customize this to keep running until a certain criteria is met?
This is perhaps best established from within your program, although it is hard to give you directions without much info.
Lastly, what are the best practices of automation and scheduled tasks?
Depending on your application architecture, scheduling and automation can be handled either from within the app or get support from the operating system. The criteria depends on how much control the application needs, which platform makes scheduling easy etc.
Hope this helps.
Quartz is a scheduling project for Java. I have used it in many projects and find it to be very intuitive.
It may be a little over the top for what your after but worth a look anyway.
You can make use of Timer for scheduling the events & the events/task must be implemented using TimerTask
I have a swing desktop application that is installed on many desktops within a LAN. I have a mysql database that all of them talk to. At precisely 5 PM everyday, there is a thread that will wake up in each of these applications and try to back up files to a remote server. I would like to prevent all the desktop applications from doing the same thing.
The way I was thinking to do this was:
After waking up at 5PM , all the applications will try to write a row onto a MYSQL table. They will write the same information. Only 1 will succeed and the others will get a duplicate row exception. Whoever succeeds, then goes on to run the backup program.
My questions are:
Is this right way of doing things? Is there any better (easier) way?
I know we can do this using sockets as well. But I dont want to go down that route... too much of coding also I would need to ensure that all the systems can talk to each other first (ping)
Will mysql support such as a feature. My DB is INNO DB. So I am thinking it does. Typically I will have about 20-30 users in the LAN. Will this cause a huge overhead for the DB to handle.
If you could put an intermediate class in between the applications and the database that would queue up the results and allow them to proceed in an orderly manner you'd have it knocked.
It sounds like the applications all go directly against the database. You'll have to modify the applications to avoid this issue.
I have a lot of questions about the design:
Why are they all writing "the same row"? Aren't they writing information for their own individual instance?
Why would every one of them have exactly the same primary key? If there was an auto increment or timestamp you would't have this problem.
What's the isolation set to on the database connection? If it's set to SERIALIZABLE, you'll force each one to wait until the previous one is done, at the cost of performance.
Could you have them all write files to a common directory and pick them up later in an orderly way?
I'm just brainstorming now.
It seems you want to backup server data not client data.
I recommend to use a 3-tier architecture using Java EE.
You could use a Timer Service then to trigger the backup.
Though usually a backup program is an independent program e.g. started by a cron job on the server. But again: you'll need a server to do this properly, not just a shared folder.
Here is what I would suggest. Instead of having all clients wake up at the same time and trying to perform the backup, stagger the time at which they wake up.
So when a client wakes up
- It will check some table in your DB (MYSQL) to see if a back up job has completed or is running currently. If the job has completed, the client will go on with its normal duties. You can decide how to handle the case when the job is running.
- If the client finds that the back up job has not been run for the day, it will start the back up job. At the same time will modify the row to indicate that the back up job has started. Once the back up has completed the client will modify the table to indicate that the back up has completed.
This approach will prevent a spurt in network activity and can also provide a rudimentary form of failover. So if one client fails, another client at a later time can attempt the backup. (this is a bit more involved though. Basically it comes down to what a client should do when it sees that a back up job is on going).
I have a java program which creates a lock file to ensure that no other executions run at the same time as it. If the program runs it creates the file, and upon exit, either successful or via an exception, the file is removed. But if the user hits Ctrl+C, closes the terminal, or in some other way interrupts execution, the file is not deleted. Is there any way to detect this interrupt command and ensure that the file is deleted in this case as well?
You might want to look into shutdown hooks.
Also, this is probably a duplicate or near-duplicate of this previous SO question from a day or two ago:
How can I "intercept" Ctrl+C in a CLI application?
The only good way to deal with this is to timestamp your log file, and update the logfile with a new timestamp every few seconds. File.deleteOnExit will help, but no method is foolproof (what happens when someone just pulls the power cord?).
If you write a timestamp, then you can check for a valid timestamp (recently written) and overwrite the log file if it is too badly out of date. That way a stale lockfile won't get in the way of the user.