Monday, 30 March 2009

Being Groovy

Nothing spectacular here, but it's interesting to see just how nice and simple Groovy can be. I have a page in my app where the user can tick a checkbox for each of their networks to say which networks should receive a status update. The request looks something like this:
newStatus=hello%20world!&network1=on&network2=on&network3=on

Grails supplies this as a map called params, but what I really want is a simple list of network ID's. Here's how I do it:
def networkIds = params.findAll({ key, val ->
key.startsWith("network")
}).collect({ key, val ->
Integer.parseInt(key[7..-1])
})

Basically, I'm chaining two calls together - findAll + collect - that both accept a closure. I'm using findAll to filter out any entries that don't start with 'network' and then collect to convert the resulting map into a list of ints. And not an iterator in sight!

Tuesday, 24 March 2009

Why Grails Is Good

Obviously I can't say that Grails is the best thing since sliced bread and then not present some evidence to support my claim, so here's a specific example.

In my application I have a Network domain class and some other domain classes that extend it - TwitterNetwork, FacebookNetwork, etc. I wanted to handle the CRUD functionality for these classes in a single controller, but keep the forms separate. Having auto-generated the controller + views and then deleted the stuff I didn't want, here's the structure I ended up with:
- grails-app
- domain
- Network.groovy
- FacebookNetwork.groovy
- TwitterNetwork.groovy
- controllers
- NetworkController.groovy
- views
- network
- list.gsp
- facebookNetwork
- create.gsp
- edit.gsp
- twitterNetwork
- create.gsp
- edit.gsp
Out of the box, the default list action just works:
def list = {
if (!params.max) params.max = 10
[ networkInstanceList: Network.list(params) ]
}

As do the delete, save and update actions.

All I have to do now is get the edit and create actions to use the correct view, depending on the network type. To do this I use the class name to determine which view to use. For example, here's my edit action:
def edit = {
def networkInstance = Network.get(params.id)
renderEditForm(networkInstance)
}

def renderEditForm(network) {
def map = [ networkInstance : network ]
def viewPath = getViewPath(network)
render(view:"/${viewPath}/edit", model:map)
}

// derive the view path from the given network instance
def getViewPath(network) {
def networkName = getName(network)
networkName[0].toLowerCase() + networkName[1..-1]
}

The great thing is, I know that will work because by convention Grails will put the views for TwitterNetwork in the twitterNetwork folder and the views for FacebookNetwork in the facebookNetwork folder. It then becomes a simple case of taking the class name and making the first character lower case.

I use the same principle for my create action:
static networks = [ "twitter" : TwitterNetwork,
"facebook" : FacebookNetwork ]

def create = {
def networkInstance = createNetwork(params.type)
networkInstance.properties = params
renderCreateForm(networkInstance, params.type)
}

// create a new network instance of the given type
def createNetwork(networkType) {
if (networkType in networks.keySet()) {
def clazz = networks[networkType]
return clazz.newInstance()
}
}

... etc

And that's it! Full CRUD functionality for a set of polymorphic domain classes in a few lines of code - most of which were auto-generated by the framework. :-)

Wednesday, 11 March 2009

Is Grails The Answer?

I certainly think so. Over the last few years, I've used a variety of Java web frameworks such as Struts, Spring MVC + Tapestry and various combinations of Spring, Hibernate, JPA + EJB. Before all those things came along, I even tried my hand at JSP's, vanilla servlets + JDBC. I got some decent results out of most of those frameworks, but at the same time, it was hard work and productivity wasn't very high on the agenda. However, once things like Rails + Django appeared on the scene, I started to wonder if I should be using Java in the first place? These new frameworks made use of more dynamic languages - Ruby and Python - and promised short development cycles and extremely high productivity.

