Chaining job execution in Quartz

Quartz javaThere isn’t explicit way to chain jobs in Quartz. However this is still possible, by doing some tricks. Here is an explanation on how to do that (in very few words).

There are two ways to put job in chain:
– first one, by using Listeners( for example JobChainingJobListener),
– and the second one, by using JobDataMap which every job contains.
I prefer the second way with JobDataMaps. Why ? Because DataMaps are persistent so information about chained jobs survives restart of the server.

Chain is nothing more than normal queue of the jobs, so to put two jobs into chain we need to create queue from them. Queue should be bidirectional to allow easy manipulation. The idea is to put 4 properties into JobDataMaps:
– nextJobName, nextJobGroup – identify next job in chain
– previousJobName, previousJobGroup – identify previous job in chain

Those 4 variables are enough to implement standard bi-directional queue operations like: addJobToQueue(..), removeFromQueue(..), moveUp(..) and moveDown(..). One thing to remeber: adding job to chain should stop it, to avoid triggering jobs in unspecified order.

Last thing to do is to create own implementation of the Quartz Job interface which, in execute() method, will fire/trigger next job in chain, if there is any.

That’s all.

You May Also Like

Grails with Spock unit test + IntelliJ IDEA = No thread-bound request found

During my work with Grails project using Spock test in IntelliJ IDEA I've encountered this error:

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.codehaus.groovy.grails.plugins.web.api.CommonWebApi.currentRequestAttributes(CommonWebApi.java:205)
at org.codehaus.groovy.grails.plugins.web.api.CommonWebApi.getParams(CommonWebApi.java:65)
... // and few more lines of stacktrace ;)

It occurred when I tried to debug one of test from IDEA level. What is interesting, this error does not happen when I'm running all test using grails test-app for instance.

So what was the issue? With little of reading and tip from Tomek Kalkosiński (http://refaktor.blogspot.com/) it turned out that our test was missing @TestFor annotation and adding it solved all problems.

This annotation, according to Grails docs (link), indicates Spock what class is being tested and implicitly creates field with given type in test class. It is somehow strange as problematic test had explicitly and "manually" created field with proper controller type. Maybe there is a problem with mocking servlet requests?

Spring Security by example: OpenID (login via gmail)

This is a part of a simple Spring Security tutorial: 1. Set up and form authentication 2. User in the backend (getting logged user, authentication, testing) 3. Securing web resources 4. Securing methods 5. OpenID (login via gmail) 6. OAuth2 (login v...This is a part of a simple Spring Security tutorial: 1. Set up and form authentication 2. User in the backend (getting logged user, authentication, testing) 3. Securing web resources 4. Securing methods 5. OpenID (login via gmail) 6. OAuth2 (login v...