Skip to content

DigitalInclusion/knowledge-sharing

Repository files navigation

This quickstart will get you going with a Spring MVC Hibernate application that uses a Postgres database service, deployed to Heroku.

{.note} Sample code for the demo application is available on GitHub. Edits and enhancements are welcome. Just fork the repository, make your changes and send us a pull request.

Prerequisites

Create a Java app that uses Spring MVC and Hibernate

If you don't already have a Spring MVC Hibernate app, the easiest way to create one is with Spring Roo. Spring Roo is a RAD tool that lets you quickly build Spring MVC applications with a complete model, view and controller layer, including relational database integration.

Option 1. Clone the sample app

If you don't want to install Spring Roo, you can clone the sample app:

:::term
$ git clone https://github.com/heroku/devcenter-spring-mvc-hibernate.git 
Cloning into petclinic...
remote: Counting objects: 205, done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 205 (delta 93), reused 205 (delta 93)
Receiving objects: 100% (205/205), 98.55 KiB, done.
Resolving deltas: 100% (93/93), done.

This will check out the completed app. To step back to the starting point, do:

:::term
$ git revert starting-point

Now you can skip forward to "Modify Database Configuration".

Option 2. Create the app using Spring Roo

Install Spring Roo if you don't already have it. Then create a directory for your app and generate the app using the clinic.roo script:

:::term
$ mkdir petclinic && cd petclinic
$ roo script --file clinic.roo
    ____  ____  ____  
   / __ \/ __ \/ __ \ 
  / /_/ / / / / / / / 
 / _, _/ /_/ / /_/ /  
/_/ |_|\____/\____/    1.1.4.RELEASE [rev f787ce7]


Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
project --topLevelPackage com.springsource.petclinic
Created ROOT/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
...
Updated SRC_MAIN_RESOURCES/log4j.properties
Script required 41 second(s) to execute

By default, the generated app sets up the Hypersonic in-memory database. However, it is strongly recommended to use the same database locally as in production. So we will switch the application over to using Postgres with this Roo command:

:::term
$ roo persistence setup --provider HIBERNATE --database POSTGRES
...
Updated SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Please update your database details in src/main/resources/META-INF/spring/database.properties.
Updated ROOT/pom.xml [removed dependency org.hsqldb:hsqldb:1.8.0.10; added dependency postgresql:postgresql:8.4-702.jdbc3]
Updated SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
Updated SRC_MAIN_RESOURCES/META-INF/persistence.xml
...

Finally, let's create a git repo and commit this baseline of our application:

:::term
$ git init
$ echo target > .gitignore
$ git add .
$ git commit -m init

Modify database configuration

The web app generated by Spring Roo expects you to set database connection properties in the file src/main/resources/META-INF/spring/database.properties. However, it is not a good idea to hardcode database configuration into a file that is part of your project. Instead, we will edit the Spring configuration to read the configuration from an environment variable.

Heroku automatically provisions a small database when you create a Java application and sets the DATABASE_URL environment variable to a URL of the format

postgres://user:password@hostname:port/dbname

You can also provision a larger database service yourself using the heroku addons command. Either way, the database connection information will be stored in the DATABASE_URL variable.

Create a new URI spring bean initialized with this environment variable by adding this to src/main/resources/META-INF/spring/applicationContext.xml:

:::xml
<bean class="java.net.URI" id="dbUrl">
    <constructor-arg value="${DATABASE_URL}"/>
</bean>

Edit the dataSource section in src/main/resources/META-INF/spring/applicationContext.xml and replace the property place holders with the following:

:::xml
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
    <property name="driverClassName" value="${database.driverClassName}"/>
    <property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + @dbUrl.getPath() }"/>
    <property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/>
    <property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/>
    ...

To run your app locally set the DATABASE_URL variable in your local environment to point to your local postgres database, for example:

:::term
$ export DATABASE_URL=postgres://scott:tiger@localhost/myapp

