Tejas Rana

Why Should Java Developers Give Grails a Chance?

Java has an ecosystem that has matured through years of development, establishing it as one of the most reliable platforms out there. Yet it lacks the means necessary to get the job done quickly, especially for things like web applications. In an attempt to avoid frustrations with these types of issues, developers often opt instead for implementation languages and their modern web frameworks, such as Ruby with Ruby on Rails, Python with Django, and so on. Unlike Java, these provide a much more streamlined path to building a web application.
Fortunately, for Java developers wanting to build web applications, there is a better way, and it involves Grails. In this article, we will see how Grails with Groovy is a viable alternative in the JVM realm. We will look at some examples where Grails is appealing to us as Java developers and might tempt someone else to give it a shot as well.

The Story

In a startup I worked for, we had this exact problem. We had a Spring application which was becoming a pain to work with. With it growing larger and larger, we soon found that refactoring and adding functionality was taking us way longer than it should. Combining that with some other motivations led us to decide to rewrite our core application. We were also open to changing or replacing existing technology stack. Grails looked like a viable choice since it runs in the JVM and is built on top of technologies we already knew. It uses the Groovy programming language but at the same time allows you to mix it with Java. So we took the plunge.

Full Speed Ahead

One thing Grails really excels at is making it easy to start a new project. It is as simple as running a command which creates the project structure with all the folders needed for the classes you will add later. Adding model classes, controllers, services and web pages takes a similarly minimal amount of effort. The only thing you need to take care of is naming and placing stuff correctly. Unlike Java, there is virtually no boilerplate code that needs to be there just because it needs to be. This is partially made possible by using Spring and Hibernate which are two of the pillars of Grails, as well as the concept of coding by convention. To run the project, Grails comes bundled with Apache Tomcat as a development server. All we have to do is run the project in our IDE and the server will be fired up with our code deployed. Also, the Grails’ Object Relational Mapping (GORM)with Hibernate will take care of creating the database for us. To use an existing database, we need to configure the JDBC connection properties or just leave it by default to use an in-memory instance. Once the server with Grails is running (takes a little bit more than a Spring MVC application), we can modify the code and the hot deploy functionality will keep our debug session equipped with the latest version. The only classes that cannot get reloaded this way are the entity classes.
Populating the database can be done by using SQL scripts, but that can get tedious. All Grails projects contain a Bootstrap class which will be run when our application is run. In this class, we can store or modify data and thus initialize our application state. This proved very useful for us so we have some test cases in development version right away.

Manipulating Data

One of the things that immediately caught our attention with Grails was the ease of working with data. Reading from the database is a task that needs to be done over and over. And many times it is simple. Like fetching one or more entities which meet certain criteria and then aggregating them. Why not use a dynamic finder for that? It is a way of querying data where methods are dynamically created at runtime. All you have to do is follow a naming convention.

def users = User.findAllByLastNameLikeOrAgeGreaterThan(‘Doe%’, 30)

The line above line will fetch all User objects with last name starting with “Doe” or age greater than 30. Yes, not a very sophisticated case but you get the gist.
What if we wanted to filter this list additionally for the ones that have the “failedLogins” property greater than 10? And what if we wanted to sort them by their date created? And what if we wanted to get their first names concatenated or find the maximum age of the users returned?

users = users.findAll() { it.failedLogins > 10 }
users = users.sort { it.dateCreated }
def firstNamesString = users.firstName.join(‘, ‘)
def maximumAge = users.age.max()

The above examples may look simple, but they show how powerful Grails can be for querying, filtering, and manipulating data. In Java 8, you can achieve similar results for some of these cases, but it will still require more code than Grails.

Sometimes I Want to Create Differently

A dynamic constructor or named argument constructor is a feature that many of us wanted to have in Java. It’s nice to define which constructors a certain class allows, but in many cases you just want to set some properties and get the darn instance. Groovy adds a special constructor for each entity which basically takes the elegance of a map as input and sets the properties with the map entries.

def Person = new Person(name: 'Batman', age: 57)

This approach leads to code that is much more expressive and avoids the need for all the constructor boilerplate code.
And BTW, here are some examples of the awesomeness and elegance of Groovy’s maps:

def emptyMap = [:]
def map = [bread:3, milk:5, butter:2]
map[‘bread’] = 4
map.milk = 6

This is another example of how the code can be short and simple, yet powerful. It shows how inline initialization can be used and how map values can be manipulated in a way similar to object properties. No need to call traditional Java methods for basic manipulation, unless you really want to.

We Need More Power!

Of course, there is no framework that can do everything, but when we’re filling in the gaps, we should see what else might already be available before trying to implement our own solution. To expand our arsenal of Grails-based functionality, we can use Grails Plugins. Installing a plugin is simply done by adding another line in the BuildConfig class that is present in every Grails project (code convention strikes again!).

