Archive

Posts Tagged ‘Maven’

Scheduling using Quartz

June 8, 2010 2 comments

Many times we need to perform repetitive jobs in our applications. One common way is to use Thread.sleep method but if you need to synchronize the start of the job based on clock cycles , using a Quartz scheduler is way simpler. Cron triggers can be used to schedule the time that the job starts. We will take a look at how to use Quartz in the non-spring and spring way.

Without Spring…
Get the Quartz 1.8.0 download from here. Add the slf4j jars to the classpath.
My main class looks like this…

public class Main {

 public static void main(String[] args) throws SchedulerException, ParseException {
 Main main = new Main();
 main.scheduleJobs();
 }

 public void scheduleJobs() throws SchedulerException, ParseException {
 SchedulerFactory factory = new StdSchedulerFactory();
 Scheduler sch = factory.getScheduler();
 JobDetail jobDetail = new JobDetail("testJob", null, MyTestJob.class);
 CronTrigger cron = new CronTrigger("testCron", null , "* * * * * ?");
 sch.scheduleJob(jobDetail, cron);
 sch.start();
 }
}

What we have done here is that we have created a scheduler by using SchedulerFactory. JobDetail is the definition of the job that will be run once the trigger fires. “testJob” is the name we give to the job detail, its group is “null” and the class that implements Job is MyTestJob. Similarly, the CronTrigger has the name “testCron”, belongs to group “null” and has a cron expression that fires every second.

The MyTestJob class is as follows…

public class MyTestJob implements Job {

 @Override
 public void execute(JobExecutionContext arg0) throws JobExecutionException {
 System.out.println("In my job.");
 }
}

If we run the program we will see some log messages and then the following output will be printed on the console.. one line every second…
In my job.
In my job.
In my job.
In my job.

Using Spring..
We first create a basic Spring project with Maven… see my older post to get an idea.
The dependencies on my pom.xml file are as follows…

<dependencies>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-jdbc</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.quartz-scheduler</groupId>
 <artifactId>quartz</artifactId>
 <version>1.8.0</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-support</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 </dependencies>

We will create the beans.xml file in the resources dir. It looks like this….

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 <bean name="exampleJob">
 <property name="jobClass" value="com.wordpress.codesilo.ExampleJob" />
 </bean>

 <bean id="cronTrigger">
 <property name="jobDetail" ref="exampleJob" />
 <property name="cronExpression" value="* * * * * ?" />
 </bean>

 <bean id="scheduleFactory">
 <property name="triggers">
 <list>
 <ref bean="cronTrigger" />
 </list>
 </property>
 </bean>
</beans>

The ExampleJob class if the class that will run once the trigger fires. It looks like this..

public class ExampleJob extends QuartzJobBean {
 @Override
 protected void executeInternal(JobExecutionContext arg0)
 throws JobExecutionException {
 System.out.println("In the job");
 }
}

Our main class will have this only..

 public static void main(String[] args) throws SchedulerException {
 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 }

If we run main , we will see the following …
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
In the job
In the job
……..

We will initialize log4j by adding the following log4j.xml file in the resources dir.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 <appender name="console">
 <param name="Target" value="System.out"/>
 <layout>
 <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
 </layout>
 </appender>

 <root>
 <priority value ="debug" />
 <appender-ref ref="console" />
 </root>

</log4j:configuration>

Now, we will see all the debug messages along with out System.out message …”In the job”

In order to inject a bean in the job class we change the exampleJob declaration in beans.xml to the following and declare the “injectedBean” …

<bean name="exampleJob">
 <property name="jobClass" value="com.wordpress.codesilo.ExampleJob" />
 <property name="jobDataAsMap">
 <map>
 <entry key="injectedBean" value-ref="injectedBean" />
 </map>
 </property>
 </bean>

 <bean id="injectedBean"/>

We will have a simple method that displays a message in the InjectedBean class

 public void execute(){
 System.out.println("In injected bean execute method");
 }

and call this method from the ExampleJob class.
Now, if we run main we should see the following output (after removing the debug logs)
In the job
In injected bean execute method
In the job
In injected bean execute method

Stateful Job and Concurrency

In order that the job is not fired concurrently we can have two approaches …

a) Make the job stateful.  All we need here is to implement StatefulJob when creating the ExampleJob class. So, the ExampleJob class declaration now looks like this..

 public class ExampleJob extends QuartzJobBean implements StatefulJob {
 ......
 ......
 }

Read more about it here.

b) Use “MethodInvokingJobDetailFactoryBean” and set the concurrent flag to false. Here is a section from the docs

By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with each other. If you specify two triggers for the same JobDetail, it might be possible that before the first job has finished, the second one will start. If JobDetail classes implement the Stateful interface, this won’t happen. The second job will not start before the first one has finished. To make jobs resulting from the MethodInvokingJobDetailFactoryBean non-concurrent, set the concurrent flag to false.

 <bean id="jobDetail">
 <property name="targetObject" ref="exampleBusinessObject" />
 <property name="targetMethod" value="doIt" />
 <property name="concurrent" value="false" />
 </bean>

