mišljenja i zapažanja o društvu i životu u Hrvatskoj

Grails LogoIt’s nice to start a new year off on the right foot, and what better way to do it than by learning and trying out something new? Grails has been on my mind for years and now it seems that the time is ripe to give it a try. It is one in a fairly long list of web frameworks. Like most its competitors, it too touts unique features which make its developers believe it will be the Next Big Thing. While IT history has made it perfectly clear that a magic wand will not be produced any time soon, I thought it worth the effort to get to know and leave an article or two on the subject along the way.

So, why Grails? To begin with, developers who work within the confines of a single paradigm and have never learned about anything else tend to be quite provincial in their way of thinking: every paradigm and tool imposes many constraints on how developers implement a system and how it works, but they don’t realize it because they haven’t seen anything that works differently. It is like asking a veteran CVS user if they like it: sometimes they say that it’s OK (with CVS, it doesn’t get any more positive than that), but they only say it because they’ve gotten so accustomed to working around its numerous and fundamental flaws that they don’t even notice they’re doing it any more. Coming back to Grails, I have worked with various web technologies, but have been left longing for a framework which makes it easy to automate a set of processes without having to wrestle with it along the way.

If Grails had to be described in less then ten words, it would be “a Java-esque equivalent to Ruby on Rails“, Rails being one of the most talked about technologies on the web (or hyped, if you like). Rails was chosen as a role-model because it comes with the promise of being DRY-compatible (Don’t Repeat Yourself), light-weight, quick to pick up, set up and above all, very productive. Grails takes a page from the Rails book, but attempts to achieve its goal – high productivity and succinct code – by using established technologies, rather than writing everything from scratch, as was done with Rails. The two offer what appear to be a very similar development environments (in the broadest sense), but Grails uses proven enterprise software to do it: Hibernate and JDBC for database access, Spring for behind-the-scenes dependency injection, Groovy as the programming language and one of the most heavily optimized and ruggedised pieces of software ever – its majesty, the Java Virtual Machine – as is execution environment. If the only difference between Grails and Rails was e.g. Hibernate, I would still find it hard to justify choosing Rails, but with the whole package it seems like a rather unfair competition. It might be worth keeping in mind that I haven’t seriously used either yet, so I might be jumping to conclusions.

Groovy, the Grails the language of choice is a special reason I am looking forward to Grails. I have been using Groovy for a few years now and I think I might write a separate article on how wonderfully liberating and lightweight using it feels, possibly followed by another one describing how I long for Java to at least show that it’s reaching in the right direction. That said, talking about Grails without mentioning Groovy would in my mind miss the point, so I’ll try to give you a taste of the language without going overboard. What Grails is to Rails, Groovy is to Ruby: a Java-esque language (accepts most Java code as valid Groovy code), not nearly as burdened by expectations of an army of Java developers, compiles to Java bytecode, runs on the JVM along side pure Java classes…it doesn’t keep its close relationship with Java secret. However, while Java inter-operability is likely to help adoption in the Java community, Groovy has a lot to offer of its own: it can be both dynamically and statically typed, it radically simplifies Java’s syntax, enriches core Java APIs and can be interpreted so it lends itself to advanced scripting. A few code snippets should go far in illustrating what it looks like in action…

Want the contents of a text file?

content = new File("myfile.txt").text

Probably not the best fit for reading e.g. multi-gigabyte logs, but it works great 95% of the time without laying out all the underlying plumbing for all the world to see. Suppose myfile.txt was a configuration file: how would a content update be saved back to the file?

new File("myfile.txt").text = updatedContent

How do you initialise a map?

Map map = [red:"wait", yellow:"get ready", green:"go!"]

How many characters do the individual semaphore messages contain?

map.values().collect { println it.size() }

How do you count to 128?

128.times { println it }

How do you retrieve a value deep in an object graph?

println user?.address?.streetName

You don’t think this last one was anything special? In Java, it would typically look like this:

if (user != null && user.getAddress() != null) {
    System.out.println(user.getAddress().getStreetName());
}

I could just go on with rather impressive support for domain-specific language development, metaprogramming, working with XML, closures, looping and iteration, default imports, the interactive shell, regular expressions and so on – but that belongs in a different article.

