Spring Roo 1.2 will be tipping point for RAD Java

by
Tags:
Category:

I’m going to make a bold statement: Spring Roo is about to do for Spring developers what Ruby on Rails did for Ruby developers – make developer agility, and not mechanical, rigid architectural structures, the focus of daily developer productivity.

There. I’ve said it. But I have to step back for a minute and disclaim a few things. First, as some of you may know I’ve been working with Spring and Spring-related projects for a while. I’m also the education director here at Chariot, and Spring has been a mainstay of many of our Java-based consulting projects and course materials – we’re also VMware Training Partner. Finally, I’m an author on Spring Roo in Action by Manning, which is undergoing the transformation from draft to publication by early 2012.

With the disclaimers aside, let’s dig into my treatise.  First, a bit about what, exactly, Roo is…

Roo in a nutshell

Roo is a developer productivity tool that uses a simple command-line shell to configure projects, install features, and create various objects such as JPA entities, controllers, services, repositories, and tests.  Conceptually, it is similar to Rails, Grails, or even JBoss Seam, in that you use it to bootstrap a project.

Unlike these other frameworks, which lean heavily on dynamically generated code, Roo is a compile-time framework – no “Roo Runtime” exists to interpret your code.  The shell adjusts your code and configuration, based on changes made to annotations in source code (either by the Roo shell, or by the developer).  Roo even generates setters, getters, JPA code, transaction logic, scaffolded controller views, and a lot more.

Here is a typical Roo JPA entity:

@RooJavaBean
@RooToString @RooActiveRecord
public class Employee { @Max(length = 20) private String firstName; @NotNull @Max(length = 30) private String lastName; }

You may be saying “where are the getters, setters, IDs, constructors?  Isn’t this just another strange “hide my code in some unaccessible place” framework?

Well, yes, and no.  It turns out that when you create this entity (via a set of Roo shell commands or just by saving it in the source directory structure), Roo generates some special files, known technically as Aspect-J Inter-Type Declarations, or informally as mix-ins.  These files contain the boilerplate methods, such as setters and getters, JPA code, the default primary keys and versioning, even a default toString() method.

You can use this entity directly from a controller or Spring bean:

Employee e = new Employee();
e.setFirstName("Joe");
e.setLastName("Smith");
e.persist();

As an aside, the @ActiveRecord annotation generated our persist() method. It also generated others, such as getEmployee(Long id), update(), and delete() to name a few… That’s the Active Record pattern at work.

Is that all it can do?

No, Roo isn’t just a persistence layer development tool.  Roo is also a development productivity platform.  Every feature in Roo is implemented as an add-on – there are pre-installed add-ons to set up Spring MVC, GWT, MongoDB, various JPA containers such as Hibernate, OpenJPA and EclipseLink, text searching with Solr, JMS with ActiveMQ, Email, Selenium integration tests, and a lot more.

The real power of Roo will come when developers begin embracing and writing their own add-ons.  Since they install in the shell itself, you can essentially provide pre-configured versions of the Roo environment for your developer team, and give them all the same, consistent productivity tools.

So, that’s Roo in a nutshell.  But here’s what I think is going to make the upcoming version a break-out tool for 2012.

Spring 3.x is dominant

For all the JavaOne bombast, let’s face it: a large number of developers are using Spring to get things done.  Why?  Because it simplifies every day development tasks.  Spring makes things [replace next word with your favorite explitive] stink less.  If you’ve ever needed to write JDBC code, you know the Roo Jdbc Template is a godsend.  Spring MVC has gotten so flexible and powerful that it’s trivial to expose RESTful web services and MVC forms.  And with projects like Spring Integration and Batch, both also open source efforts, you can wire in service-based architectures, messaging and batch operations without paying tens of thousands of dollars just for a single CPU license.

Spring projects are Open Source

Just like Ruby on Rails, Spring is an open source platform.  Even Spring Integration source code can be downloaded and reviewed.  Except a few sub-projects, such as the monitoring core of Spring tc Server, you can debug right into source on just about anything.  Spring Roo is yet another project by this team.  They put Roo on GitHub (github.com/springsource/spring-roo) and have a public JIRA and forum.

But Spring moves complexity to configuration, right?

Ah, good thinking.  If you’ve done anything with a significantly complex Spring application, you’ll see those configuration files, the setup of frameworks such as Spring MVC, Web Flow, JMS, and others, as tasks you’d rather not do.  Sure, Spring has evolved over the past decade – from just XML to annotation-driven bean definitions and auto-wiring, to the new JavaConfig feature, which allows you to specify configuration in Java classes.

This is the Spring adoption price of entry.  We’ve got to configure Spring to do what we want.  Inexperienced Spring developers have quite a time learning the ropes.  And the Java EE community, with tools like TomEE that do Java EE out of the box require zero configuration.

