Rob Williams is a probabilistic Lean coder of Java and Objective-C. Rob is a DZone MVB and is not an employee of DZone and has posted 171 posts at DZone. You can read more from them at their website. View Full User Profile

Another Java Disaster: Jobs

  • submit to reddit

I‘ve blogged before about my low opinion of Quartz. Ok, for everyone who loves to make the argument that we live in the land of choice, and the ‘boy, I‘m not going to end up trapped in a walled garden, I‘m going to have choices.‘ 15 years on, we have one job engine that if you showed it to someone serious (and they didn‘t know what it was) they would guess it was in the pupal stage. It‘s anemic feature set is a complete joke. And yet, it‘s been adopted by Spring and Seam. Why? Welcome to the choicest monoculture around: Java.

Now here‘s the surprise in today‘s post: starting from this scabbed puss pocket, Seam somehow found a way to make it even worse.

First off, I defy anyone to read the documentation to the Quartz wrapper in Seam and not develop a stage 4 migraine. It‘s like ‘wait, how do I get something to run at a given time?‘ You‘d think there would be a simple answer. Instead, a clown car of insanity seeps out that makes that old Belushi skit on SNL about the watch that‘s so complex you have to flag someone down in the street to help you get the time from it look kind of staid. Why is it so confusing? Because you can use annotations. But you still have to configure it in components.xml, then the method itself has a return value of the QuartzTriggerHandle, but forget that, it can be null. (In other words: senselessness is the dominant quality.)

People used to mock C++ as the wrapper language. At least their wrappers did stuff!! Java is so full of wrappers that actually decrease functionality it‘s whacked. That‘s what happens here: promise: augmentation, reality: diminishment (some musical theory humor).

So after the API/approach has rolled off you like a spattering of mercury, and you start to use the thing, that‘s when it gets really dark. So I wanted to add some retry logic. How hard could that be in a job engine that‘s been around for 15 years? Apparently no one ever thought of that on the team, because there is no support. So I found an example, that was kind of nice: terse, clear, on Github. Saw that the dude extended SimpleTrigger and just overloaded executionComplete. Perfect. This is going to take no time at all. [Extra credit: guess which design pattern came to mind?... A: the same one that the layout managers in Swing use.]

So then, I go back to the QuartzTriggerHandle, thinking ‘this must extend or Decorate the trigger.‘ Nope. Then it must let me inject it. Nope. Drilled around a bit and found, to my horror, it makes the trigger, by violating the first commandment of DI: thou shalt not new!! Seriously, Guys? I mean, really?

Some people would say this platform has bred mediocrity. Um, I‘m dying to find something mediocre. For all the shortcomings of the C++ community (and there were plenty) it makes Java look like a goat rodeo.



Published at DZone with permission of Rob Williams, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)



The Wanderer replied on Mon, 2011/03/21 - 5:33am

Um, what the fuck? How about you just implement the execute(..) method (of the Job interface) like this: try { ... } catch(JobExecutionException e) { e.setRefireImmediately(true); throw e; } Et voila, a simple Job that will retry indefinitely. Now you figure out for yourself how to retry only n times...serious: either i didn't get what your rant is about, or you should stop whining & start working. Don't blame Java for your own stupidity, thank you very much.

Rob Williams replied on Mon, 2011/03/21 - 9:42am in response to: The Wanderer

lol.. yeah, you missed it (somehow): I should be able to make a trigger type that has retry logic built in so I don't have to implement it every time I use it. Your 'mentality' (stress on the mental part) is a perfect example of what I'm talking about: the API has been designed for dopes like you. No extension is provided for because they have figured out that a. you would never think about solving a problem at an abstract level, and b. you gotta keep moving.. don't think, that's going to make you seize up with an anxiety attack, 'start working'... :p .. like a shark, or, no, more like the people those new one arm bandits they talked about on 60 Minutes a few months ago: they put their users into a trance by giving them tiny little rewards so rapidly that later, they don't even know they lost all their money.

Karl Peterbauer replied on Mon, 2011/03/21 - 12:24pm

Um, what the fuck?

First, it's easy to find architectural flaws in a scheduler API dating back to 2002 or it's CDI wrapper. No reason to freak out.

Secondly, your objective of a "retry logic" is questionable anyway: If a job is executed regularly, then your programmatic "retry logic" just adds another, higher periodicity. If your job is designed properly, then it should be able to detect incompleteness quickly, so you can schedule it with a high rate and you get your "retry logic" for free.

Thirdly, please don't ever try to get your hands dirty with real-world system administration (= cron, bash, perl and friends). Your central nervous system might get severly damaged.