Add Jetty Runner

Jetty Runner lets you easily execute your web app as a standard Java application (without having to deploy it to a container). It's a simple jar that you can copy down from the central Maven repository to the target directory as part of you build. We'll use the maven-dependency-plugin to do this by adding the following plugin configuration at the end of the plugins section of pom.xml:

:::xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>copy</goal></goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>org.mortbay.jetty</groupId>
                        <artifactId>jetty-runner</artifactId>
                        <version>7.4.5.v20110725</version>
                        <destFileName>jetty-runner.jar</destFileName>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

Declare process types with Procfile

You declare how you want your application executed in Procfile in the project root. Create this file with a single line:

:::term
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

Optionally Choose a JDK

By default, OpenJDK 1.6 is installed with your app. However, you can choose to use a newer JDK by specifying java.runtime.version=1.7 in the system.properties file.

Here's what a system.properties file looks like:

:::term
java.runtime.version=1.7

You can specify 1.6, 1.7, or 1.8 (1.8 is in beta) for Java 6, 7, or 8 (with lambdas), respectively.

Run your app locally

Let's run the app locally first to test that it all works. You must have a Postgres database up and running and accessible on the DATABASE_URL you specified above.

Build your app

:::term
$ mvn package
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building petclinic 0.1.0.BUILD-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
...
[INFO] --- maven-dependency-plugin:2.3:copy (default) @ petclinic ---
[INFO] Configured Artifact: org.mortbay.jetty:jetty-runner:7.4.5.v20110725:jar
[INFO] Copying jetty-runner-7.4.5.v20110725.jar to /Users/jjoergensen/dev/tmp/spring-roo-petclinic/target/dependency/jetty-runner.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.466s
[INFO] Finished at: Mon Aug 29 20:56:03 PDT 2011
[INFO] Final Memory: 9M/81M
[INFO] ------------------------------------------------------------------------

Start your app

Note: you can also start your app using foreman to execute the Procfile. [Read more about foreman and procfiles](http://devcenter.heroku.com/articles/procfile).
:::term
$ java -jar target/dependency/jetty-runner.jar target/*.war

Test it

Go to http://localhost:8080 and test it out by creating a new record.

Deploy to Heroku

Commit your changes to Git:

:::term
$ git add .
$ git commit -m "Ready to deploy"

Create the app:

:::term
$ heroku create
Creating high-lightning-129... done, stack is cedar
http://high-lightning-129.herokuapp.com/ | [email protected]:high-lightning-129.git
Git remote heroku added

Deploy your code:

:::term
$ git push heroku master
Counting objects: 227, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (117/117), done.
Writing objects: 100% (227/227), 101.06 KiB, done.
Total 227 (delta 99), reused 220 (delta 98)

-----> Heroku receiving push
-----> Java app detected
-----> Installing Maven 3.0.3..... done
-----> Installing settings.xml..... done
-----> executing .maven/bin/mvn -B -Duser.home=/tmp/build_1jems2so86ck4 -s .m2/settings.xml -DskipTests=true clean install
       [INFO] Scanning for projects...
       [INFO]                                                                         
       [INFO] ------------------------------------------------------------------------
       [INFO] Building petclinic 0.1.0.BUILD-SNAPSHOT
       [INFO] ------------------------------------------------------------------------
       ...
       [INFO] ------------------------------------------------------------------------
       [INFO] BUILD SUCCESS
       [INFO] ------------------------------------------------------------------------
       [INFO] Total time: 36.612s
       [INFO] Finished at: Tue Aug 30 04:03:02 UTC 2011
       [INFO] Final Memory: 19M/287M
       [INFO] ------------------------------------------------------------------------
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 62.7MB
-----> Launching... done, v5
       http://pure-window-800.herokuapp.com deployed to Heroku

Congratulations! Your web app should now be up and running on Heroku. Open it in your browser with:

:::term  
$ heroku open