But, having spent the best part of ten years becoming a Java expert, moving to an entirely new platform seemed like a very big jump - particularly in the case of Ruby/Rails. After all, the JVM is (in my opinion) one of Java's biggest strengths - if only there was an easier way to tap that potential. Enter Groovy + Grails! I'd been following Groovy pretty closely for a while and really liked the look of it, eg. its extensive use of closures. I was also aware of Grails, but the name put me off slightly - it just seemed to be shouting "me too!" a little too loudly for my liking. But following my disappointment with Google App Engine, I decided it was finally time to take the plunge.

I needn't have worried. Quite simply, Groovy + Grails is the best web framework I have ever used in any language. After just one day (which included frequently referring to the documentation) I had full CRUD functionality for a set of polymorphic domain classes. Following that, adding an Authentication Filter was a breeze, creating a Custom Tag Library was incredibly easy and even Ajax Integration (so often where complexity starts to creep in) wasn't too unpleasant. And here's the best part ... all these features build on my existing knowledge of Servlets, Spring, Hibernate, etc, so I'm not learning a whole new technology stack from scratch.

After three days I had an application that was every bit as functional as its Google App Engine equivalent, which took a similar amount of time. I'll admit that I haven't strayed too far from the golden path, but so far, all the signs are extremely encouraging. There's plenty of support out there and the user community is extremely active. I've also read reports of companies using Grails for real-world sites, which is more than some of the latest frameworks can boast. I'll keep you posted ...

RSS Feeds - A Confession

Shocking I know, but I have never really made use of RSS feeds. I gave Google Reader a try, but I just couldn't see the point. Having added various sites like guardian.co.uk, bbc.co.uk and Slashdot, I just never bothered to check it. Why? Because these were sites I visited pretty much every day anyway - I didn't need another application telling me what articles were on there.

However, having been on a mission to immerse myself in the Groovy + Grails community of late, I suddenly get it! Sites like Graeme Rocher's Blog and Grails Podcast are not sites I look at every day, but I want to be notified whenever they publish new articles. And that's exactly what RSS / Google Reader does for me. A quick glance at my overview page, and I can see if any of the feeds I've subscribed to contain any new articles. :-)

Friday, 6 March 2009

Google App Engine - Final Thoughts

I was a little disappointed with Google App Engine. While I concede that it allows you to get some VERY quick results, what started out as niggling doubts at the start of the project soon became genuine concerns:

1) The whole thing seems to be a bit muddled. They're kind of half-supporting an old version of Django, meaning that some Django features are available but some are not. For example, if you try to do a server-side password field as suggested in the Django docs, it doesn't work.

2) No guidance on project structure, unit testing, etc. The approach adopted by most people seems to be 'lump everything in one folder' which leads to a very disorganised project. By contrast, Groovy + Grails has clearly defined areas for domain models, controllers, views and tests.

3) You're tied to Google's technology. Running a GAE app outside the App Engine environment is not simply a case of flicking a switch. Similarly, you would need to do a significant amount of work to get a Django app to run on app engine.

4) Out of the box, you don't even have access to the session! Everything has to be done with the datastore, which feels very restrictive.

5) Your request handlers implement get, post, etc which map directly to HTTP methods. For me, this level of abstraction is too low - in the last few years the Java community have progressed onto controllers + actions which seems to be a better fit for implementing complex behaviour.

6) Persistent entities must extend a database Model class. Worse still, if you intend to create multiple sub-classes of that class, you should extend PolyModel. Again, this kind of thing has been frowned upon by the Java community for some time. By contrast, a model in Groovy + Grails looks like this:
class User {

String email
String password

static hasMany = [networks: Network]

static constraints = {
...
}
}
Note that it does not need to extend anything (ie. the domain model is decoupled from the persistence strategy) and is given the ability to get, save and delete itself at runtime.

That said, I don't suppose that I'm the target market for GAE. Just the fact that hosting is provided will be a massive draw for a lot of people and I doubt there's anything better if you're wanting to create a quick and dirty mashup of some 3rd party services.