Radu Alex replied on Mon, 2011/03/21 - 12:26pm

I never understood this pessimistic attitude and I don't think that this kind of articles are useful or informative for anyone. Clearly NOT the Java spirit we are all used with.

What I expect to read on DZone (great informative site, btw) is an article that:
- presents the background of the problem
- presents the current way to resolve the problem
- comes with arguments about why the current solution is not a viable one
- present and argument a new algorithm or solution
Just cursing the frameworks creators because they didn't implement a solution that you have in mind is not a nice attitude...

Branden Makana replied on Mon, 2011/03/21 - 12:48pm in response to: Radu Alex

I second this comment - while I've worked with Quartz+Spring before and didn't have any issues, I wasn't doing exactly what the author was doing. Either way though, this is something that belongs on a message board as a complaint. This article was unhelpful in that it didn't lay out the solution the author came up with to bypass the perceived issue, so it ends up being just a rant.

James Jamesson replied on Mon, 2011/03/21 - 2:00pm in response to: Rob Williams

lol, it is time to get off the bus then.

Rob Williams replied on Mon, 2011/03/21 - 2:27pm in response to: Radu Alex

Great, why don't you show me the way Radu: write a tutorial on extending SimpleTrigger in Seam.

Rob Williams replied on Mon, 2011/03/21 - 2:32pm

How do you solve the problem? There is no solution: you cannot create a trigger because the Seam class already newed it. I could rewrite that class. So far, I have not chosen to do that.

If you have a solution to this, please advance it. Lots of people did that on my blog, was very interesting. Just sitting there and saying 'der, he's not nice,' is pretty silly. Furthermore, it raises some questions about frameworks when they preach something they are not practicing.

Frankly, the solution I'm leaning most toward is writing a simple job engine myself and open sourcing it. Making a pluggable retry Strategy is something I could make work in < 1h.

If you are just looking for stories with immediate, happy endings, don't read my stuff.

Amir Laher replied on Mon, 2011/03/21 - 10:05pm

I have something constructive to offer. It may help:

Spring 3 has introduced its own Scheduler feature, which I've found really easy to use, and for my current project, it gave me something much closer to what I expected from Quartz, with much less time and much less headache.

Granted, I was already using Spring's IOC for my app, but you don't actually need to be using their IOC container.

You could set up a plain-Java scheduler, but I used the Spring config approach. This example shows a scheduler with 2 scheduled tasks:

<task:scheduler id="MyScheduler" pool-size="1" />
<task:scheduled-tasks scheduler="MyScheduler">
<task:scheduled ref="manager" method="notifyProcessList" fixed-rate="5000" fixed-delay="1"/>
<task:scheduled ref="simpleProcessor" method="process" cron="3/10 * * * * ?"/>

See docs for more info:


Note1: this addresses the DI issue that Quartz introduces with it's icky "JobDetail" definitions. In case it wasn't obvious, in the above example, the ref="manager" and ref="simpleProcessor" are references to existing objects in the applicationContext.

Note2: There isn't any 'retry' feature that I'm aware of (it rdoesn't really bother me, but anyway).

Cloves Almeida replied on Mon, 2011/03/21 - 10:11pm

I've had my headaches with Quartz, but mostly because I didn't fully understand the concepts. Other than that, it's pretty good and has some kick-ass features I wouldn't dream about re-implementing (like guaranteed persistent job execution inside a JTA transaction).

The Seam cron wrapper is ALPHA state and not a top priority. If you do need something like a "@Retry" modifier or make the Scheduler injectable so you can build your own trigger, you're welcome. The developers at Seam are pretty open about contributions.

Another idea is dropping the job engine altogether and just expose the jobs through REST calls and use cron. Seam REST support is top-notch.

Cloves Almeida replied on Mon, 2011/03/21 - 10:18pm

And before you try to reinvent the wheel:

Rob Williams replied on Tue, 2011/03/22 - 12:49am in response to: Cloves Almeida

Agents would be better than REST and CRON. One of the problems with REST is that it's ultimately just data centric. Jobs, especially when you start really thinking about modeling them (something the Quartz team never got bogged down in), is all about behavior. As to the persistence in JTA, I guess that's really great if you need it. But would have been nice if they delivered that after doing a really complete job model.

Rob Williams replied on Tue, 2011/03/22 - 12:50am in response to: Amir Laher

Thanks, Amir, I will have a look.

Fab Mars replied on Wed, 2011/03/23 - 12:09pm

+1 to Karl and Radu... My advice is not to use Quartz and do it with your own muscled fingers(tm) oçr with another fw.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.