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

Entries in Spring Framework (2)

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.

Wednesday
Oct082008

Updated SpringSource Distribution Policy

Note: I'm updating this article's title. Rod had noted it's not a licensing change, rather a distribution change. I made the change to my post text, but not the URL or the article title.

Read the updated SpringSource distribution decision on Rod Johnson's Blog Page. This is a change to a recent policy decision by SpringSource to provide updates for 3 months after a new major/minor release.

The change provides for releases of builds to the open source community until a new major/minor version is delivered. For example, the current 2.5.5 release would be revved to 2.5.6 (based on Rod's information) and once a 3.0 release is provided, the 2.5.x line would be provided but not updated (unless your organization is a SpringSource licensee under support contract).

This is a fair agreement, as open source teams can now continue building applications based on Spring and decide when they are ready to update to a newer version of the software, without worrying about purchasing support. Concordant with this change are upcoming licensing models for small business and systems integrators.