Tapestry 5 on top of GORM with Maven
With Grails 1.1 (RC2 at the time of this writing) the Grails team made it much more easy to use GORM, the Grails Object Relational Mapper outside of Grails itself. Starting from a discussion on the grails-user mailinglist, which cumulated in this blogentry I wanted to make Tapestry 5 run on top of it and succeeded.
The most important thing to note is that you have to write your page classes in groovy if you want to use the dynamic finders etc. of Gorm. If you want to use Gorm capabilities from java you need to write a groovy wrapper aka dao.
You find a zipfile with working sources (as of Apr. 1st 2009) for Download here.
1. Setting up Tapestry
For the sake of simplicity I start out from the Tapestry archetype which you can generate with
mvn archetype:generate -DarchetypeCatalog=http://tapestry.formos.com/maven-repository
and I assume you have basic knowledge about using maven and Tapestry. I use the latest snapshot (at the time of this writing 5.1.0.1-SNAPSHOT).
Since GORM configuration depends on Spring you need to setup Tapestry to work with spring. In the pom.xml add the following dependency:
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-spring</artifactId>
<version>${tapestry-release-version}</version>
</dependency>Change the <tapestry-release-version> property to the one you want to use.,
In web.xml add the following:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/appContext-main.xml</param-value> </context-param>
I store my Spring configuration in /WEB-INF/classes normally, but you can choose whatever directory you prefer. Just change the path accordingly.
And also in web.xml change the <filter> entry of Tapestry to
<filter> <filter-name>app</filter-name> <filter-class>org.apache.tapestry5.spring.TapestrySpringFilter</filter-class> </filter>
You can find more information about setting up Tapestry's spring integration here for the latest snapshot and here for the latest release version. Since Spring integration changed quite a bit with Tapestry 5.1. I would suggest using 5.1.
2. Setting up Spring configuration
If you sticked to the example above just create the file appContext-main.xml in the directory WEB-INF/classes and paste the following content. Please note that you have to substitute <yourpackage> with the package you chose while generating the maven archetype.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:gorm="http://grails.org/schema/gorm" xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://grails.org/schema/gorm http://grails.org/schema/gorm/gorm.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="jdbc:hsqldb:mem:tapestryDB"/> <property name="password" value=""/> <property name="username" value="sa"/> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> </bean> <!-- - Message source for this context, loaded from localized "messages_xx" files. --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages"/> </bean> <gorm:sessionFactory base-package="<yourpackage>" data-source-ref="dataSource" message-source-ref="messageSource"> <property name="hibernateProperties"> <util:map> <entry key="hibernate.hbm2ddl.auto" value="update"/> </util:map> </property> </gorm:sessionFactory> <!-- Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @Resource. --> <context:annotation-config/> <!-- Instruct Spring to perform declarative transaction management automatically on annotated classes. --> <tx:annotation-driven/> </beans>
3. Setting up Gorm
In the pom.xml we need some more dependencies. Spring of course, but also the hsql database which is referenced in the appContext-main.xml and the groovy dependencies.
<dependencies>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-core</artifactId>
<version>${tapestry-release-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-spring</artifactId>
<version>${tapestry-release-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-test</artifactId>
<version>${tapestry-release-version}</version>
<scope>test</scope>
</dependency>
<!-- Gorm dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.0.1B_spec</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.grails</groupId>
<artifactId>grails-bootstrap</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.grails</groupId>
<artifactId>grails-gorm</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.grails</groupId>
<artifactId>grails-web</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.7</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.8.0.GA</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.8</version>
<classifier>jdk15</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
<!-- Just to be sure -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
Furthermore we need the following repository and plugin repository if they are not already present:
<repositories>
[...]
<repository>
<id>codehaus-snapshots</id>
<url>http://snapshots.repository.codehaus.org</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
[...]
<pluginRepository>
<id>codehaus-plugin-snapshots</id>
<url>http://snapshots.repository.codehaus.org</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
And now the last and most important configuration: the GMaven plugin By default if compiles all Groovy sources under /src/main/groovy, but since I want to keep all my sources under /src/main/java I added the configuration section to the plugin.
<plugins>
[...]
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0-rc-5-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy.maven.runtime</groupId>
<artifactId>gmaven-runtime-1.6</artifactId>
<version>1.0-rc-5-SNAPSHOT</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<fileset>
<directory>${pom.basedir}/src/main/java</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</fileset>
</sources>
</configuration>
</plugin>
</plugins>
Now for testing purposes you can just create the following classes:
in src/main/java/<yourpackage>/entities the file TestBean.groovy. Note that the @Entity annotation is NOT the one from the JPA but the one from grails.persistence package!
import grails.persistence.Entity
@Entity
public class TestBean
{
String name
String text
}
in src/main/java/<yourpackage>/pages the file TestPage.groovy:
import <yourpackage>.entities.TestBean
import org.apache.tapestry5.annotations.Property
import org.apache.tapestry5.ioc.annotations.Inject
import org.slf4j.Logger
public class TestPage
{
@Inject
private Logger log
@Property
private List<TestBean> testBeans
Object setupRender()
{
testBeans = TestBean.list()
if (testBeans == null || testBeans.size() == 0)
{
new TestBean(name: "Test1", text: "Text 1").save()
testBeans = TestBean.list()
}
return null
}
}
And lastly the page template TestPage.tml in the WEB-INF directory:
<html t:type="layout" title="TGorm TestPage" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xmlns:p="tapestry:parameter"> <h1>Gorm Test</h1> <t:grid t:id="testBeanGrid" source="testBeans"/> </html>
If you start the application now with mvn jetty:run and browse to http://localhost:8080/<yourcontext>/TestPage you should see the grid with one entry.
Have fun!
You find a zipfile with working sources (as of Apr. 1st 2009) for Download here.
- Admin's blog
- Login or register to post comments
- German











