[Note: The Information in the following post is out of date. Please use the Grails Heroku plugin instead ( edited Dec 19, 2011 )]
Heroku recently announced Java support. In this post, I will show you how to deploy Grails applications into Heroku using the Maven support available to Grails.
Heroku recommends building a jar file and executing this against an embedded Jetty instance. This solution simply does a simple grails run-app and is inspired by the Play! framework support in Heroku. ( BTW, why Roo & Play! and not Grails? )
Updated Sept. 02 – using jetty runner in the example.
1. Install the Heroku package bundles in your local machine.
Follow the instructions here: http://devcenter.heroku.com/articles/java#local_workstation_setup
2. Get your credentials by signing up for an account at http://www.heroku.com
3. Associate your credentials via ‘heroku login’ in a terminal window.
deathstar:grails-heroku-sample tomaslin$ heroku login Enter your Heroku credentials. Email: email@example.com Password: Found existing public key: /Users/tomaslin/.ssh/id_rsa.pub Would you like to associate it with your Heroku account? [Yn] y Uploading ssh public key /Users/tomaslin/.ssh/id_rsa.pub
4. Install Foreman
gem install foreman
5. Install Maven if you don’t have it.
Follow the instructions at http://maven.apache.org/download.html
You might also want to set a MAVEN_OPTS environment variable to handle the amount of memory grails uses to build -
export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=192m"
6. Install Grails if you don’t have it
Follow the instructions at http://www.grails.org/Installation
Building a Heroku grails project
1. Create your grails project
In a console, type
grails create-app grails-on-heroku
2. Convert this into a Maven project
We convert the grails project into a Maven project because this is usually less of a pain. Refer to section 4.5 of the grails user guide if you want to have other workflows.
In terminal, type:
mvn org.grails:grails-maven-plugin:1.3.7:create-pom -DgroupId=com.tomaslin
where groupId is the package name for your company.
Maven will proceed to download the entire Internet ( or so it seems ). But at the end of this process, you should have a sexy sexy Pom.xml file.
3. Define a Procfile
Create a file on the root of the application named Procfile.
Add the following into it:
web: mvn -Dserver.port=$PORT grails:run-app
Add the following into it:
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war
4. Uncomment mavenCentral() and mavenLocal()
You probably also want to uncomment the mavenCentral() and mavenLocal() repos from grails-app/conf/BuildConfig.groovy
5. Add reference to jetty-runner in your pom.xml file.
Add this to your pom.xml’s build section ( see Graeme’s comment on this post for a link )
<plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <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>
Deploying your sexy beast
In a console, type
git init git add . git commit -a -m init heroku create --stack cedar git push heroku master
If you type heroku open, you won’t see anything since your application is deployed against /grails-on-heroku. You can change the context path if you would like to see it in root.
You can use the command heroku logs to see the deployment process.
You end up with a deployed application like this:
- The hibernate plugin seems to crash and burn in maven. The temporary solution was to uninstall the plugin. This might have to do with the inclusion of the pom file of a stale jBoss repo. Or it could be completely unrelated.
- Heroku seems to do a mvn:install on every deployment. Might be easy to remove this.
- In my digging, came across these posts that might be helpful:
- Executable Wars – http://eclipsesource.com/blogs/2009/10/02/executable-wars-with-jetty/
- HerokuJetty – https://github.com/fabiokung/lein-herokujetty
- Compared to CloudFoundry ( which still doesn’t have a price sticker ), Heroku is very nice. Having their servers build the war files definitively feels faster and more productive.
- Originally started trying to do a grails run-war, but it seems that server.port is not passed in correctly to this.
- This is not production ready, you should never run production with grails run-app.
- Heroku doesn’t seem to accept polyglot projects. If it detects that something is a clojure project, it will ignore the Java POM. This whole fiasco would have been easier if we could have used herokujetty and mvn:pom.