Basic Spring Code with Maven

May 10, 2010 1 comment

This blog shows how we can use a simple maven project and work with Spring to interact with a database.
First, we create a simple project using the maven command..

mvn archetype:generate

We select the maven-archetype-quickstart project (option 15)
Run the command

mvn eclipse:m2eclipse

to create the .classpath and .project files for eclipse.
We will create a file beans.xml in src/main/resources dir. Not creating the beans.xml file in the resources dir will give you the following exception:
Exception in thread “main” org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [beans.xml] cannot be opened because it does not exist

Here is my beans.xml file.

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 <bean id="dataSource">
 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
 <property name="url" value="jdbc:mysql://localhost:3306/database-name"></property>
 <property name="username" value="root"></property>
 <property name="password" value="root"></property>
 </bean>
 <bean id="template">
 <property name="dataSource" ref="dataSource"></property>
 </bean>
 <bean id="mySQLDao">
 <property name="template" ref="template"></property>
 </bean>
</beans>

Create a main class with the following code:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MySQLDao mySQLDao = (MySQLDao)context.getBean("mySQLDao");
System.out.println(mySQLDao.queryForDate());

In MySQLDao we have the following code:

 private JdbcTemplate template;

 public Date queryForDate(){
 String sql = "select now() from dual;";
 Date currentDate = (Date)template.queryForObject(sql, Date.class);
 return currentDate;
 }

 public void setTemplate(JdbcTemplate template) {
 this.template = template;
 }

In pom.xml add the following dependencies:

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-jdbc</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>2.5.6</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.11</version>
 <scope>compile</scope>
 </dependency>



If the mysql-connector jar is not installed in the local repository , use the following command to install the jar.

mvn install:install-file -DgroupId=mysql -DartifactId=mysql-connector-java -Dversion=5.1.11 -Dfile=mysql-connector-java-5.1.11-bin.jar -DgeneratePom=true -Dpackaging=jar

Running the main class should now give the current timestamp from the database.
To run main from the command line use the following command

mvn exec:java -Dexec.mainClass="com.wordpress.codesilo.Main"

Accessing databases using datasource xml

March 15, 2010 Leave a comment

We will use the previous struts project to setup database access to MySQL running on localhost.
Run the following command to create the .project and .classpath files for Eclipse and import the project in Eclipse

mvn eclipse:m2eclipse

Download the database driver mysql-connector-java-5.1.11-bin.jar from here and save it to the lib folder in this location $JBOSS_HOME/server/web/lib

Create a jboss-web.xml file in the WEB-INF folder with the following content

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
 <resource-ref>
 <res-ref-name>CodesiloDS</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <jndi-name>java:CodesiloDS</jndi-name>
 </resource-ref>
</jboss-web>

In the web.xml file add the following :

 <resource-ref>
 <res-ref-name>CodesiloDS</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
 </resource-ref>

Create a datasource xml file and add it to the deploy dir of JBoss.

Here is the content of my file:

<datasources>
 <local-tx-datasource>
 <jndi-name>CodesiloDS</jndi-name>
 <connection-url>jdbc:mysql://localhost:3306/database-name</connection-url>
 <driver-class>com.mysql.jdbc.Driver</driver-class>
 <user-name>username</user-name>
 <password>password</password>
 <min-pool-size>5</min-pool-size>
 <max-pool-size>20</max-pool-size>
 <!-- Typemapping for JBoss 4.0 -->
 <metadata>
 <type-mapping>mySQL</type-mapping>
 </metadata>
 </local-tx-datasource>
</datasources>

Replace database-name, username and password with appropriate values.

To keep things simple to test, we will add an action in struts-config and have the Action class call the database.

In the action class add this

private final String DATABASE_JNDI_SOURCE = "java:CodesiloDS";

and have this in the execute method. (In the real world most of this code would reside in your model and any helper classes.)

public ActionForward execute(ActionMapping mapping, ActionForm form,
 HttpServletRequest request, HttpServletResponse response)
 throws Exception {

 Connection conn = null;
 Statement stmt = null;
 ResultSet rs = null;
 String date ="";
 try{
 Context ctx = new InitialContext();
 DataSource ds = (DataSource)ctx.lookup(DATABASE_JNDI_SOURCE);
 if(ds!= null){
 conn = ds.getConnection();
 stmt = conn.createStatement();
 rs = stmt.executeQuery("select curdate() from dual;");
 if(rs.next()){
 date = rs.getString(1);
 }
 }
 }
 catch(Exception e){
 ---- code here----
 }
 finally{
 try{
 rs.close();
 stmt.close();
 conn.close();
 }
 catch(Exception e){
 ---- code here -----
 }
 }
 System.out.println("This is a test: " + date);
 return mapping.findForward("success");
 }

