Using a Timer in Clojure

235 views
Skip to first unread message

Mathias Dahl

unread,
Sep 1, 2008, 5:11:15 PM9/1/08
to Clojure
I would like to have a java.util.Timer running in my Clojure webapp.
Once per week, some time each Friday, the code the timer calls would
send out an e-mail with news to a list of recipients. I have never
used Timers nor worked with threads in Java so this is kind of new
ground to me. I found some piece of code on Sun's site (http://
java.sun.com/products/jfc/tsc/articles/timer/) but did not understand
how to translate that to Clojure.

Has anyone here tried doing anything similar in Clojure?

Thanks!

/Mathias

.Bill Smith

unread,
Sep 2, 2008, 9:48:59 AM9/2/08
to Clojure
The following code creates a timer that runs after a delay of three
seconds.

(import '(java.util TimerTask Timer))

(let [task (proxy [TimerTask] []
(run [] (println "Running")))]
(. (new Timer) (schedule task (long 3000))))

I'll let someone else comment on the concurrency issues.

Bill

Josh Daghlian

unread,
Sep 2, 2008, 11:06:13 AM9/2/08
to Clojure
For regular tasks of the sort you describe, especially things like
sending out regular emails, backing up systems, and other maintenance
tasks, you may want to consider using cron on a unix machine instead.
Cron is a super old (read, highly configurable and well-understood)
piece of software (or family of nearly identical implementations,
anyway) that is designed exactly to trigger recurring tasks.

In each line of the configuration file (the "crontab"), one specifies
the text of a command and the month(s), day(s), day(s) of week,
hour(s), minute(s), and second(s). The command can be an arbitrary
terminal command, program, or shell script.

See http://en.wikipedia.org/wiki/Cron and scroll down to the "fields"
section.

In the 0.25M LOC system I program for at work, we write standalone
methods in Java (how I wish that some of them were in clojure) and use
cron to call them via JMX. Not only does this separate the timing code
from the thing being timed, but it puts the timing of these regular
(daily, weekly, hourly, etc.) background jobs in the hands of the
operations team, who can easily do things like turn them off during
upgrades or reschedule them when our usage patterns change.

I know this completely fails to answer your original question about
Timer, and it introduces more moving parts into your software, but
having fallen into this trap at least once I feel compelled to try to
spare you the pain of trying to reimplement unix cron.

Cheers.
--josh

J. McConnell

unread,
Sep 2, 2008, 11:14:26 AM9/2/08
to clo...@googlegroups.com
On Tue, Sep 2, 2008 at 11:06 AM, Josh Daghlian <dagh...@gmail.com> wrote:

For regular tasks of the sort you describe, especially things like
sending out regular emails, backing up systems, and other maintenance
tasks, you may want to consider using cron on a unix machine instead.

I'll second that it sounds like cron is what you're looking for here. However, another option also worth looking into is Quartz:

http://www.opensymphony.com/quartz/

It's a Java library for scheduling tasks. It's designed to satisfy all of the use cases of cron and then some and, since it's in Java, it is easy to reuse your existing Java/Clojure code. At my company we've had good results with both cron and Quartz for various tasks.

- J.

.Bill Smith

unread,
Sep 2, 2008, 12:08:33 PM9/2/08
to Clojure
> For regular tasks of the sort you describe, especially things like
> sending out regular emails, backing up systems, and other maintenance
> tasks, you may want to consider using cron on a unix machine instead.

Yup, lots of CRON-style functionality already exists, so no reason to
invent your own scheduler. Independent of that decision, you may gain
some reliability by running scheduled tasks in a separate process from
the webapp. If people depend on receiving those emails in a certain
timeframe, you don't want a webapp failure to get in the way.

Bill

Mathias Dahl

unread,
Sep 2, 2008, 2:49:01 PM9/2/08
to Clojure
It's all good advice and I have used cron before so it should not be
hard. However, there is one problem and that is that I need to open up
a Derby database from the cronjob, but as the database is already open
in the webapp, it is locked and cannot be opened until the webapp is
closed. So I will go for using a Timer, for now. The scheduling is not
very critical (It's more like "nice to have" and I could even call the
appropriate function manually once per week if needed) and restarting
the app if it becomes unstable in any way is no biggy either.

Thanks for all the tips!

/Mathias

pkw

unread,
Sep 6, 2008, 4:03:02 AM9/6/08
to Clojure


On Sep 2, 2:49 pm, Mathias Dahl <mathias.d...@gmail.com> wrote:
> It's all good advice and I have used cron before so it should not be
> hard. However, there is one problem and that is that I need to open up
> a Derby database from the cronjob, but as the database is already open
> in the webapp, it is locked and cannot be opened until the webapp is
> closed. So I will go for using a Timer, for now. The scheduling is not
> very critical (It's more like "nice to have" and I could even call the
> appropriate function manually once per week if needed) and restarting
> the app if it becomes unstable in any way is no biggy either.

If it's a webapp ...
Create a page that does what you want in whatever webapp framework you
use.
Have cron do a simple wget to that page at the appropriate time.
(some security would need to be implemented.)

Otherwise I second the usefullness of Quartz. It can be integrated
into the java webapp process, and it can configure just like cron. At
least I've done it with Tomcat and JBoss.
(IIRC Quartz has one extra field than what cron has in the job
settings. Maybe it's "seconds")

--paul wisehart

Mathias Dahl

unread,
Sep 6, 2008, 8:47:21 AM9/6/08
to Clojure
> If it's a webapp ...
> Create a page that does what you want in whatever webapp framework you
> use.
> Have cron do a simple wget to that page at the appropriate time.
> (some security would need to be implemented.)

That is quite clever. I might try that if the approach using a Timer
does not work out well.

Thanks!

/Mathias
Reply all
Reply to author
Forward
0 new messages