Getting back to Grails, it appears as difficult to briefly summarize what it brings to the table. Like Maven or Rails, it is opinionated software: it has a fairly strong idea of how an application should be built and how it should run. This undoubtedly makes it a less than an optimal choice for certain applications, but my impression is that a lion’s share of applications easily lend themselves to the Grails architecture, in much the same way that Maven easily builds diverse applications. The conventions Grails brings to the table – its directory layout, naming, database model guidelines etc. – all of them are carefully chosen to reduce slack where it is least necessary and maintain and expand it where it is. In a sense, developers no longer have to think very hard where a piece of code should go. Now, if all developers were rock star developers, this might not be very welcome because they don’t have much trouble finding their way in the first place, but the reality of software development is not as rosy. A typical team consists of people of very varying skill levels and some guidance is often welcome. The conventions and the specific technology mix also have the nice side-effect of making it easier to find one’s way around a different Grails application, compared to picking up an arbitrary Java application.

Since I have already mentioned the technology mix, Grails comes with batteries included. It has a templating engine to render HTML, a default servlet container to develop in, a pair of JavaScript libraries for the UI, unit testing infrastructure, a build system, an ORM to access a database and even a database itself! Once it is downloaded and installed, it takes no more than a few minutes to write and run the first database-enabled application. I like that, and I like it even more that much of the underlying technology can be taken out and replaced by something else, e.g. Hibernate with TopLink, Jetty with Tomcat etc.

Finally, it has a lot to show for itself as a framework. Many (most?) code changes don’t require any kind of reloading, in effect providing PHP-like, immediate application updates. This tightens the write-deploy-test loop and in doing so, it allows developers to maintain focus on the task at hand, rather than wandering off to an interesting blog (like this one…) while the code builds yet again. It distinguishes between various runtime environments, very similar to Rails: it is nice that the test database gets purged automatically, but it would be quite a problem if the same happened to the production database… It boasts a plugin architecture and a growing collections of available plugins. It has  an interesting data access abstraction above Hibernate called GORM which makes for very concise and readable queries. It has data migrations to allow controlled application upgrades preventing data loss, it allows quick CRUD prototyping from the command line, it has high quality unit, functional and integration testing infrastructure, a nice data validation system, tag libraries and many more promising features that would each easily be subjects of their own articles or books.

At the moment, I am reading a Grails book from cover to cover, approaching the end and really enjoying most of what I’m seeing. While I do expect a number of “oh, no, what were you thinking…” moments, I am really eager to see how well it lends itself to expressing some of my ideas…

