Thursday, January 24, 2008

Add a quartz job to Spring


There are a few steps to adding a quartz job to a Spring app:

1. Add the jars: quartz-1.6.0.jar, commons-logging.jar, commons-collections.jar. If also found I needed jta.jar for my cron trigger job.

2. Create your job class which is a QuartzJobBean, implementing the executeInternal method:

public class MyJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {

System.out.println("my job is running");
}
}

3. Add the quartz config into the spring web context xml. There are three parts:

3a. Add the job bean:

<bean name="myJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.test.MyJob" />
</bean>

3b. Add the trigger - I'm using a cron trigger which will run this job every 15 seconds:

<bean name="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="myJob"/>
</property>
<property name="cronExpression">
<value>0/15 * * * * ?</value>
</property>
</bean>

3c. Add the quartz factory, and name the trigger:

<bean
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="myTrigger"/>
</list>
</property>
</bean>

Compile. deploy and run!

If you want to add Spring injected classes into your job, use the jobDataAsMap property. In the example below myBean and myString have getters and setters in the MyJob class.

<bean name="myJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.test.MyJob" />
<property name="jobDataAsMap">
<map>
<entry key="myBean" value-ref="beanName" />
<entry key="myString" value="some value" />
</map>
</property>
</bean>

That's it!

Monday, November 5, 2007

Bounce apache

I don't bounce apache enough to remember the command, so here it is:

/usr/local/apache2/bin/./apachectl restart

Tuesday, October 9, 2007

Broken pipes with Tomcat and DBCP connection pooling

Getting "broken pipe" errors showing up in your tomcat logs? Happening every 8 hours or so?I had this problem with MySQL 4.1.21 and I've managed to fix it.

(NB. if you are running 5.0.45 MySQL then you'll get a "com.mysql.jdbc.CommunicationsException: Communications link failure" error which is a symptom of the same problem)


A quick search of the web revealed that lots of people are getting these and there are LOTS of suggested solutions. The most common explanation is that your MySQL connections are getting terminated by MySQL before they have been released by the connection pool. Then the next time you try to get a connection from the pool, you'll get a dead connection which will give a "broken pipe" error.

The first step is to try and reproduce it, without waiting around for 8 hours!

I checked the MySQL timeout setting via "mysql> select @@global.wait_timeout". Mine was set to 28,800 which is, not suprisingly, 8 hours. I then reduced this to one minute by:
  • stopping MySQL ("/usr/local/bin/mysqladmin shutdown"),
  • modifying the /etc/my.inf file and adding a "wait_timeout=60" under the "[mysqld]" heading and saving,
  • restarting MySQL ("/usr/local/mysql/mysqld_safe")
Don't worry if your session timeout hasn't changed ("mysql> select @@session.wait_timeout") - it doesn't seem to affect your terminal session. Your global session will have changed, and new connections will use the global setting.

Next I started my application and saw my connections appear (via "mysql> show processlist;") and then disappear at the 60 second mark. Trying to use the app again resulted in the broken pipe error HOORAY! Retrying the app resulted in one broken pipe error per connection in the pool, then it all works OK.

Now the fix.

Appending ?autoconnect=true to the JDBC driver connection string didn't work.

Killing the idle session before MySQL did was the solution. With the MySQL timeout still set at 60 seconds, I decided to evict idle session after 30 seconds by adding the following to the data source:

minEvictableIdleTimeMillis=30000 (evict after 30 seconds inactivty)
timeBetweenEvictionRunsMillis=10000 (run the evicter every 10 seconds)
numTestsPerEviction=-1 (check every connection)

Now, running the same test above, the connections disappear from the list after about 40 seconds. And retrying the ap just creates a new connection. HOORAY! Fixed!! If you are not happy with your connection pool getting wiped out then you can set "minIdle=n" against the data source. When the items from the pool are evicted, new ones are crested to keep the pool full.

In the end I went for a 6 hour idle eviction, checking very 30 mins.

Friday, September 21, 2007

Testing an Http POST from the command line

Got a REST web service update using an Http POST that you want to test? If so, run this command:

curl --header "Content-Type: text/xml" --data '' "http://www.myserver.com/myapp/AppServer" –i

And get this result:

HTTP/1.1 200 OK
Date: Fri, 21 Sep 2007 00:43:08 GMT
Set-Cookie: JSESSIONID=4EB1673F5BD20FF0495A9FBB38017C38; Path=/myapp
Content-Type: text/xml;charset=ISO-8859-1
Transfer-Encoding: chunked



You can easily time it using:

time curl --header "Content-Type: text/xml" --data '' "http://www.myserver.com/myapp/AppServer" –i

Wednesday, June 20, 2007

"failed to install tomcat5 service" woes?

Trying to install Tomcat 5.x on your XP machine and getting this message:

"failed to install tomcat5 service" Abort, Retry, Ignore...?

The problem could well be that you have already installed Tomcat5 before on this machine and windows is not happy trying to install a second Tomcat5 service. In my case I had installed Tomcat5 before and had deleted it but the old service was still hanging round. The solution is to remove the old service and then the install will continue along happily.

To see if you already have a Tomcat service, you can look in the Service window (under Start-Control Panel-Administrative Tools-Services) and look for a service called "Apache Tomcat". That is the sucker. Right-click and look at the Properties. Check the service name - it will be "Tomcat5". Stop the service if it is running.

Then fire up a command window and run this command:

>sc query tomcat5

This will give you details of the service (if you spell it right). To delete the service:

> sc delete tomcat5

and you should get a nice "[SC] DeleteService SUCCESS" message.

Now you can continue your install!

Friday, May 11, 2007

What jar files to add to your Spring app for Xfire

To expose some of your Spring classes as web services via Xfire you can follow one of the many tutorials on the web. But nobody tells you which jar files into your class path. These worked for me (under Apache Tomcat 5.5 runing Spring 1.2.9):
  • xfire-all-1.2.4.jar - the main library for xfire
  • activation-1.1.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.jar
  • jdom-1.0.jar
  • jsr173_api-1.0.jar
  • mail-1.4.jar
  • stax-1.1.2-dev.jar (this was a pain in the a$%#e to determine!)
  • stax-api-1.0.1.jar
  • wsdl4j-1.6.1.jar
  • xbean-spring-2.7.jar
  • XmlSchema-1.1.jar
This was in addition to usual jar files that MyEclipse will add to your Spring web project when you add Spring capabilities.

Spring and log4j

If you have a Java Spring web application in Apache and are getting this error:

log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).
log4j:WARN Please initialize the log4j system properly.


Then you can fix it by making sure that the log4j.properties file gets deployed to the classes folder under .../webapps/{project}/WEB-INF/classes/

Try sticking it in there and the error should go away. Too easy!