compile ':spring-security-core:2.0-RC4'

The line above adds the Spring security core to our application and there is virtually no more configuration needed to incorporate this functionality.

It’s similar to using Maven dependencies (which you can also reference in the same config class), but the plugins are usually larger blocks that contain the whole functionality.

That being said, let me tell you about a case we had to deal with. We needed to implement a search spanning across several data entities. Grails has an Elasticsearch plugin which is a breeze to use. As mentioned before, we only need to reference the plugin in the config file and we’re good to go. If we want to search for entities of a certain class, we just need to add a static “searchable” property to that class. And if we want, we can even limit the properties that will be allowed to be searched.

class User {
    static searchable = { only = name }
    String name
    Double salary
}

It is so little code, but under the hood, Grails and the Elasticsearch plugin will automatically index all users by name and enable us to search by name. The actual search call is also very concise:

User.search("${params.query}")

If we don’t want to, we will never have to touch the Lucene index. All will be done auto-magically for us. The plugin even has an API for displaying search results – it can highlight the match found inside searched text. This is just an example how a plugin can provide a huge bundle of functionality which can make us that much more efficient by avoiding the need for us to implement it ourselves.

We Still Need More Power

Plugins are great, but sometimes we don’t need a whole plugin, we just want something extra. Do you remember the last time you wanted to have an additional method on an existing Java class but you didn’t want tp (or couldn’t) extend/override them? In Groovy, you can add methods and properties to existing classes, or even just certain instances of them. For instance, you can add a formatting method to the java.util.Date class which is awesome when you want to format dates consistently and just don’t want to write static util classes or define various filters.

Date.metaClass.formatDate = { delegate.format("dd.MM.yyyy") }

What if you want to sort a list of users by a computed value and you only need this in one case (i.e. adding a new method in User class would be polluting)? You could add a property on each of those instances and then just sort or filter the collection by that property:

user.metaClass.computedProp = 312 * 32 * 3

Groovy authors have already added a lot of enhancements to some of the core Java classes, so we don’t have to. Below are some examples.
Using “minus” to remove all elements from a collection that are present in another collection.

assert [1, 2, 3, 4, 4, 5] - [2, 4] == [1, 3, 5]

Additional methods for manipulating java.util.Date objects which come in handy so many times, such as adding/subtracting days from dates or getting/setting a certain field of the date without converting it to Calendaror using additional libraries.

def yesterdayAllMyTroublesSeemedSoFarAway = new Date() - 1
def myAwesomeAnniversaryYear = myAwesomeDate[Calendar.YEAR] + 1
myAwesomeDate.set(year: myAwesomeAnniversaryYear, second: 0)

When you want to really get descriptive with date manipulation, you can simply use the Groovy added TimeCategory class:

use (TimeCategory) {
println 1.minute.from.now
	println 10.hours.ago
	def someDate = new Date()
	println someDate - 3.months
}

A Hammer and a Nail

Then there are the IDEs. Eclipse-based GGTS and IntelliJ IDEA are set-up for working with Grails. They understand the project structure (and will help you navigate through folders and resources) and have shortcuts for the commands you will most often use (e.g., add controller, add a page, run a project, etc.). With Grails you will execute commands (to run a project or set-up a new plugin functionality) and you will need different configurations, which is also covered by the IDEs. Code completion works nicely in Grails web template pages where you will often reference controllers and actions.There are also other IDEs that can be used with Grails such as Netbeans, TextMate, Emacs and others.

What About the Dark Side?

Just as with everything in life, there are caveats with Grails also. There is a lot of magic being done under the hood which can often be a good thing, but sometimes the result will not be what you expected. Bugs will happen just because of not using typing (yes, types are optional in Groovy) and not being careful enough. And maybe you won’t notice an error until it’s too late. Also, it’s very tempting to write one-liners to impress your coworkers. And yourself. But these powerful lines of code might not be as self-explanatory to your coworkers. Or even to yourself in a couple of months. That’s why I think Grails demands more programming discipline than some of the more traditional frameworks.

Time is Money

Coding shouldn’t take more time just because your current framework demands it to. Especially with the increasingly huge number of startups these days, it’s important to focus on the tasks that really matter and to be as efficient as possible. Time is indeed money and time to market is critical. You need to be able to act quickly and implement the solution before time runs out and your competition beats you to it.
My friends working with Ruby on Rails or Python/Django have long been telling me how cool those technologies are. And it really felt silly to think how much more time it took me in Java to write code that stores something in database and displays it in a web page. Grails may indeed be a useful answer. It’s not that you couldn’t do this with pure Java, Spring MVC, and Hibernate. You could. Your application might even run a little faster. But you will get the job done faster with Grails.
This post originally appeared in Toptal Engineering blog

Exit mobile version