Wednesday, September 24, 2008

The Mysterious Ways of SchedulerFactoryBean

Using Spring framework and Quartz, I wanted to make some dynamic Jobs and triggers. After banging my head and some accidents I finally understood how to use it. The API docs say:

"For dynamic registration of jobs at runtime, use a bean reference to this SchedulerFactoryBean to get direct access to the Quartz Scheduler (org.quartz.Scheduler). This allows you to create new jobs and triggers, and also to control and monitor the entire Scheduler."

What the hell that means, I couldn't figure. Hunting for some examples on the web didn't help either. In one of my posts I have given a link to fine tune SchedulerFactoryBean for static jobs. Picking from there, let us assume you have a Stocks Alert Manager to which you wish to give a spring managed scheduler using your very own SchedulerFactoryBean . Let us assume your stockAlertsManager looks like this:


Then your bean config should look something like this:

If you have not noticed, the scheduler property of StockAlertsManager is of type org.quartz.impl.StdScheduler but in the bean config I have set it to the reference of our all-powerful SchedulerFactoryBean. Despite of the mismatch in types your spring application will not complain and initialize the scheduler property nicely. Even when SchedulerFactoryBean does not in any way extend StdScheduler or implement Scheduler . Wierd, counter-intuitive but works. Re-visiting the API doc:

"For dynamic registration of jobs at runtime, use a bean reference to this SchedulerFactoryBean to get direct access to the Quartz Scheduler (org.quartz.Scheduler). This allows you to create new jobs and triggers, and also to control and monitor the entire Scheduler."

Well, they literally meant it! Who would have thought?!

Tuesday, September 23, 2008

Using Autowiring for Testing RMI Services in Spring

Scehduling can be a common requirement in many applications. However testing such an application that used RMI with JUnit and JMock in a Spring-Maven environment turned out to be a little tricky for me. Thanks to the help of a colleague (thanks Mudassir!) and some head banging, I was able to find a way: Autowiring.

Generally my basic JUnit test cases have the following features:
1. The whole class annotated by @RunWith(JMock.class) - org.junit.runner.RunWith;
2. A set up method (the init method) annotated with @Before - org.junit.Before
3. The test cases annotated @Test - org.junit.Test
4. JUnit4Mockery used to mock relevant interfaces - org.jmock.integration.junit4.JUnit4Mockery
5. The usual expectatons and assertions
6. Spring adds punch with ability to mock request, response, sessions - org.springframework.mock.web.*

A Simple Test Case

Works fine for most things. Now picture this: you are developing application that needs to check stock prices every five minutes and send alerts to registered users if need be. Lets say there are three modules being developed for it: the user interface using which a user may register for an alert for stock price, the scheduler that keeps track of these alerts and the workflow engine that takes care of the alerts once fired. A classic MVC approach so far.

The controller accepts alerts from user interface and schedules Jobs that forward all information to the workflow. Let us assume these three modules are being developed by three different teams sitting in three corners of the world (ok, may be three corners of the office or just three different/independent machines/servers).

Now, when you are making the controller, you are essentially dependent on view for input and on the model for feedback (if any) for your input. We can provide access to our controller using any RMI strategy. For our example, we consider Spring's HttpInvoker. We intend to write a a test case to test the controller module.

Our controller has a remote service running in a spring environment. If it had been a simple servlet listening to ordinary post/get requests, writing a test case with MockHttpRequest would be a piece of cake. However when it is an RMI service, what mock up to use? An answer can be a test class looking something like this:

A Test Case For RMI Service


The answer lies in using SpringJUnit4ClassRunner and then auto-wiring the HttpInvokerService. ContextConfiguration points to the locations for the config xml. In the current case you should put it in "myPackage. If you are using Maven, the resources folder would be the right place to put it. The config file may look like:

Autowiring Config


If you are using Maven, don't forget to add the following dependencies:

Maven Dependencies

A few tweaks may be needed to suit your case but this should give you a general idea about using autowiring for your test cases in JUnit, JMock, Spring, Maven environment.

Friday, September 12, 2008

Maven Blues

Was facing a strange problem where Maven (version 2) would say something like "generics are not supported in -source 1.3" for Java 5 features. Adding the following the Plugins element in the pom helped:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugins>

Wednesday, September 3, 2008

Quartz and Spring

For scheduling purposes one can use Quartz with Spring. The basic usage can be learnt by going through the quartz tutorial and spring documentation on scheduling .

However when it came to using advanced usage like configuring job stores, I had a little difficulty finding stuff. A particular entry in the spring forum was really useful. These three resources were able to take care of my reasonably complex needs for scheduling. Hope they are of some use to you too.