Quantcast
Channel: technoChord » tech
Viewing all articles
Browse latest Browse all 15

Grails – The Holy Grail of Rapid Application Development

$
0
0

Today there are far too many choices in the technology stack to build a modern enterprise application. Altho’, for the most part, that’s a good thing, when it comes to building a plain vanilla solution that is mainly a CRUD application, that range of choices may be unnecessary. Convention over Configuration (CoC) frameworks are an answer to that problem. And altho’ Ruby On Rails was the first modern attempt (meaning web based enterprise applications) to address that issue, GRAILS seems to be the emerging winner.  Here’s why:

  1. It has the backing of a avant garde organization like the Spring Framework.
  2. It is built on Spring MVC which is already very widely used.
  3. It is based on Groovy that is, in turn based on Java (Groovy offers all the benefits of a Dynamic Programming Language,which are absent in Java)
  4. It has the momentum of a freight train judging from the community support and traffic.

So I experimented with GRAILS and was pretty impressed. So here’s a brief look at this technology.

What is GRAILS?

The picture below shows the technology involved in enabling GRAILS (Groovy on Rails).

Gant - Allows Ant Taskdefs to be embedded in Groovy instead of of XML. More powerful because the logical language constructs that Groovy offers are absent in XML

Gradle - A build language using a Groovy supported DSL

Grape - Provides annotations for making project dependencies available in your source code.

Grails uses Gant to build a conventional project structure. Gant, in turn, can access all the Ant taskdefs to do it’s work. At present Grails uses GAnt to run it’s commands, but indends to switch to Gradle in the near future.

Actually Gant is a subset of Gradle. The main difference is that Gradle has a plugin architecture that is absent in Gant.

Gradle may be used to build the Grails project and Grape provides annotations in the Groovy code. The several (hundred) plugins that the Grails eco-system offers, may use Gant for macro functions (like file manipulation) and Groovy for fine grained functions.

As we can see,  Groovy offers the glue that holds everything together.Groovy can:

  1. Invoke Java programs, including Spring managed beans because it is based on Java and built on Spring
  2. Invoke Ant based Taskdefs by using Gant scripts that are Ant taskdefs embedded in Groovy
  3. Use Lambda functions (closures) being dynamic

How to build an app with GRAILS:

Here are the typical steps to begin a new project. Install Grails, set GRAILS_HOME and place GRAILS_HOME/bin in your classpath. Then do the following at the grails prompt :

  1. To build a project  – Type create-app testapp: Grails creates the basic directory structure of the project including defaults for the look-and-feel (css) of the web application.
  2. To create Domain Objects – Type create-domain-class com.acme.IncomeStatement: Grails creates a Groovy class that represents IncomeStatement in the correct directory. Since the details of the domain object are not yet defined, it’ll just be a stub for now.
  3. To create Controller – Type create-controller com.acme.IncomeStatement : Grails creates a stubbed out controller called IncomeStatementController.
  4. To provide app specific info – Edit the domain object by placing some member variables in it.  Edit the controller and specify a static scaffold=true in it.
  5. To build out the project – Type generate-all to let Grails create the controller and the views (GSPs) for this use case (IncomeStatement)
  6. To run the app, type run-app and visit a browser by pointing to testapp on port 8080 and go from there.

When issuing each of these commands, GRAILS runs Gant based scripts that use conventions to build out the application objects.

At this point you should be able to Create, Read, Update and  Delete an IncomeStatement from a web page right down to the database. The details on how to build the application can be gotten from several tutorials and the documentation.

What’s GRAILS value proposition:

Doing the above is pretty painless and after the dev environment is set up, would typically take no more than 5 minutes. Assuming that building validation and modifying the look-and-feel would probably take another 10 minutes, fifteen minutes to create a full-fledged CRUD application is not bad!

Looking under the covers to see how GRAILS actually achieves this then it boils down to just two things (remember, GRAILS, not Groovy):

  1. Scaffolding: Here is where Grails uses Gant and Groovy to create CRUD code for you in the controller and views as GSPs with appropriate tags in it.
    To help the creation of scripts you can use the Domain Specific Language aspect of Groovy to specify constraints and bindings. This is a big time-saver when all you want is CRUD operations on your domain objects and properly laid out css for your web pages. The code that is generated by scaffolding, includes, among other great features,  validation in the controller and supports pagination in the views. So although it may sound trivial. scaffolding does do a lot for you!
  2. GORM: Grails ORM uses a hibernate plugin under the covers to interact with the persistent store. All domain objects, by default are persistent objects. To change things you have to use an ORM DSL in either the application wide configuration or domain specific groovy file. Most of the features of Hibernate are available with the addition of Dynamic Finders. Because Groovy is interpreted at run-time, these methods are not physically available on the domain object but are made available at run time.

