Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

« SpringSource Roo 1.0.0.M2 released, great blog post by Ben Alex on internals... | Main | Gettin' all Testy - The Spring TestContext, Hibernate, and you... »
Friday
Jun122009

SpringSource Roo - What is it?

Overview

I just did a talk with our development team at Chariot on SpringSource's latest application platform builder, Roo. As with most new projects, I approached it with some skepticism--why do we need another convention over configuration framework?  Re: Spring, I was happy working in Grails! After spending a couple of days with it, I now realize that it was a very smart move to create this project.  This series of posts will outline what I'm learning, and hopefully will get you off to a good start in your own experiments.

Much of what I'm saying was written up very well by Ben Alex himself in this blog post. I suggest reading his post as well.

They're using Maven?

Roo is headed up by Ben Alex, and it was refreshing to see that his approach is centered around using Maven as the build system.  Essentially, the roo platform gives you a command line (named, aptly, 'roo'), which lets you issue commands to build and modify your platform.

For example, to build a new project, you issue:

roo> create project -topLevelPackage com.chariot.demo.roodemo

This builds a new Maven project. Under the covers, the team has installed the following features:

  • Spring Framework 3.0.0 beta
  • Spring MVC, annotation driven
  • A Web application plus the mvc context
  • Spring context loaders in web.xml
  • Jetty and Tomcat runner support
  • Eclipse and SpringSource Tool Suite project natures, including ADJT, Spring, STS

JPA Support

This is a fully functional application from the get-go. What's more, you can add features to the project easily. Since it's a convention-over-configuration, domain-driven application platform, let's create a JPA domain class. First, we have to install JPA:

roo> install jpa -provider HIBERNATE -database MYSQL

This installs JPA support. You could also pick ECLIPSELINK or OpenJPA as providers. The Maven build is configured to add the relevant libraries, and the applicationContext.xml file reflects the installation of JPA as a platform. In addition, roo sets up the transaction management platform, including annotation-driven transactions, and gives you a database.properties file.

One thing to note: right now Roo gives you a DriverManagerDataSource, which doesn't do connection pooling, but you are free to modify that and add the relevant support for DBCP or C3P0 instead. In fact, roo has an "add dependency" command to add Maven Artifacts, if you'd like to use their command line.

Creating a JPA Domain Object

Normally Spring developers are used to building JPA entities, wrapping them with Repository objects, and then coordinating access to these data layer repositories with Service-level beans. Ben and his team seem to have realized that one of the key features of Grails is GORM, a domain-driven object relational modeling system. In GORM, you can define and add constraints to an object, and have it persist itself.

The clever way that the Roo team solved this challenge was to add special annotations and some AOP magic to weave in validation and persistence code using Aspects. For example, if I define a simple JPA bean using 'new persistent class jpa' and edit it like this:


// the roo command to generate the class skeleton:
roo> new persistent class jpa -name Conference

// (without imports) the code:
@Entity
@RooEntity
@RooJavaBean
@RooPlural("conferences")
@RooToString
public class Conference {
@Column(nullable=false)
@Size(min = 5, max = 30,
message = "Please enter a name between {min}
and {max} characters.")
private String name;

@Size(min = 10, max=512,
message = "{description.required}")
private String description;

@Temporal(TemporalType.TIMESTAMP)
@Column(insertable=true, updatable=false)
@NotNull
private Date created;
}

You are getting the following functionality:

  • You get an id and version column automatically by default
  • You can use JSR-303 annotations like @NotNull, @Size, and others. These will modify the UI pages and generate error messages using Spring MVC's errors object.
  • Roo will automatically generate getters and setters and helper methods for your domain objects, and do it by watching your @Entity classes and sensing that they are changed
  • Hint:  If you place a ValidationMessages.properties file in the root of the src/main/resources directory you can externalize the error messages as in the {description.required} message above.  Roo doesn't look for these in the MessageSources as this is a JSR-303 spec requirement.

Roo will also write persistence mechanisms and attach them to the Entity's class. For example, you get:

  • persist() - saves your entity for the first time
  • remove() - deletes the entity
  • findAllConferences() - does a jpa entity manager query to get the all conferences
  • findConferenceById() - does a get by the primary key
  • flush() - flushes to the persistent storage mechanism (Hibernate in this case)
  • countAllConferences() - does a select count(*) query to count the rows

How does it do that?

How Roo does that ;-)