So, Java EE to the rescue?

Well, yes and no…  Java EE has evolved.  Now you can install a Java EE application into a web profile container and be off and running – without installing or downloading additional frameworks. However, I look at Java EE and Spring as two different philosophies – as alike and yet different as Nutella and Peanut Butter.  Bear with me here…

While Java EE is a standards-based platform, with input from a wide variety of organizations, it has consistently evolved, but at a slow pace.  Java EE is geared toward running on web and application servers, has specific component types, and vetted frameworks such as JPA, JSF, and the dependency injection of JSR-299.  Nutella.

However, Spring, since it evolves due to developer needs, actually can adapt every 12-18 months or earlier, adding features including the JSR-250 Spring annotations, not specifying a single ORM tool or vendor, and generally abstracting and simplifying a pluggable configuration strategy.  If you want to use JPA with Hibernate to start your project, then find the database is much too difficult to map, you can always switch to MyBATIS, NoSQL stores or even Spring JDBC without worry.

Likewise with web frameworks – you can start with Spring MVC, and if your team needs web workflow, give them Spring Web Flow, or if they want container-driven programming, install JSF on Web Flow or the ajaxy GWT.  Even Flex clients are easy to bolt on.

Peanut Butter.

Ok, I’m completely biased, that is true.  And there are others diametrically opposed to my viewpoint.  They say Spring is just too complex to configure, and is a “third party framework.” Roo’s goal is to get configuration tasks out of your way, and remove the boilerplate code so that you can focus on getting things done.  Just like any other RAD framework such as Grails, Rails, or Django, it automates the mundane.

Roo takes commands that can be bundled in a script file.  Here is a sample file that creates a voting application:

project --topLevelPackage com.springsource.vote
jpa setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT
 entity jpa --class ~.domain.Choice --testAutomatically
 field string namingChoice --notNull --sizeMin 1 --sizeMax 30
 field string description --sizeMax 80
 web mvc setup
 web mvc scaffold ~.web.ChoiceController
 entity jpa --class Vote --testAutomatically
 field reference choice --type Choice
 field string ip --notNull --sizeMin 7 --sizeMax 15
 field date registered --type java.util.Date --notNull --past
 web mvc scaffold ~.web.VoteController
 web mvc controller ~.web.PublicVoteController --preferredMapping /public
 web mvc language --code de
 web mvc language --code es
 logging setup --level WARN --package WEB
 security setup
 finder list --class ~.domain.Vote --depth 2 --filter reg,betw,IpEq
 logging setup --level INFO

What do we get by running this script?

  • A Spring MVC Web application
  • JPA based persistence, backed by the latest Hibernate API
  • Validation provided both server and client-side via the Java EE Bean Validation Framework and Dojo, respectively
  • Two entities, Choice and Vote, and backing form web pages for create, read, update, delete and list for each
  • Language support for both English and German
  • Spring Security

So, in short, quite a lot.  And Roo has over 30 commands built in, including embedding of content such as twitter and facebook feeds, exporting JSON data from controllers, and much more.  Things you’d need to spend a few hours to research now take literally minutes to install and test.

How does Roo separate the business code from the mundane?

Roo configures the project for you, as we discussed above, but it also builds business-level objects for each thing you create. Just to show you the correlation between the commands above and the objects they create, let’s look at the Vote entity and the VoteController MVC controller:

@RooJavaBean
@RooToString
@RooDisplayString
@RooJpaActiveRecord
public class Vote {
    @ManyToOne
    private Choice choice;
    @NotNull
    @Size(min = 7, max = 15)
    private String ip;
    @NotNull
    @Past
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date registered;
}

See how the Vote object doesn’t have setters, getters, constructors, equals methods, or anything else that can be mechanically generated? Unlike dynamic language frameworks, Roo generates actual Java-based AspectJ files to hold these artifacts, such as:

  • Vote_Roo_ToString.aj
  • Vote_Roo_JpaEntity.aj
  • Vote_Roo_DisplayString.aj

Here is VoteController.java:

@RequestMapping("/votes")
@Controller
@RooWebScaffold(path = "votes", formBackingObject = Vote.class)
public class VoteController {
}

Remember, Roo then generates the real code to manage all of the CRUD operations in an Aspect-J ITD file, VoteController_Roo_Controller.aj. It also scaffolds a set of views.

When you save this file, the Roo shell will rip the method out of the Aspect, so they won’t conflict. Easy, isn’t it?

You are in control

Ok, you decide, you want to change the behavior of the Roo controller or forms.  Maybe you want to go right back to the grid when you’re done.  Just pluck the method out of the ITD and put it into the class (it’s not literally that simple, you’ll have to convert the syntax, but close).

