Sunday, September 23, 2007

Qwicket, maven and eclipse

I want to start using JPA with Wicket, and the quickest way was to start with Qwicket, a project that already has done the heavy lifting. I also wanted to get a bit more experience with maven, which is touted as a successor to ant. Furthermore, I wanted to be able to build and run my maven-managed application from eclipse. And lastly, I wanted to use MySQL. Qwicket does come with maven support, but it's managed from an ant script. I wanted native maven support.

Here's what I did to change qwicket so it fits my requirements:

  • This assumes MySQL is installed and running.
  • Create a schema called qwicket in the MySQL catalog. You can just leave it empty.
  • Install maven 2 for the command line (http://maven.apache.org/download.html)
  • Install the eclipse maven 2 plugin (http://m2eclipse.codehaus.org)
  • Start a DOS shell (this will work for other shells too)
  • I'm using C:\eclipseproj as my eclipse project directory, but it could be anything:
C:\eclipseproj>mvn archetype:create -DgroupId=qwicket -DartifactId=qwicket
-DarchetypeArtifactId=maven-archetype-webapp
  • Note the last argument. It creates an appropriate directory structure for a web application.
C:\eclipseproj>cd qwicket
C:\eclipseproj>mvn eclipse:eclipse
  • In eclipse, import the project into your workspace:
File --> Import --> Import Existing Projects into Workspace
  • Edit pom.xml as follows:

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>qwicket</groupId>
<artifactId>qwicket</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>qwicket Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<wicket.version>1.2.6</wicket.version>
<jetty.version>6.1.4</jetty.version>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- WICKET DEPENDENCIES -->

<dependency>
<groupId>wicket</groupId>
<artifactId>wicket</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>wicket</groupId>
<artifactId>wicket-extensions</artifactId>
<version>${wicket.version}</version>
</dependency>

<!-- LOGGING DEPENDENCIES -->

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.0.1</version>
</dependency>

<!-- JETTY DEPENDENCIES FOR TESTING -->

<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-management</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>

<!-- SPRING and HIBERNATE -->

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.0.ga</version>
</dependency>
<dependency>
<groupId>wicket</groupId>
<artifactId>wicket-spring-annot</artifactId>
<version>1.2.6</version>
</dependency>

<!-- EMAIL -->

<dependency>
<groupId>commons-email</groupId>
<artifactId>commons-email</artifactId>
<version>1.0</version>
</dependency>

<!-- MYSQL -->

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>3.1.14</version>
</dependency>

</dependencies>
<build>
<finalName>qwicket</finalName>
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
</resource>
<resource>
<filtering>false</filtering>
<directory>src/main/java</directory>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Now we are ready to work with qwicket.
  • Unpack qwicket.zip to qwickettmp

  • In the Windows file explorer:

  • Delete qwicket\src\main\java

  • Copy qwickettmp\src\java to qwicket\src\main

  • Delete qwicket\src\main\webapp

  • Copy qwickettmp\src\web to qwicket\src\main, rename to webapp

  • Right click on the project in eclipse, add the java folder to the source path

  • Copy qwicket\src\main\webapp\WEB-INF\classes\log4j.properties to src\main\resources (I'm not sure why log4j doesn't pick it up from the original location)

  • Note that webapp\classes\application.properties is not used in my implementation.

  • Open qwicket.myapp.util.Start.java

  • Change the lines
     ptabs.setContextPath("/");
ptabs.setWar("build/war");
  • to
     ptabs.setContextPath("/qwicket");
ptabs.setWar("target/qwicket.war");
  • Edit applicationContext.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/qwicket</value>
</property>
<property name="username"><value>your username here</value></property>
<property name="password"><value>your password here</value></property>
</bean>

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="qwicket.myapp.QwicketSessionFactory" abstract="false" singleton="true" lazy-init="default" autowire="default" dependency-check="default">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="annotatedClasses">
<list>
<value>qwicket.myapp.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<!-- Services -->
<bean id="userService"
class="qwicket.myapp.service.impl.UserServiceImpl">
<property name="userDao" ref="userDAO" />
</bean>

<!-- End Services -->

<!-- DAOs -->
<bean id="userDAO" class="qwicket.myapp.dao.impl.UserDaoImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- End DAOs -->

<!-- Application -->
<bean id="QwicketApplication"
class="qwicket.myapp.QwicketApplication" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/qwicket</value>
</property>
<property name="username"><value>root</value></property>
<property name="password"><value>admin</value></property>
</bean>

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="qwicket.myapp.QwicketSessionFactory" abstract="false" singleton="true" lazy-init="default" autowire="default" dependency-check="default">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="annotatedClasses">
<list>
<value>qwicket.myapp.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<!-- Services -->
<bean id="userService"
class="qwicket.myapp.service.impl.UserServiceImpl">
<property name="userDao" ref="userDAO" />
</bean>

<!-- End Services -->

<!-- DAOs -->
<bean id="userDAO" class="qwicket.myapp.dao.impl.UserDaoImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- End DAOs -->

<!-- Application -->
<bean id="QwicketApplication"
class="qwicket.myapp.QwicketApplication" />
</beans>
Now to set up eclipse to build the application:
  • Open the External Tools Dialog from the toolbar

  • Select "m2 build" in tree

  • Click the New icon

  • For Name type "qwicket war"

  • For Base directory click Browse Workspace, select qwicket

  • For Goals type "clean compile war:war" (an alternative is "clean package")

  • Click Apply, then Run

To run the application:
  • Open the Run Dialog from the toolbar

  • Click Java Application in the tree

  • Click the New icon

  • For Project: Browse, then select qwicket

  • For the Main class: Browse, then select qwicket.myapp.util.Start

  • Click Apply, then Run

  • Note: you can also run the app using maven: "mvn jetty:run". If you choose to do this, there's no longer a need for Start.java. Also, maven will automatically build and package your war if necessary.

1 comment:

John-Crichton said...

Hi,

"qwicket.myapp.QwicketSessionFactory"
from you applicationConfig.xml
does not exist in the qwicket project?