Jun 29, 2010

Usage Patterns for Gaelyk

Using Groovy on Google App Engine is relatively simple due to Groovy’s compatibility with Java.  However, until recently, the framework support has been lacking.  Grails now supports GAE through the use of the app-engine plugin and the gorm-jpa plugin.  However, in many cases this can be a little heavy weight.  Much of the GORM functionality is also lost because of GAE’s usage of a NoSQL datastore and the limitations of JPA.

Gaelyk is quickly emerging as one of best frameworks for development on Google App Engine.  It is extremely lightweight, but provides value by making the most common actions in GAE easily accessible.  It also takes advantage of Groovy’s dynamic nature to make gathering and persisting data extremely easy.

By design, Gaelyk does not force any particular usage pattern.  It can be as simple as a list of scripts that create html using MarkupBuilder or as complex as a full MVC pattern similar to Grails.  While this is great to have, it can also leave you paralyzed by choice.  Here I’d like to explore a few of the patterns that I’ve come across while using the framework.

The Gaelyk tutorial lays out a a very simple usage pattern: Create an entity, populate with parameters from the request, save.

def person = new Entity("Person")
person << params
person.save()

Here the params object contains request parameters.  This approach is highly UI driven.  Our domain object structure is dependent on what parameters are provided on the request.  Of course you could also add validation etc to your script to ensure data integrity.  The tutorial also points out that the subMap function can be used to limit the fields in question.  However at that point we start to wonder where to define those fields and how to organize these domain definitions.

One approach is to define domain objects as you would in a typical MVC framework.  An example of that is here.  This allows for clearly defined types.  However, under the covers the object must be saved as an Entity, so you are left with the choice of converting the object back and forth or managing an entity object under the covers, making your domain object a delegate to the entity.  Either way this can be a real headache.

The middle ground approach that I find most useful is to define your domain, but not as an object.  That way you can take advantage of the dynamic features in the Gaelyk tutorial, but still clearly define your domain model.

Here is a Gaelyk plugin that I’ve created for this approach. Because of the magic of dynamic routing and dynamic attributes, all we have to do is define the structure of the domains in a class called DomainDefinition and the CRUD actions and pages are available.  Unlike Grails or other frameworks, there is no generated scaffolding.  All domains will use the same actions by default.  However, if you choose to implement your own custom view or action for a particular domain, it is smart enough to use that instead.

The basic pattern used by this approach is very similar to the pattern in the Gaelyk tutorial.  Below is the function used for retrieving the parameters defined for a given entity.  Here domain is the domain definition we’ve defined determined by the URL and params are the request parameters.

propertyValues = {domain, params ->
    def props = [:]
    domain.attributes.each { attr ->
        props << ["${attr.name}":attr
                  .transformFromString(params[attr.name])]
    }
    props
}

As you can see the same pattern is used except we are only populating attributes that are defined in our domain.  An optional “transformFromString” method is also used to take the String parameter and create the appropriate datatype.  This provides a consistent method for populating our objects without the need for managing domain objects.  Additional methods are available for creating, retrieving and storing entities.  With all of this the save script for all domains looks like this.

def domain = DomainEntity.findByName(params.domain)
request.setAttribute("domainEntity", domain)

def props = propertyValues(domain, params)
if (domain.validate(params)) {
    createEntity(domain.name, props)
    forward '/domain/list.groovy'
} else {
    request.setAttribute("error","Failed Validation")
    forward getRoute(domain, 'create')
}

We now have an easy way to define our domain objects and a dynamically created scaffolding without compromising the flexibility of the framework. This is sufficient for most simple domains and works as a simple base for more complex domain definitions. More complex scenarios can follow a similar pattern with customizations. Be sure to check out the source to see the implementation details and examples.

As Gaelyk matures, usage patterns will certainly continue to develop.  Depending on your project size and type, any of the above patterns, or something different altogether may be the best solution.  Given the extreme flexibility of the Gaelyk framework, many things are possible.

About the Author

Object Partners profile.

One thought on “Usage Patterns for Gaelyk

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]