Hibernate Spatial extension together with Spring running on a Tomcat
I have done a lot of projects based on Hibernate (JPA2), Spring, Tomcat (Jetty for test) and Maven (http://www.wiegand.dk/wordpress/?p=51 [1]). The basic setup is not easy – but once done correct – it can be reused in most projects afterwards.
Some years ago my company (http://northtech.dk/ [2]) moved its main focus from general software architecture to the GEO sector. Because of that we are adding the GEO perspective to all our utilities and frameworks. This article is about how to add GEO awareness to our core JAVA paradigm (http://www.wiegand.dk/wordpress/?p=51 [1]).
The general way of handling geometries in JAVA is by JTS (http://en.wikipedia.org/wiki/JTS_Topology_Suite [3]). JTS is the core in most open spatial software (http://www.osgeo.org [4]).
We (NorthTech) mostly use the PostgreSQL (http://www.postgresql.org [5]) database with the spatial extension – PostGIS (http://postgis.net [6]), but we have also use Oracle and Microsoft SQL to handle geometries. This article has focus on using PostGIS, but one of the perks by using Hibernate Spatial is that most of your code is database independent.
The setup is in three parts.
- The first part is how to setup Maven to handle database drivers and JTA.
- The second part is to setup Spring/JPA2/Hibernate
- The third part is how to configure the data source in Tomcat
1: Setup Maven
The first thing that needs to be done is to include Hibernate spatial in your project. In Maven it is pretty easy.
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-spatial</artifactId> <version>${hibernate.spatial.version}</version> </dependency>
Note: Currently ${hibernate.spatial.version} is [4.3].
I use the following repositories.
<repositories> <repository> <id>OSGEO GeoTools repo</id> <url>http://download.osgeo.org/webdav/geotools</url> </repository> <repository> <id>Hibernate Spatial repo</id> <url>http://www.hibernatespatial.org/repository</url> </repository> </repositories>
But… because of a class-loading problem in the combination of PostGIS, Hibenate Spatial and Tomcat data source the PostGIS driver must NOT be included in the WAR file – as well as the PostgreSQL driver and JST.
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-spatial</artifactId> <version>${hibernate.spatial.version}</version> <exclusions> <exclusion> <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> </exclusion> <exclusion> <groupId>com.vividsolutions</groupId> <artifactId>jts</artifactId> </exclusion> <exclusion> <groupId>org.postgis</groupId> <artifactId>postgis-jdbc</artifactId> </exclusion> </exclusions> </dependency>
The project still needs the three dependencies but the scope must be set to [provided]. In some cases the scope can be set to [test] but in my case would I like to execute Jetty through Maven.
Note: Currently ${jts.version} = 1.13, ${postgis.version} = 1.5.2, ${postgresql.version} = 9.1-901.jdbc4
<dependency> <groupId>org.postgis</groupId> <artifactId>postgis-jdbc</artifactId> <version>${postgis.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts</artifactId> <version>${jts.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> <version>${postgresql.version}</version> <scope>provided</scope> </dependency>
Now a correct WAR file can be build but I would like to use Jetty as a test server through Maven as well. I use the Jetty Maven plug-in (http://eclipse.org/jetty/documentation/current/jetty-maven-plugin.html [7]) for this. When the Jetty Maven plug-in has been setup correct you can run your application by executing [mvn jetty:run].
The three dependencies you removed from the WAR files need to be reintroduces to the Jetty plug-in. Maven plug-ins has another scope for dependencies so you need to add the Hibernate spatial repository to plug-in repositories as well.
<pluginRepositories> <pluginRepository> <id>Hibernate Spatial repo</id> <url>http://www.hibernatespatial.org/repository</url> </pluginRepository> </pluginRepositories>
Now you can configure the Jetty plugin to include the dependencies.
<plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.10</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <stopKey>foo</stopKey> <stopPort>8085</stopPort> <contextPath>/trackimporter</contextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>8080</port> <maxIdleTime>60000</maxIdleTime> </connector> </connectors> </configuration> <dependencies> <dependency> <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> <version>${postgresql.version}</version> </dependency> <dependency> <groupId>org.postgis</groupId> <artifactId>postgis-jdbc</artifactId> <version>${postgis.version}</version> </dependency> <dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts</artifactId> <version>${jts.version}</version> </dependency> </dependencies> </plugin>
This is it for the Maven setup. It is now possible to create a correct WAR file and run your application on Jetty as well.
2: Setup Spring
Setting up Spring to use Hibernate Spatial is pretty easy. You only need to add the correct dialect to the JPA properties.
<prop key="hibernate.dialect">org.hibernate.spatial.dialect.postgis.PostgisDialect</prop>
Now the core spatial paradigm has been setup and you can add JTS geometry to your entities. You have to specify how to handle the JTS geometry in an entity by adding the Hibernate type annotation.
@Column(name = "GEOM") @Type(type = "org.hibernate.spatial.GeometryType") private Geometry geometry;
You should now be able to test it locally in Jetty.
3: Configure Tomcat data source
In Tomcat you need to add the three dependencies you removed – JTS, PostgreSQL driver and PostGIS driver – to the Tomcats lib folder. In the setup above the three JARs are called:
- jts-1.13.jar
- postgis-jdbc-1.5.2.jar
- postgresql-9.3-1102-jdbc41.jar
Then you can setup the data source in Tomcats configuration context [conf/context.xml].
<Resource auth="Container" maxActive="100" maxIdle="10" name="MY_DS" username="login" password="password" poolPreparedStatements="true" type="javax.sql.DataSource" driverClassName="org.postgis.DriverWrapper" validatingQuery="select 1" url="jdbc:postgresql_postGIS://localhost:5432/mydb"/>
That’s it! Install you WAR file and enjoy 🙂
Best Regards
Rolf Wiegand Storgaard