For example, you take the code from the controller aspect method:

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public java.lang.String VoteController.show(
                              @PathVariable("id") java.lang.Long id, 

Model uiModel) {
addDateTimeFormatPatterns(uiModel);
uiModel.addAttribute(“vote”, Vote.findVote(id));
uiModel.addAttribute(“itemId”, id);
return “votes/show”;
}

The syntax is slightly different; you have the class name prefixed to the method name, and spelled-out classes such as java.lang.String. However, with a little cleanup, you can paste this into your controller class, and modify the return value (changes bolded):

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String show(@PathVariable("id") Long id, Model uiModel) {
    addDateTimeFormatPatterns(uiModel);
    uiModel.addAttribute("vote", Vote.findVote(id));
    uiModel.addAttribute("itemId", id);
    return "votes/list";
}

And that’s it!  In general, you are in control of your Java classes, Roo is in control of the Aspects.  If you don’t like the code in the aspects, remove the annotation (which will remove the aspect file) or push in the methods you want to customize.

On the web side, each web framework has different things you can and can’t change.  In Spring MVC, Roo devised a set of high level tags such as containers for various actions (create, update, list) and component tags for dates, rich text and the like.  In Roo in Action I go into detail on how to customize these web pages, and even skip the scaffolding altogether and roll your own web or Ajax interface.

The Roo team listens

The Roo team is in contact with developers and is open to discussions about features.  I know I’ve contributed a number of JIRA issues that have become new features. In that way, the team is listening to the developers and acting in their interests – they recently added service-and-repository support, so that Roo developers don’t have to explain to their wincing staff architects that Roo works more magically, like a Rails application.  Now those teams will get the productivity Roo brings to the table.  Another big (upcoming) addition is multi-project (POM) support, so enterprise developers who have to deploy EARS or separate projects into multiple POMs can benefit as well.

The add-on API is powerful

One of the issues with writing Roo add-ons was the stability of the add-on code.  Each release broke the code of the prior release.  The changes I’m seeing with Roo 1.2 seem to be focused on making the add-on API more useful and perhaps more stable.  I hope the team will provide easy upgrade paths, including deprecating rather than removing and renaming classes, with follow-on releases. What can you do with an add-on?  Well, pretty much anything.  For example:

  • You can manipulate files such as Spring configurations, POM files, servlet.xml, etc, thereby making it easier for them to work with a given API by setting it up for them.
  • You can use a built-in type parser system to generate and update the annotations and code attached to Java types (classes), thereby activating your add-on’s class watcher (which can generate boilerplate code in your own Aspect-J ITDs).  
  • You can add commands to the Roo shell, and specify a method for each command to determine whether it should be exposed (why expose web-based commands when you haven’t set up your web engine yet, for example).
  • You can gain access to the OSGi console and stop/start other bundles, or detect if bundles are installed.

Roo is NOT a Runtime Platform

Remember, for all of the smartness involved in assembling features for the Roo shell, it’s a compile-time platform that uses Aspect-J to weave code into classes at compile-time, not run-time.  With SpringSource Tool Suite or IntelliJ IDEA, you can set breakpoints in Aspect-J ITDs, and debug your application in every line of code, even if generated by Roo.  Since everything is compile-time, the platform is capable of being faster than typical dynamic language platforms (someone ought to run a benchmark!).

Important features coming in Roo 1.2

Up until this point in time, the goal of the Roo team has been to stabilize the Roo platform and add-on system.  They’ve added things like a public add-on registry, support for publishing your own company-level add-ons via the OSGi OBR (OSGi Bundle Repository) protocol, and improving overall shell features and performance. So, what is on deck for Roo 1.2?  Here are some highlights:

  • JSF support – including automatic scaffolding of JSF pages for models you specify.  The JSF module seems to be using PrimeFaces at this time.
  • Multi-POM support – a big improvement – will contain the ability to specify POM projects, and WAR, JAR projects.  An example already exists in the GitHub project page – look for multimodule.roo and see the commands to set up your own web and repository project.
  • Support for Spring Data APIs, which simplify CRUD-based application writing by providing (wait for it) proxy-based, generated methods using an interface you provide.  This is an extremely powerful API.
  • Support for NoSQL databases.  The MongoDB database is included in the first milestone snapshot.
  • Support for Spring services – these are automatically marked transactional and delegate either to Roo entity methods, or if repositories exist, delegate to the repository backing an entity.
  • Ability to switch between service-and-repository or Active-Record implementations of your persistence model just by switching annotations on the JPA entity.

As with other versions, pre-release upgrades may be a bit tricky – we will have to see whether Roo can upgrade a project in place.  The Roo documentation provides help once a version is released.

Resources