[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.
Prerequisites
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: tomaslin@gmail.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:
http://hollow-spring-928.herokuapp.com/grails-on-heroku/
Observations
- 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.
“This is not production ready, you should never run production with grails run-app.”
Why is that? What do we miss to make it production-ready?
Run app has a reloading agent, which might affect performance. You probably want run-war.
Is run-war recommended for production?
See here for a Grails 2.0 example that uses the Jetty container approach recommended via Heroku https://github.com/grails-samples/hello-heroku/
With this example, it seems to be a ‘hard’ way, doesn’t it?
Correctly if I am wrong. The pom.xml in the example is manually written?
If so, I am wondering how can I obtain a complete pom.xml out-of-the-box before deploying to Heroku.
No, we modify the POM.xml generated by the maven plugin – see step 2.
This is awesome! Thanks for posting this. Feel free to email me if you have any problems or questions. jw at heroku dot com
Pingback: Pedro Newsletter 01.09.2011 « Pragmatic Programmer Issues – pietrowski.info
In the pom created by the grails-maven-plugin, I had to change the scope of slf4j from runtime to compile to get my app to start on Heroku. Otherwise, I got:
java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
I tried that but is still failing i changed the pom slfj4 to compile, can you provide more tips around that, maybe your pom.xml (i would love to have a clean one, cause it downloads the internet)
I ran through this using Groovy 1.8.2 and Grails 1.3.7. It worked flawlessly except that I had to add some dependencies to BuildConfig.groovy:
runtime ‘antlr:antlr:2.7.6’
runtime ‘commons-collections:commons-collections:3.1’
runtime ‘org.slf4j:slf4j-api:1.5.2’
The only other thing I noticed was that the application was deployed to the root, rather than to a URI matching the name of the project. Nice one!
Pingback: Android, Grails and Heroku « Surfsoft Consulting Blog
Hi! I’m really enthusiastic on your tutorial, and I think it’s very useful.
I tried it by myself, but I get just this in the log:
2011-10-05T23:54:46+00:00 heroku[router]: Error H14 (No web processes running) -> GET sharp-leaf-7769.herokuapp.com/ dyno= queue= wait= service= status=503 bytes=
Do you have any clue for me? Thanks in advance!!
Make sure you have a Procfile that defines how to start the web process. And then try to start up a web dyno:
heroku scale web=1
Then check to see if it is running:
heroku ps
Thanks a lot! I tried it and it worked nicely.
I didn’t know I had to use herkou scale, now I do 🙂
Thanks again!
You shouldn’t usually have to. But there are situations where Heroku won’t automatically create a default web dyno for you. I’ve seen this when I didn’t have a Procfile on my first git push.
I followed the tutorial step-by-step but I’m getting the following output in heroku logs:
2011-10-31T11:49:34+00:00 heroku[web.1]: Starting process with command `java -Xmx384m -Xss512k -XX:+UseCompressedOops -jar target/dependency/jetty-runner.jar –port 18081 target/`
2011-10-31T11:49:35+00:00 app[web.1]: Unable to access jarfile target/dependency/jetty-runner.jar
2011-10-31T11:49:35+00:00 heroku[web.1]: Process exited
2011-10-31T11:49:36+00:00 heroku[web.1]: State changed from starting to crashed
2011-10-31T11:49:36+00:00 heroku[web.1]: State changed from crashed to created
It seems that it can’t find the jetty-runner.jar file. Yet I added the plugin sections in my POM.
My mistake: I had forgotten to commit the changes to my pom.xml. But now that it’s done I get this when I run ‘heroku open’: http://stormy-light-1933.heroku.com/
And if I append ‘grails-on-heroku’ at the end: http://stormy-light-1933.heroku.com/grails-on-heroku (error 404).
Any idea of what I did wrong?
Pingback: Android, Grails and Heroku » Surfsoft Labs
is this hosting free of cost??
Yes for the first running instance. Details are on heroku website