Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreGrails is a fantastic framework for developing web applications quickly and easily. You also have access to a plethora of plugins that provide features or make integration with other systems nice and easy. That's all good, but in this article I want to talk about what happens when your application grows and you start drowning in a sea of controllers, domain classes, and other files.
The real beauty of this pattern is that you can aggregate these units into coarser-grained concerns, so you end up using the pattern at multiple levels. For example, say that the web service mentioned above provides a blog-like feature. You could package the business logic, SOAP gateway, and perhaps a REST interface all into a single unit that can be reused.
The standard form of packaging for such coarse-grained features in the Java world is the Java ARchive (JAR). If you're already a Grails developer, you will know that your Grails applications can use such JAR files. But they don't help when it comes to controllers, domain classes, and other special Grails "artifacts". Fortunately, we have a ready-made unit that can help: the Grails plugin.
Ryan Geyer has written a great post demonstrating how to use a plugin to provide a reusable domain model and why you might want to do so. Here's another example in diagrammatic form:
We package a blog feature into one plugin and a payment processing feature into another. The idea here is that multiple applications are likely to use the same payment processing code and some may also require a blog feature. You can also package static resources to ensure that all your applications have a consistent look and feel. That's what the branding plugin is for. This could include views, layouts, and tag libraries.
Ryan's article shows how to do all this via the plugin installation mechanism, but let's face it, that's hardly conducive to a rapid feedback development cycle. Every change in a plugin requires you to package the plugin and then install it in your application. Fortunately, there is another way.
Imagine you have a simple application and a blog plugin side by side in the same directory:
my-app +- blog +- app
To include the blog plugin into app, just add this entry to grails-app/conf/BuildConfig.groovy:
grails.plugin.location.blog = "../blog"
The required prefix is "grails.plugin.location." - what comes after is up to you, but I recommend you use the name of the plugin. On the right hand side of the expression is the path to the plugin's development directory. Note that this can be absolute or relative.
Voila! When you run the application, you will have all blog's domain classes, controllers, views, etc. available. Even better, if you modify one of blog's controllers or views while the application is running, those changes will automatically be picked up. In other words, you get automatic reloading with in-place plugin artifacts just as you do with your application artifacts.
So with in-place plugins you get the benefits of separation of concerns, but you also get the rapid-feedback development cycle from normal Grails development!
This technique works well while you're working on a plugin, but it doesn't scale particularly well between multiple applications and development teams. Fortunately, you can easily remove the grails.plugin.location line from BuildConfig.groovy, publish the plugin to an internal Maven repository as described here, and then add the plugin as a dependency via the dependency DSL.
Using plugins to break applications into reusable parts is an incredibly powerful and flexible technique that will allow teams to easily manage multiple applications or even complex standalone ones. As you have seen, Grails supports this approach with the in-place plugin mechanism, which allows for rapid development, and plugin dependencies. On top of that, you can easily transition between the two mechanisms by a quick change to the grails-app/conf/BuildConfig.groovy file.
I hope this article inspires some of you to try this technique and benefit from Grails' productivity boost for large applications as well as small.