Source code is available here. This article is part of a series, the commit in the repository for this article is: 03a9e1c

Introduction

This will be a rather short article because it is merely a combination of the previous post and Yong Mook Kim's excellent Hibernate + Spring Tutorial.

I don't wish to steal his thunder, so I'll direct you to read his tutorial rather than regurgitate the details here.

Prerequisites

  1. PostgreSQL

PostgreSQL is a leading open source database system. Although not strictly necessary to have locally installed, a local installation for debugging and development will speed things up quite a bit.

Setup

PostgreSQL

Installation of PostgreSQL varies from system to system, search online for how to install postgresql from your package manager or install it manually from the postgresql website. Heroku only works with the three most recent versions of postgres in the wild at all times. In addition to installing the service, be sure to provision yourself a normal (non administrative) user. This requires updating your app every three years, but if you are using persistence layers like Hibernate correctly this shouldn't be too much trouble.

If you wish to allow local connections to the database you will need to add entries to /var/lib/pgsql/data/pg_hba.conf for your particular user.

Example:


local    alex       alex                                       md5
host    alex       alex       127.0.0.1/32          md5
host    alex       alex       127.0.0.1/32          md5

Heroku PostgreSQL Addon

Most all web applications make use of databases. Heroku provides different addons for interacting with a variety of database vendors. This example will make use of PostgreSQL 9.2

To install the addon perform the following in your project root folder:


$ heroku login #you will be prompted for your Heroku account credentials
$ heroku addons:add heroku-postgresql:dev
$ heroku pg:promote HEROKU_POSTGRESQL_<COLOR>_URL

When creating a new database, Heroku assigns a random unique "color" to it, so replace <COLOR> with whatever your color happens to be. Only one database may be designated as the main database pointed to by DATABASE_URL in the configuration. The heroku pg:promote command will promote a "color" url to the main db url.

To remove the addon or inspect current configuration use "heroku addons:remove heroku-postgresql:dev" and "heroku config" respectively. For more details see their postgresql addon documentation.

Environment

Set DATABASE_URL to point to your local postgres server (postgresql runs on port 5432 by default) Use the "heroku config" command to see the url template for heroku's database as an example. Remember that the url contains protocol, username, password, path, and query parameters (for additional options).

If you do not wish to connect to a local database (or dont even have it installed) you may connect directly to heroku's databases remotely. My experience with this is pretty slow - your mileage may vary. Also, if you wish to connect remotely you will need to modify our webappContext.xml from:


<property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() }"/>

To use ssl:


<property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() }?ssl=true&amp;sslfactory=org.postgresql.ssl.NonValidatingFactory"/>

Note: There is probably a cleaner way to do this conditionally so that we don't have to modify the spring config each time we wish to swap out databases.

Running the Code

I have adapted mkyong's simple Stock example to have two entry points to a web service:


POST /spring/stock?code={code}&name={name}
GET /spring/stock/{code}

When performing a GET request, if the stock does not yet exist it returns "No Stock Available" otherwise it returns back the stock code and name for the given stock code.

Adaptations

In my repository there have been a few changes:

In SpringMVC, web applications have a central application context to manage resources shared amongst child dispatcher contexts. This is useful for expensive and limited resources such as database connections. This will become even more useful in my next post when we visit Spring Security and Jetty Session IDs.

Thoughts

Be extra careful with component scanning in spring and only scan packages that need it. Not only does it eat up extra memory, but in the worst case, the transaction manager for spring/hibernate can bind to the wrong beans and throw exceptions instead of properly servicing our requests.

One annoyance I have with spring-orm by itself is all the damned boilerplate interfaces. Spring-data should clean this up nicely for us. I've messed around a bit with spring-data and neo4j in the past, but am still learning the basics of Hibernate. There is a deluge of information on all of these technologies. In isolation, each one is easy enough to understand, but it is easy to lapse on the details when orchestrating them all at once (Part of why I made this blog!). Future posts will contain details about these other technologies as I advance upon them.