(Ok, I couldn't resist.) Here's how it works: Roo uses AspectJ to install .aj files to shadow all of the key objects (Domain Classes, Controllers, etc). It also installs certain AOP features that look for key annotations such as @RooEntity and @RooJavaBean to generate and synchronize those .aj files.

The Conference file generates (as of today) the following AJ files:

  • Conference_Roo_Entity.aj - wires in the id and version fields, as well as flush(), merge(), countConferences(), findAllConferences(), findConference() and findConferenceEntries()
  • Conference_Roo_JavaBean.aj - generates getters and setters for fields in the domain class
  • Conference_Roo_Plural.aj - looks like it determines how to ask for multiples of the object. So, for example, Entity would be defaulted to Entitys. Apparently there is an @RooPlural annotation that lets you modify what gets generated here.
  • Conference_Roo_ToString.aj - automatically creates an Apache ToStringBuilder on the fields including the id and version. Nice touch.
  • Conference_Roo_Configurable.aj - adds the @Configurable annotation to the entity. This is where my spring-fu needs a little dusting off ;)

So, now roo can issue calls to the Conference object as if it is a domain class.  

Update, I was attempting to do this in IntelliJ Maia within a controller, and I couldn't issue the code. It looks like if you want to edit the code yourself you need to further configure Maia and on Eclipse you really need SpringSource Tool Suite with the Roo plugin.  I'm testing this with the 2.1.0.M2 release of STS.  

Conference c = Conference.findConference(2L);
c.setName("BasketWeaving 101");
c.update();

The Story So Far...

So, in a few steps, we've created a project and configured it with JPA, then written a fully domain-driven database model object that can be persisted using this platform. If it wasn't obvious, I keep a roo command line open all the time, run SpringSource Tool Suite (or IntelliJ Idea Maia beta, which has support for Aspects), and run the app using 'mvn jetty:run' or 'mvn tomcat:run'. That's pretty nifty.

IDE Support

To use Roo under STS / Eclipse, just use 'mvn eclipse:eclipse' and import the existing project into your workspace. To use it under Idea, you'll have to download the Maia beta (it works pretty well and can view aspect files without screwing up your project). I've also tested this from NetBeans and it opened and let me view the aspects as text files. You should NOT edit the .aj files directly, as they are re-generated and you'll lose code.

One word of warning: On STS / Eclipse, you'll have to refresh the project if you add support for any feature that updates the maven pom. To build the eclipse project, do 'mvn eclipse:eclipse' and then go and refresh (F5) the project tree. Also, I've seen where I have to manually referesh contents of files because Eclipse doesn't watch them very well. IntelliJ or NetBeans 6.7 RC2 do fine re-reading the POM automatically.

Why not Groovy/Grails?

That's a good question.  Rod/Ben answered this somewhere in the blog post comments with the comment that many Spring developers can't or won't move to Groovy and/or another persistence framework like GORM.  If your company insists on doing Spring development in Java, or wants you to use the Spring APIs directly rather than wrap them in something like Grails, this is a great alternative.  Also, I can't think of a better way to kick the tires of features like Spring Security, JMS Templating, Spring IoC 3.0, Bean Validation annotations, JPA, and others from within Spring itself.

I'm still a huge Groovy on Grails fan, and see this as one of two ways to build applications on top of the Spring core.  The fact that regular Spring developers can take advantage of domain-driven application persistence is a huge bonus for our industry.

Early Days

This product still has a way to go, and was released as a milestone build recently (1.0.0.M1).  I've asked questions in the forum and posted JIRA issues, and the team has been absolutely responsive.  They will take your input and are welcoming contributors.

Resources

Coming up...

Over the next series of posts, I'll dig deeper into the JPA configuration, talk about scripting roo, outline the web framework, and show you how you can use Roo to automatically scaffold your web application and interact with the domain-driven Entities, using annotations and aspects.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (3)

Hi Ken,

Great post! I am looking forward to the follow-ups :).

As for the STS / Eclipse project refresh - you can set this up in the preferences -> general -> workspaces -> refresh automatically.

Hope this makes your life a little easier.

Cheers,
Stefan

June 12, 2009 | Unregistered CommenterStefan Schmidt

Thanks Stefan! You've been very responsive to JIRA and forum questions. The eclipse refresh tip is good to know.

June 12, 2009 | Registered CommenterKen Rimple

As for the question regarding "Why not Groovy/Grails?" I can only recommend watching Rod Johnson's SpringOne keynote (currently available at InfoQ).

During the presentation he points out that the long-term roadmap will include Groovy/Grails support even in Roo. In addition he states that the current starting point with Roo and the generates Spring 3 best practice code shall enable Java programmers to become more productive instead of having to write all the 'boilerplate code' for setting up a new project, installing a JPA provider, configuring entities and the likes. This is what currently distinguishes Java from RAD platforms like Grails and is one of its deficiencies which shall be addressed by Roo.

Cheers,
Axel

June 13, 2009 | Unregistered CommenterAxel Knauf

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>