Comments on: "The Groovy Way to Spin the Web" (10)

  1. Hello Tomi,

    I understand all your theory while comparing Grails to Rails, but on the other hand I have a lot of experience on both of them. My current job is to maintain a Grails web application, and I’ve been doing so for the last 3 years as main main job, in two different companies and different projects.

    I do also believe that reusing proven technology is a good thing, but in practice, Rails is a solid framework and a very well tested on (talking about automated tests). I can’t remember fighting against some bug in Rails, since 2007 when I’ve learned it. On the other side, I’ve been fighting against Grails since I’ve got in touch with it in 2009, every single day. I face a lot of bugs and there are some parts of the code that are just scary. You’ll find an example in my last article about what I learned about code writing along the years:

    http://rosenfeld.heroku.com/en/articles/programming/2012-01-08-what-did-i-learn-about-code-writing

    Take a look at the code extracted from the Grails framework in the “How not to code” section.

    Unless you’re developing on Windows, I would rather strongly recommend Rails over Grails. Grails is a hell buggy and over-engineered. The Hibernate integration in GORM is over complicated and leads to lots of problems… For instance, I can’t understand why do we need an owner side of many-to-many relationships…

    Also, there is a lot of magic and meta programming in Grails that makes it very bug prone and hard to debug. In the other hand, Rails is just Ruby. Your Models are inherited from ActiveRecord::Base. Your controllers are inherited from ApplicationController that is inherited from ActionController::Base. In Grails, all special methods are injected by the framework.

    Writing automated tests in Grails is a pain. I’ve been fighting against some really weird bugs while writing a unit test for one of my controllers today on this exact day. The tests passed when not running inside the interactive console. When run from the interactive console, they would pass in the first time and fail in the second one. Adding a non-sense test to the testing class, made it work even in the interactive console, but that simply doesn’t make sense. This happens to me all the time… A while ago I’ve got lots of reloading issues with Grails until I could associate it with my Vim swap files. All those issues took me lots of valuable time.

    I would really suggest against Grails and strongly recommend Rails for development in non-Windows environments.

  2. Hi Rodrigo, thanks for the comment: I appreciate the opportunity to learn from your experience.

    I read your article, briefly reviewed the HibernateCriteriaBuilder.invokeMethod() code and for the most part, I agree with several points: I would say the method is way too long, parameter and variable naming is poor, deep branching logic makes it difficult to know what the execution context is and so on. There are things in there I would not agree with (e.g. methods up to 5 lines), but that is beside the point.

    I guess one of your points is that Grails can’t be trusted because it was written in this manner? I would need more than a single class to base that decision on, but it might makes sense to take a quick look at the source…

    As for your own experience, my impression is that you’ve done much more work with Grails than Rails: do you think you might be seeing more bugs in Grails because you spend more time with it? Regarding the bugs you experienced, did you take them up with the Grails community? Is it common knowledge that Grails is very buggy? Do bugs get fixed quickly? I ask because the bugs you mention seem rather low level so they would impact a lot of people heavily…

    As for the “magic” and meta programming, that too is “just Groovy” and while I understand the value of sticking to direct (rather than meta-) programming, there are cases when it is warranted: e.g. aspect oriented programming (not related to Grails, but it illustrates a useful kind of “magic”). I’m not saying that Grails is doing it right: it’s just that the argument isn’t an absolute truth.

    Finally, do you think Grails 2.0 changes anything? I mean, your experience from 2009. is valuable, but Grails was very very young then: how relevant is it to Grails today?

  3. Hi tonalf, let me answer in topics:

    Limiting method bodies to 5 lines: not a rigid rule, but in general, it helps writing unit tests and improves readability. A method should have a single responsability. If it really needs more than 5 lines, that is ok, but usually you can write methods up to 5 lines…

    My points about Grails are farther more than just its source code and lack of more automated tests. I used it regularly and have tons of complains. I’ve written an article entitled “Why I prefer Rails over Grails” before in my site, but I didn’t link it to you because it is outdated since Grails 2 was released. Grails 2 is way better than Grails 1.3.7 but still has plenty of bugs. There are also many other reasons, but I couldn’t find some time for writing an updated article comparing both. I’ll let you know when I write one.

    About my Rails experience: I’ve developed with Rails from 2007 to 2009. Never had any issues with Rails bugs. Since 2009, I’m developing with Grails and had been having lots of different issues since then. But that doesn’t mean I stopped programming with Rails at all. I still write Rails applications for my own use and my site is written in Rails, for instance. I’m just not a full-time Rails developer. But Rails is much more mature now than when I’ve used it full-time in 2009. It has lots of great features since then and the community has also evolved a lot with new and powerful plugins, all of them (the most used ones) very well tested (again, read automated tests), differently from the Grails community that has lots of plugins lacking automated tests…

    Also, try to read the Rails sources and you’ll find that it is much better written and organized and that the documentation is pretty good. Also take a look at the test coverage to see how complete it is… If in doubt, try to make a small modification to Rails source and re-run the tests and you’ll see at least one of them failing if you changed any behavior…

    Rails won’t accept any changes other than refactorings without a test. I’ve already contributed to Rails and I know their policy. You’ll also find that the tests are very readable too.

    About Grails 2, I’m already using it since December, 15 and it was a pain to upgrade my application. Just look for my messages in the Grails user’s list to find out all the strange issues I had and lots of bugs I’ve found in the process.

    You’ve asked if the bugs are quickly fixed in Grails. Definitely not! I still have reported bugs opened (most of them) for several months now. In the other side, the only 2 minor bugs I’ve reported to Rails last year were fixed within an hour. Yeah, I mean the fixes with the tests were commited within an hour since I reported them in GitHub.

    About meta-programming. I don’t have anything against meta-programming but you shouldn’t be using it when regular programming does the job in a great way. Even in Ruby, where I find meta-programming a lot easier than in Groovy, I still think you shouldn’t abuse from meta-programming. Often there is no need.

    I understand lots of frameworks for manipulating byte-code and frameworks like Spring and aspectJ for Java, but they exist to circumvent the verbosity and limitations of the Java language. Groovy and Ruby aren’t verbose languages, and you should be able to accomplish most of your tasks with regular programming on those languages.

    Also, from what I’ve seen, the Grails bugs do affect other users too, altough I can’t understand too why most won’t report them and just use some workaround…

    • Thank you for the comments, Rodrigo. I tried to find something to confirm your opinion of Grails on the web and indeed, it is not difficult to find other people who have similar impression. Most of the chatter on the subject is from 2008 and 2009, though, and I get the feeling things have improved a bit since. I definitely like the confidence you express in the Rails unit test coverage.

      As for Rails, from what I’ve read, it appears to be a pleasure to work with for a lot of people. I might take a closer look, although it is not like I haven’t already seen a few things, some of which I’m not too thrilled with: the gem system, the gaping hole left by the absence of HQL (apparently, Rails has no DB-independent way to handle queries returning results from multiple tables) and there is the obvious question of available libraries: I would be surprised if e.g. log4j, Jasper Reports, Apache POI etc. weren’t light years ahead of anything Ruby has to offer and as much as Grails might seem like a pale imitation of Rails, JRuby looks like a pale imitation of Groovy so Grails still feels like it keeps more doors open.

      I do look forward to reading your updated comparison, though.

  4. Hi Tomi, I’ve started to write the updated article but it will be very long and I’m done for today, although there are yet lots of sections to write about, so I’m not sure when I’ll be done with it. For now, I’ve just wanted to point out that HQL limitations are one of my major issues with Hibernate and that ActiveRecord , used by Rails by default, does support joins in a DB independent way. I’d strongly suggest you to read the Rails guides before getting to your precipitaded conclusions: http://guides.rubyonrails.org/active_record_querying.html#joining-tables

    ActiveRecord at least will allow you to easily use some SQL snippets if you need to.

    With regards to the Java libraries, I really can’t understand why do you think log4j is a so special library. A logging system can’t really be so complex that it would make any difference if you change your language… But I must agree with you that you won’t find libraries like Jasper or POI for Ruby. I’ve written about how to generate PDF from ODF templates for the Rails Magazine in the past (see link below), but I agree it is a different approach. If you really need such kind of complete libraries, you can also use JRuby, so there is no need to avoid Rails. Rails test suite will go green on JRuby too.

    http://rosenfeld.heroku.com/en/articles/ruby-rails/2010-03-16-generating-pdf-with-odf-templates-in-rails

    And I don’t understand why you think JRuby is an imitation of Grails if it existed before Grails. Also didn’t get what is your problem with RubyGems. It is much more powerful than Maven. And Bundler is yet more powerful, using RubyGems and adding more specialized support. The Java community doesn’t have anything close to Bundler for managing dependencies…

    • Hi Rodrigo, are you saying ActiveRecord provides an equivalent for “select v, t from Visitor v join v.tickets t” without falling back to plain (and DB-specific) SQL?

      As for Java libraries, I’m certain the Ruby library collection is growing and has wonderful things to show, but compared to Java, almost any other language would find it hard to compare. Speaking from personal experience, the kind of niche nuggets of gold one stumbles upon looking for Java libraries is really awe-inspiring. That leaves me (maybe not you) with JRuby, and while JRuby does in fact provide a certain level of interoperability, Groovy consistently comes up as the superior language with regard to Java interop. It might not be a bad idea to take a closer look at the significance of the difference, though…

      As for gems, the few times I tried ruby out, gems felt like a parallel package management system to apt or rpm (not a good thing, in my mind)…but fair enough: if you ignore the native OS package management system, I expect it does its job well.

      I appreciate you drawing my attention to Bundler: Maven has so far proven to be invaluable in the kinds of projects I work on (moving from Ant and Ivy some time ago), but I would gladly learn about how can it be done better. Just need to find a way to replace sleep with reading.😉

      • Tomi, ActiveRecord takes a better approach than Hibernate. Instead of recreating another query language that isn’t as powerful as ANSI SQL and have lots of real limitations that I’ve found really annoying in actual scenarios, Ruby ORM implementations like Sequel or ActiveRecord will use a DSL for building the real query in an agnostic way.

        Take some time to read the examples of Sequel or ActiveRecord and you’ll understand. Here are some examples for Sequel:

        http://sequel.rubyforge.org/rdoc/files/doc/cheat_sheet_rdoc.html

        I don’t share your thoughts on Java vs Ruby libraries comparison though. I can’t find libraries like Bundler for Java or test frameworks as powerful as Rspec, for example. Of course, the comparison is not fair since Java is a much more limited language, but what I’m saying is that usually I have an easier time finding good libraries for Ruby rather than Java. Java libraries have usually verbose APIs.

        Specially for the web, new things usually happen on the Ruby land first. The Ruby community is awesome and really smart. And specially, they do care a lot about test coverage, and code quality. Much more than the common culture in Java.

        Could you explain yourself why do you think that Java integration is better in Groovy than in JRuby? For example, if you want to add some jar dynamically to CLASSPATH:

        JRuby: require ‘file.jar’
        Groovy: this.getClass().classLoader.rootLoader.addURL(new File(“file.jar”).toURL())

        Actually, I didn’t test the Groovy example, just take it from StackOverflow.

        With regards to the comparison between Bundler, RubyGems and Maven, this is the thing. Maven you require you to specify the specific versions of the libraries. RubyGems allows you to specify dependencies as ‘json > 1.2’, for example. But it will always try to get the newest allowed versions. This could lead to some problems if you installed the dependencies today in your development machine and later in your production server as they can download different versions of the dependencies and could have some side-effect result. Bundler will take a snapshot of your exact versions when you download them and generate a Gemfile.lock file. After that, you’re always able to get the exact same versions, just like Maven. But you don’t need to specify rigid dependencies in your Gemfile if it happens for you to want do update some of your dependencies… Bundler is really very powerful.

        But I don’t get why you criticize the fact that RubyGems is a parallel system to apt, for example, but you don’t see Maven the same way. RubyGems is a dependency manager, just like Maven, so why should we package all our libraries in OS specific ways that makes everything much more complicated? Packaging a gem is really really simple. Try to package a gem and some dpkg and you’ll clearly notice the difference in difficulty.

  5. I too have worked in both in Rails and Grails. Probably have more Rails experience, but have a strong Java background. Personally, and from my experience in the environment I work in … Rails has been an absolute pleasure to work with. Ruby is just fun to program in. ActiveRecord is the bomb, rails database migrations are fantastic and the view layer is so easy to use, I mean helpers are great. But and the big but for us is that we have to deploy the app as a war onto the JVM using jetty. This has been a complete hassle. It was actually easier under Rails 2, but the advent of bundler and default usage in Rails 3 it has been a pain for us. As for Grails, well I don’t like hibernate much, but overall it’s pretty easy to use. The dependency management is so simple. Taglibs suck. It does not have the same functionality of Rails for database migrations. But working in groovy is also pretty fun. But where it’s great is the deployment. Ahh just one command to build a war file. But I agree that it does have a few bugs floating around. But if you look at Grails compared to other Java web frameworks … then I would prefer to work in Grails. But this whole debate is rather opinionated. My personal pick would be to work in Rails and deploy it using passenger. But if I have to work in a java centric place then I would rather work in Grails. My ten cents🙂

    • Thanks for the feedback, Terence. For what it’s worth, Grails does seem to support database migrations, although it’s not a core feature.

      As chance would have it, I will probably get my hands dirty with both Grails and Rails over the next few months…I’m quite excited to see what will come out of it.

      • Try to use the Grails database migrations plugin and let me know your opinions on it. Please, try it in an existent database (import initial migration). I’ve found lots of bugs on this plugin in the past, so I gave up on using it… This is specially painful if you have to deal with geospatial enabled databases, but did have bugs in usual databases as well.

        And yes, the few times I tried to deploy JRuby on Rails applications as a war was really a pain. I have to agree that deployment to Java containers and dependency management integration with Maven is much better supported in Grails, unless you’re depending on SNAPSHOT versions of some maven artifacts.

        But on the other hand, I know some people that are using the war strategy on Rails 3 for quite a while now and I don’t see them complaining about it. I’ll ask them how they do that.

        And yes, Hibernate sucks! But worse than that, Grails tries to hide its internal details from newcomers, which is totally wrong as they’ll experience several “gotchas” (they prefer to call it that way instead of bugs cause otherwise they would have to fix them). I’ve spent at least 2 full days this week fighting against GORM/Hibernate trying to find an explanation for some bugs happening on production…😦 It is definitely not DRY. When working with associations, you must use item.delete() in conjuction to owner.removeFromItems(item) or you’ll have some hard-to-track bugs in you application. Or you must set some options in the mapping static variable for instructing Hibernate to delete the item when it is removed from the collection. But this is all non-intuitive.

Leave a Comment

Popunite niže tražene podatke ili kliknite na neku od ikona za prijavu:

WordPress.com Logo

Ovaj komentar pišete koristeći vaš WordPress.com račun. Odjava / Izmijeni )

Twitter picture

Ovaj komentar pišete koristeći vaš Twitter račun. Odjava / Izmijeni )

Facebook slika

Ovaj komentar pišete koristeći vaš Facebook račun. Odjava / Izmijeni )

Google+ photo

Ovaj komentar pišete koristeći vaš Google+ račun. Odjava / Izmijeni )

Spajanje na %s

%d bloggers like this: