Getting Groovy with Seam after TSSJS

Date April 1, 2008

TSSJS was a great conference this year. Neal Ford, well-known author and ThoughtWorker, initiated the conference by delivering an inspiring keynote address discussing dynamic languages, DSLs (Domain-specific languages), and their role in the evolution of software development. Matt Raible blogged about the presentation and you can find a brief summary here. Polyglot programming became a theme of the conference with Ted Neward delivering yet another inspiring keynote encouraging developers to create their own language.

Building on this inspiration, Scott Davis discussed taking the Groovy Red Pill. Well, you would be happy to know I have taken the Red Pill, but of course with a Seam twist. I have been working on a time-tracking application (for my company’s internal use) utilizing Seam and Groovy that I will release as a freely available example. Groovy and Seam integration will be discussed in-depth in JBoss Seam 2E, but let’s look at the Groovy way to initialize a Timesheet:

@Entity
class GroovyTimesheet
{
  @Id @GeneratedValue
  Long id;

  @OneToMany
  @JoinColumn(name="TIMESHEET_ID")
  List<GroovyTimeEntry> entries = new ArrayList<GroovyTimeEntry>();

  GroovyTimesheet(PayPeriod payPeriod, int month, int year)
  {
    (payPeriod.getStartDate(month, year)..
      payPeriod.getEndDate(month, year)).each
    {
      entries << new GroovyTimeEntry(hours:0, date:it);
    }
  }

  // ... ...
}

So what is going on here? Essentially we define a range of dates that are iterated over. The PayPeriod is a fairly simple enum that determines the start and end dates of a pay period. By specifying (startDate..endDate) we define a range. Groovy understands the meaning of a range of dates allowing us to express this in a very concise manner (try expressing this in Java and you’ll get the picture). In addition, we use the each operation on this range. The each operation allows us to define a closure that executes as Groovy loops through our range of dates a day at a time. This allows us to initialize each GroovyTimeEntry instance for the pay period.

You will also note use of the << operator (or the leftShift operator). This operator is defined for a List allowing us to add elements to the list through this syntactic sugar. The GroovyTimeEntry instance is initialized using the default construction approach. By default, named constructor parameters can be specified in any order to initialize an object instance. If you define a constructor this is no longer provided by default. Finally, you will notice the use of the keyword it in the closure we defined for the each operation. The keyword it provides the value of the current element in the iteration. So in our instance, as we loop through the date range, each date will be provided iteratively in the range.

@Entity
class GroovyTimeEntry {
  @Id @GeneratedValue
  Long id;

  BigDecimal hours;
  Date date;
}

Wow, is that all the code? Looks pretty nice doesn’t it. As mentioned, the default constructor allows us to specify named parameters. In addition, getters and setters are automatically provided for each of our attributes.

You’ve probably noticed the use of JPA annotations here. This is perfectly legal and your groovy class will be a JPA entity. The same is true for Seam components annotated with @Name. So how does this work? Groovy classes are compiled to Java bytecode under the covers so JEE and Seam features are fully available to your Groovy classes at runtime. Simply use the groovyc compiler that can be accessed here or include the groovyc Ant task into your build. This will be covered in-depth in JBoss Seam 2E.

So what if we want to add GroovyTimeEntry instances to the GroovyTimesheet instance programmatically? The following code implements this:

@Entity
class GroovyTimesheet
{
  // ... ...

  void leftShift(GroovyTimeEntry entry)
  {
    entries << entry;
  }

  // ... ...
}

As mentioned, the leftShift operator is provided by Groovy and can be overloaded within your custom implementations. By defining a custom leftShift implementation we are now able to add a GroovyTimeEntry instance through the following:

// ... ...
timesheet << new GroovyTimeEntry(new Date());
// ... ...

Operator overloading isn’t limited to the leftShift operation. We can also overload other operators such as +:

// ... ...
BigDecimal plus(GroovyTimeEntry entry)
{
  this.hours + entry.hours;
}
// ... ...