In addition to above, Grails has a VERY busy developer community with tons of plugins, that you can check out here.

How to introduce GRAILS in your organization:

Identifying a narrow use-case of an existing application and building an app that reuses the existing application’s domain model and database schema is probably a good way to ease into GRAILS development.

Let’s use an example of an existing application that runs a company’s lawn care business. To illustrate reuse, let us assume that the domain objects in that existing application are persisted using Hibernate and the application is built using Maven. (Note that if no code re-use is intended, then the existing application does not even have to be written in Java; just build the GRAILS app parallel to the existing one and the only touch point would be the database).

We now want to add a feature where lawn care workers can update where they worked on a particular day and for how long. Let’s call this new feature WorkRecorder and use GRAILS to build it.

WorkRecorder will need the customer and equipment domain objects from the existing app, but will need to define it’s own domain object called Work. Therefore it will need to Create, Read, Update and Delete a Work domain object and Read  customer and equipment domain objects from the existing application.

In the picture above we can see that our brand new GRAILS application WorkRecorder creates a GRAILS object called Work and also accesses the Customer and Equipment objects from the exiting application.

For the CRUD on Work, GRAILS commands like create-domain-class can be used followed by  create-controller and create-views. With the use of scaffolding, you can get full fledged CRUD operations on the Work object. But when you have to show a list of equipment that is used to execute the work, then you will have to make those domain classes available to your Groovy classes so that you can include them in the constraints therein. There is a nice blog entry here and and Grails docs talk of it here.  In Peter Ledbrook’s article, he suggests that we can either make classes from our LawnCare app available via source code (by placing in src/java under grails-app directory), or by placing the jar file in the lib directory.

If the LawnCare application is fairly well-baked, then making it’s  jar file available to WorkRecorder may make more sense. But instead of placing it in the GRAILS project’s lib directory, I found it cleaner to make it a dependency of  the WorkRecorder app by specifying in the BuildConfig DSL’s dependencies section.
For example:

...
    dependencies {
        compile 'com.acme.greenhouse.LawnCareServices'
        runtime 'ojdbc6.ojdbc6.11.1.0.7.0'
    }
...

In theory, you could build out a parallel CRUD application (UI to db) using the “imported” domain objects Customer and Equipment. That would probably not be a good thing because now you have two ways to persist Customer and Equipment (and you’ll have bypassed any business logic embedded in the LawnCare app), but in the event that you would like this to happen, you could still use GRAILS commands create-controller and create-views commands and pass them these domain objects. With scaffolding turned on and constraints defined in CustomerConstraints.groovy and EquipmentConstraints.groovy, you could build out a modern validation UI also by using the command generate-all.

Maven and GRAILS:

Having been a Maven user for several years now, I have to admit (with a heavy heart :) , that Maven and GRAILS do not play well together. With GRAILS, Gradle is the build tool of choice (which I’ll talk about it in a later post). Gradle uses Ivy for dependency management and so, in our example, since LawnCare was built using Maven, we will end up with two local repositories of dependencies, one from Maven and another from Ivy.

By default, the Ivy repository lives under <UserName>/.grails/ivy-cache whereas the Maven one lives in <UserName>/.m2/repository. That’s not a good thing, especially for the first time when the dependencies are being downloaded.

Also, when developing behind a firewall, a proxy may need to be specified. This can be done via a grails command called add-proxy and corresponding remove-proxy. The add-proxy command creates a file called ProxySettings.groovy which contains:

myproxy=["http.proxyHost":"a.b.c.d", "http.proxyPort":"8080", "http.proxyUser":"", "http.proxyPassword":""]
currentProxy="myproxy"

To disable the proxy, you can simply comment out the currentProxy line.

In the next post I’ll cover the impedance mismatch between Gradle/Ivy and Maven.

http://www.gradle.org/

Viewing all articles
Browse latest Browse all 15

Trending Articles