On the one hand, the EJB Timer service won't gain you much more than simply having the Quartz callback methods calling a Session Bean method to do the work you need, since effectively that's all that the Timer service is doing.
In both cases there can be security/role issues (since the Timer service doesn't "log in" as anybody, you don't know "who" is making the EJB calls, well you do, it's Anonymous, but that's not helpful if Frank scheduled the job), if that's an issue for you.
JEE 6 timers are much better than JEE 5 timers, but most of that capability is available only from code (vs, say, the servers admin console, though some server may offer this facility, I don't know any that do. Services like "how many jobs are pending in the timer service" from the console.)
For example, in JEE 6 you can annotate a bean to "run every 5 minutes" or "every friday" etc.
That's all well and good, but if you wish to change that schedule, you get to rebuild/redeploy your application.
The other aspect to consider is that, by default, JEE timers are persistent. In JEE 6, this is now optional, it's default, but you can change it, however it was not optional in JEE 5.
By persistent that means that if you create a Timer that runs every 5 minutes, and restart the server, then when the server restarts the Timer will remain and execute again. Very likely it will execute immediately if the 5 minute window has passed, as Timers execute when the current time has passed their scheduled start time.
This is all well and good.
Where it become frustrating is two fold.
First, if you create a Timer for some future date (say, "run this next Wednesday"), then that Timer will fire next Wednesday, even if the server restarts.
However, the Timer is persistent to the APPLICATION, not the SERVER. If the server restarts you're good. If you redeploy the application, the timer Goes Away. Since the application is removed form the server (for redeployment), all of its Timers go with it.
That means your Wednesday job needs to be rescheduled.
If you were naive, every time the application started, you would create a Timer job that "runs on Wednesday". But if you simply rebooted the server, you'd end up with TWO jobs that run on Wed. So, you need to scan the current timer list to see if your job is already queued up. If "hard coding" the schedule in your bean is sufficient, that handles this problem nicely.
The other issue is that the container will start all (ALL) expired Timers as soon as the container has restarted. The problem here first is the potential "Timer storm". Say you have 5 jobs that are schedule to run in 1, 2, 3, 4 and 5 minutes. You have some issue with the system and it's down for 10 minutes before its restarted. When it's restarted, all 5 jobs will begin automatically, and simultaneously. Your container may have some way to throttle how may Timers can run at the same time.
But the other issue is that the lifecycle of Timers were, in JEE 5, undefined. In JEE 5, there was really no place to "hook in" when the application started up. Many folks hook in to a ServletContextListener to let them know when an application is starting up. This mostly works, but the nut is that the EJB tier pretty much has to be already running before the
Servlet tier fires up (since the Servlet tier will very likely be calling the EJB tier). So, by the time the ServletContextListener.contextInitialized method was called, any expired Timer sessions may well be off and away and running.
This is important in case your application start up need to initialize anything the Timer job may need to run, like some caches or other services.
JEE 6 MAY address this, indirectly, with the Singleton Session Bean. You can add @Startup to a Singleton Session Bean and it's guaranteed to be called before any EXTERNAL client requests are made. External as in external to the application. Are Timers external calls? *shrug* I dunno.
So, these are some "gotchas" regarding EJB timers that
you should be aware of.
If it were me, I'd manage all of the timers in my application, and mark them as non-persistent in EJB. That simplifies a lot of issues. Also, since methods can be Asynchronous, that relieves some of the processing issues with Timers (as they were the only "approved" way to run background processes in the EJB tier in JEE 5 since you shouldn't spawn threads).
We manage all of our timers in our app. On startup we lock down our Timer jobs, and then purge the EJB Timer service and reapply the timers from our DB. Our Timer jobs can't run until we've triggered that the system has started up to OUR satisfaction, and they just block waiting for that, and then quietly exit hoping they're rescheduled.
But we're on JEE 5, so we have to do that. JEE 6 would simplify my code a little, but likely not that much.