Thursday, January 3, 2013

Grails with MongoDB on Appfog - a short guide for dummies



I decided to make a proof-of-concept web app with Grails (v2.1.2) that uses the NoSQL database MongoDB and to top it off, deploy it on Appfog, which is a Cloud Foundry-based service that let's you run applications on a single platform. The nice thing about Cloud Foundry is that you can install it on your own hardware and easily migrate your apps (I believe it's called "moving from a public cloud to a private cloud"). Dilbert has a good comic strip on cloud computing.

First off, register on Appfog. Then create a Grails application (click on the big button Java Grails), then choose a data cloud storage location closest to your target audience (I chose AWS Europe West). Then choose an application name (in the "Enter domain name" field) and click the "create app" button. You can add a custom domain later, if you wish. On the App menu page, click on Services and add a MongoDB service named "mongo".

A quick detour here: I'm used to a GUI when working with databases and I found MongoVUE to be quite useful. MongoVUE can connect to the remote MongoDB on Appfog, which I will show you how to do in just a moment.

Back to the Grails app. To use mongo exclusively (without Hibernate), type in your console

grails install-plugin mongodb

grails uninstall-plugin hibernate


To install the cloud foundry plugin, type

grails install-plugin cloud-foundry

Modify your Grails app accordingly: 


Go to Config.groovy and add the following lines:

grails.plugin.cloudfoundry.username = "your.mail@mailserver.com"
grails.plugin.cloudfoundry.password = "your_password"
grails.plugin.cloudfoundry.target = "http://api.aws.af.cm"


Go to UrlMappings.groovy and add the following mapping:

"/"(controller: "home", action: "index")

Replace all content from DataSource.groovy with:

environments {
    development {
        grails {
            mongo {
                host = "localhost"
                port = 27017
                username = "grails"
                password = "grails"
                databaseName = "helloworld"
            }
        }
    }    
    production {
        grails {
            mongo {
                hostname = "localhost"
                port = 27017
                username = ""
                password = ""
                name = ""
                db = "db"
            }
        }
    }
}


Create a new domain class named (surprise!) Person:

class Person {

    String name
    String action

}

Then create a HomeController and add this action:


def index() {
        def person = Person.findByName('a guest')

        if (!person) {
            person = new Person(name: "a guest", action: 'You invite them.')
            person.save()
        }

        render view: 'index', model: [
                'person': person,
        ]
    }


Create a corresponding view called index.gsp and write:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Hello World</title>
</head>

<body>
<p>
    This is ${person?.name}. What do you do? ${person?.action}
</p>

</body>
</html>


Great, lets create a WAR file. Go to your console and type

grails prod war

Now, to upload you Grails app to Appfog you need  the "af" ruby gem. Follow this Appfog guide to install af. After installing, use the Ruby console (for Windows, the installer adds a "Start Command Prompt with Ruby" icon) and type

af login


Input your Appfog email/password. You should see a "Successfully logged into [https://api.appfog.com]" message if you get it right.
In the Ruby command prompt and go to your grails WAR file output directory. Make sure to delete everything in the directory containing the WAR file except the WAR file itself. Then type

af update name_of_your_appfog_application

Now you should be able to see "This is a guest. What do you do? You invite them." when you type the url of your app (it's in the "Domains" column of the Appfog Apps overview).

It would be nice too see the contents of the remote MongoDB in MongoVUE. To do this, you have to use Appfog's tunneling service. Go to your Ruby command prompt and install Caldecott, if you didn't already with

gem install caldecott

Caldecott is needed for Appfog's tunneling service. After installing caldecott, type

af tunnel mongo

You should receive service connection credentials and an option of which client to start (type 1 for "none"). There should also be a message like "Starting tunnel to mongo on port 10000."

Now create a new connection in MongoVUE. Set server to "localhost" and port to 10000. Input the username/password according to the service connection credentials and set the name of the database to "db" (remember the DataSource.groovy settings?).

And that's it, have fun experimenting.