This allows us to add the hours of two GroovyTimeEntry instances using the simple + operator. Notice that a return is not specified. This is optional as the last line is assumed to be a return statement.

As mentioned, a complete time-tracking application will be provided that not only demonstrates Groovy entities but also Groovy Seam components. In addition, the time-tracking application will make use of the ExpandoMetaClass to extend final Java classes at run-time! The code for the application is in development and will be made available through Google code. Also, stay tuned for JBoss Seam 2E which will provide the intimate details of Groovy and Seam integration. So take the Red Pill and use the meta-programming features of Groovy in your own Seam applications!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

9 Responses to “Getting Groovy with Seam after TSSJS”

  1. Markus Jais said:

    Very interesting stuff. Seam is already quite interesting. Using Groovy with it might make it even more productive.

    Two questions:
    Did you make any performance tests compared to a Java solution?
    Do you know if there are plans to integrate Groovy support in the JBoss Tools for Eclipse?

    Looking forward to the 2nd edition of the book. The first one was great to give me an overview of Seam.

  2. jacob.orshalick said:

    Did you make any performance tests compared to a Java solution?

    No, I have not as the solution is only implemented in Groovy. There would be a difference, I’m sure, but for most applications this shouldn’t be a problem. If you would like to get a comparison, the Seam Booking example has been implemented as a basic Java solution and a Groovy solution. You can find each in the Seam distribution. Feel free to run performance tests and report back your results. I’m sure many readers would be interested!

    Do you know if there are plans to integrate Groovy support in the JBoss Tools for Eclipse?

    There are not that I am aware of, but the Groovy plugin works nicely with JBoss Tools and is what I have been using for development. There are some issues with the Groovy plugin but it has come a long way ;)

  3. Srinivasan Raguraman said:

    Quite interesting, Yeah, implementing domain models using groovy’s additional constructs will be elegant.

  4. Chris said:

    There would be a difference, I’m sure, but for most applications this shouldn’t be a problem.

    The standard wisdom from the Groovy camp is when performance becomes a huge issue dropping down into Java is the solution. Since Groovy has numerous ways of seamlessly (pun intended) integrating with Java it shouldn’t be a problem in most cases to do just that.

    On a side note Groovy 1.5.5 was just announced with a host of performance improvements.

  5. Pawel Kaczor said:

    There are not that I am aware of, but the Groovy plugin works nicely with JBoss Tools and is what I have been using for development. There are some issues with the Groovy plugin but it has come a long way

    Could you show me your configuration of groovy plugin and jboss-tools? Is hot deployment working for groovy classes? I’ve created groovy componente annotated with @Name but it is not loaded by seam…

  6. yourbestfriend said:

    Jacob,

    Excellent overview and article, my friend. A few points to point out:

    1. The latest Groovy 1.5 version allows use of annotations but yet does not support definition of custom annotations. I hope to see that feature soon in a future version of Groovy.

    2. By default, all Groovy closures have an implicit it parameter if the closure parameters were not declared. However, you can add multiple parameters by separating them with commas.

    3. Groovy has a 1:1 mapping between an operator (+, -, *..) to an operator method. For example, by overriding plus function in a Groovy class, you are overriding the + operator for your class.

    4. Range data types can handle both forward ranges (min…max type) or reverse ranges (max..min).

    On the plugin/jboss-tools question: Groovy plugin has to be configured separately from JBoss Tools plugin. Groovy Eclipse plugin is fully functional and supports all groovy features including syntax coloring, highlighting, debugging of Groovy files within Eclipse. Groovy Plugin works with eclipse 3.2 but you need a minimum of Eclipse 3.3 to get JBoss Tools to work.

  7. Dan Allen said:

    In this posting, you make that statement that the annotations work because Groovy is being compiled (even if you didn’t mean it that way). Groovy definitely does not have to be compiled using groovyc to use it in a Java application. Seam has a Groovy classloader that can read straight from the .groovy files. Personally, I think you lose some of the benefit of Groovy if you have to compile it (until you go to production, that is).

    I really like the idea of using Groovy, but I don’t really see the benefit of creating entity classes using Groovy. Entity classes get developed once and then remain stable for a vast majority of the application’s lifetime. Given how many times they are created during a given session, I just don’t think it is worth the performance hit. In prototyping, absolutely, but not in anything that is going to stick around for a while. Now for the business logic, you would be crazy not to use Groovy.

    Groovy opens a lot of doors in terms of improving productivity and it could very well be what Java needed to avoid a complete takeover from the non-JVM dynamic language world. Once the support for Groovy comes out of the box in all the major IDEs, I will definitely use it on the next project I find myself thrown into. From what I have read (and some personal experience), the IDE plugin for Eclipse is just not there yet. My guess is that IntelliJ will beat everyone to the ball on this, with NetBeans and Eclipse duking it out for second place a year later. You can judge Groovy’s acceptance by the fact that developers don’t have to *add* a plugin.

  8. jacob.orshalick said:

    Hi Dan,

    Good to hear from you.

    Groovy definitely does not have to be compiled using groovyc to use it in a Java application. Seam has a Groovy classloader that can read straight from the .groovy files. Personally, I think you lose some of the benefit of Groovy if you have to compile it (until you go to production, that is).

    Yes you are absolutely right. This is a great feature for development, but as you state, compilation must occur prior to going to production to avoid some serious performance penalties. There is already so much FUD out there about performance concerns with Groovy I try not to fuel the fire :) Thanks for the comment though, as I’m sure others will find it useful to have this mentioned with the post! It will certainly be discussed in the book.

    I really like the idea of using Groovy, but I don’t really see the benefit of creating entity classes using Groovy. Entity classes get developed once and then remain stable for a vast majority of the application’s lifetime […] Now for the business logic, you would be crazy not to use Groovy.

    Hmmm… I suppose this depends on your view of a domain model. In my eyes, a domain model (entities) is where the business logic belongs, see the Eric Evans classic Domain-Driven Design. Therefore, Groovy is a *great* choice for the domain model! There are certainly performance considerations involved at the moment but as Groovy progresses as a technology (as Java did), these concerns will continue to diminish.

    From what I have read (and some personal experience), the IDE plugin for Eclipse is just not there yet.

    I have tried to be positive about the plugin for Eclipse, but you are absolutely right here… it needs a lot of work. IntelliJ is great, and developers rave about it’s Groovy support, but the fact of the matter is until the Eclipse plugin becomes a viable option, Groovy is going to have difficulty in the enterprise arena.

    Thanks again for the comment and good luck with your book! If you are ever in the DFW area, let me know, and we can get together for a beer or two :)

    Jacob

  9. Chris said:

    Groovy definitely does not have to be compiled using groovyc to use it in a Java application. Seam has a Groovy classloader that can read straight from the .groovy files.

    This works just fine as long as the .groovy classes only point pack at Java classes. If you mix the reference directions between Groovy and Java then you are going to have to compile the Groovy files into classes. Keeping the separation between Groovy and Java unidirectional can get tricky in non-trival applications. Also, deciding on compile or not to compile will affect how you are able to unit test the code too.

    Entity classes get developed once and then remain stable for a vast majority of the application’s lifetime….

    Seriously? In the agile software development processes I’ve been involved in this statement is simply wrong. Teams don’t (and shouldn’t) code everything they can think of into Customer in month two of the year long project. Now if you’re referencing the domain of most applications written as book examples I totally agree….

    From what I have read (and some personal experience), the IDE plugin for Eclipse is just not there yet.

    Yeah, the Eclipse plugin is crap. The NetBeans Groovy plugin should re-appear in NB 6.5 (you can pull it out of the dev branches for NB currently). But, like you rightly stated the IntelliJ plugin for Groovy is far and away ahead of the pack right now.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>