Once we call the action, we should see the current date printed on the console.

Maven and Struts 1

February 10, 2010 7 comments

Maven archetype can be used to generate blank projects. However, the mvn archetype:generate command does not give an option to generate an empty struts project with Struts 1. To generate a Struts 1.x project we need to install the struts blank archetype. Use the following commands to download and install struts blank archetype in the local repository.

svn co http://svn.apache.org/repos/asf/struts/maven/trunk/struts-archetype-blank
cd struts-archetype-blank
mvn install

Now to generate a project use the following command

mvn archetype:generate -DarchetypeGroupId=org.apache.struts -DarchetypeArtifactId=struts-archetype-blank -DarchetypeVersion=1.3.5-SNAPSHOT -DgroupId=com.wordpress.codesilo -DpackageName=com.wordpress.codesilo -DartifactId=test-struts

Now we will test this on JBoss AS. Set a variable JBOSS_HOME in bash_profile and change the plugins section generated in the pom.xml file above to the following.

 <plugins>
 <plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>jboss-maven-plugin</artifactId>
 <version>1.4</version>
 <configuration>
 <jbossHome>/${JBOSS_HOME}</jbossHome>
 <serverName>web</serverName>
 <fileName>target/test-struts.war</fileName>
 </configuration>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <configuration>
 <source>1.5</source>
 <target>1.5</target>
 </configuration>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-war-plugin</artifactId>
 <configuration>
 <webResources>
 <webResource>
 <directory>
 ${basedir}/src/main/webapp/WEB-INF</directory>
 <includes>
 <include>web.xml</include>
 </includes>
 <targetPath>WEB-INF</targetPath>
 <filtering>true</filtering>
 </webResource>
 </webResources>
 </configuration>
 </plugin>
 </plugins>

Now we will use the maven JBoss plugin to deploy the war generated above. Use the following command to deploy the war file.

mvn jboss:hard-deploy

(To undeploy use the command mvn jboss:hard-undeploy)

The war will be deployed to the following dir ($JBOSS_HOME/server/web/deploy) (in JBoss 5). If Jboss 4 is used, change the serverName above to “default”.

On starting Jboss we will see an exception ….
java.lang.ClassCastException: org.apache.xerces.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
This can be corrected by removing the jar that is included by the struts-archetype-blank plugin.
Change the following in the pom.xml

 <dependency>
 <groupId>org.apache.struts</groupId>
 <artifactId>struts-core</artifactId>
 <version>1.3.5</version>
 </dependency>

to

 <dependency>
 <groupId>org.apache.struts</groupId>
 <artifactId>struts-core</artifactId>
 <version>1.3.5</version>
 <exclusions>
 <exclusion>
 <groupId>xml-apis</groupId>
 <artifactId>xml-apis</artifactId>
 </exclusion>
 </exclusions>
 </dependency>

The server will now start without any exceptions.

Setting up Ubuntu for development

February 2, 2010 1 comment

I had to reinstall Ubuntu recently and this blog is a summary of setting Ubuntu up for development.

Installing Maven:

sudo apt-get install maven2

In the .bash_profile file in the $HOME directory set the MAVEN_REPO variable and export it. Add this line in the file : export MAVEN_REPO=$HOME/.m2/repository

Installing Sun JDK:

sudo apt-get install sun-java6-bin sun-java6-jre sun-java6-jdk
sudo update-java-alternatives -l
sudo update-java-alternatives -s java-6-sun

In the .bash_profile file again, add these lines —
export JAVA_HOME=/usr/lib/jvm/java-6-sun
export PATH=$PATH:$JAVA_HOME/bin

Update: For installing JDK on Lucid Lynx read this post.

Installing MySql Server:

sudo apt-get install mysql-server

Set the root password when prompted.

Installing Samba:

sudo apt-get install samba smbfs

Installing openssh:

sudo apt-get install openssh-server openssh-client


Installing Ruby and RoR:
This link is a very good summary of doing that in Karmic Koala.

Installing Subversion:

sudo apt-get install subversion

Installing Client for Subversion:
RapidSVN is a very good tool for Ubuntu but recently I tried  RabbitVCS. This is in active development and is very close to TortoiseSVN in Windows.
To install RabbitVCS you need to download the deb package from their website and and install it using the following command (rabbitvcs_0.12.1-2~karmic_all.deb is the downloaded file)

sudo dpkg -i rabbitvcs_0.12.1-2~karmic_all.deb

Installing Eclipse, SpringIDE and Maven Plugin for Eclipse:
Eclipse can be easily installed by using package manager but I ran into some problems with the maven plugin when I used the eclipse that came with Karmic. When I used the Eclipse from their download site ,I did not have the problems.
Get SpringIDE plugin by providing this site in the “install new software” option in Eclipse: http://springide.org/updatesite. The ADJT features were giving problems when installing this plugin so I deselected them.
Get maven plugin from here : http://m2eclipse.sonatype.org/update