Spring Roo - Reference Documentation
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT
Copyright 2009, 2010, 2011 VMware, Inc. All Rights Reserved. Copies of this document may be made for
your own use and for distribution to others, provided that you do not charge any fee for such copies and
further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Preface .... ix
I. Welcome to Spring Roo .... 1
1. Introduction .... 2
1.1. What is Roo? .... 2
1.2. Why Use It .... 3
1.2.1. Higher Productivity .... 3
1.2.2. Stock-Standard Java .... 3
1.2.3. Usable and Learnable .... 4
1.2.4. No Engineering Trade-Offs .... 5
1.2.5. Easy Roo Removal .... 6
1.3. Installation .... 6
1.4. Optional ROO_OPTS Configuration .... 8
1.5. First Steps: Your Own Web App in Under 10 Minutes .... 8
1.6. Exploring the Roo Samples .... 10
1.7. Suggested Steps to Roo Productivity .... 11
2. Beginning With Roo: The Tutorial .... 12
2.1. What You'll Learn .... 12
2.2. Alternative Tutorial: The Wedding RSVP Application .... 12
2.3. Tutorial Application Details .... 13
2.4. Step 1: Starting a Typical Project .... 13
2.5. Step 2: Creating Entities and Fields .... 15
2.6. Step 3: Integration Tests .... 18
2.7. Step 4: Using Your IDE .... 18
2.8. Step 5: Creating A Web Tier .... 20
2.9. Step 6: Loading the Web Server .... 20
2.10. Securing the Application .... 21
2.11. Customizing the Look & Feel of the Web UI .... 23
2.12. Selenium Tests .... 24
2.13. Backups and Deployment .... 24
2.14. Where To Next .... 25
3. Application Architecture .... 26
3.1. Architectural Overview .... 26
3.2. Critical Technologies .... 26
3.2.1. AspectJ .... 26
3.2.2. Spring .... 29
3.3. Entity Layer .... 30
3.4. Web Layer .... 31
3.5. Optional Services Layer .... 32
3.6. Goodbye DAOs .... 32
4. Usage and Conventions .... 35
4.1. Usability Philosophy .... 35
4.2. Shell Features .... 36
4.3. IDE Usage .... 38
4.4. Build System Usage .... 39
4.5. File System Conventions .... 40
4.6. Add-On Installation and Removal .... 40
4.7. Recommended Practices .... 40
4.8. Managing Roo Add-Ons .... 41
5. Existing Building Blocks .... 46
1.1.3.BUILD-SNAPSHOT ii
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT iii
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT iv
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT v
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT vi
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT vii
Spring Roo - Reference Documentation
1.1.3.BUILD-SNAPSHOT viii
Preface
I still recall the moment when I realised that I would like to program. The motivation for me was
recognition that creativity with software is mostly constrained by your imagination and skills, whereas
creativity outside the software world is typically constrained by whatever physical items you happen
to possess. Of course at that early stage I hadn't yet come across the subtle constraints in my optimistic
assessment of software (such as CPU capabilities, memory, CAP theory etc!), but the key principle
that software was almost boundlessly flexible sparked an interest that continues to this day.
Of course, the creativity potential of software implies an abundance of time, as it is time that is the
principal ingredient in building and maintaining software. Ever since the "castle clock" in 1206 we
have been exploring better ways of programming ever-increasingly sophisticated computers, and the
last decade in particular has seen a surge in new languages and techniques for doing so.
Despite this 800 year history of programming, software projects are no different from other projects in
that they are still bound by the project management triangle: "cost, scope or schedule: pick any two".
Professional software developers grapple with this reality every day, constantly striving for new tools
and techniques that might help them deliver quality software more quickly.
While initial delivery remains the key priority for most software projects, the long-term operational
dimensions of that software are even more critical. The criticality of these operational dimensions
is easily understood given that most software needs to be executed, managed, maintained and
enhanced for many years into the future. Architectural standards are therefore established to help
ensure that software is of high quality and preferably based on well-understood, vendor-agnostic and
standards-based mainstream engineering approaches.
There is of course a natural tension between the visibility of initial delivery and the conservatism
typically embodied in architectural standards. Innovative new approaches often result in greater
productivity and in turn faster project delivery, whereas architectural standards tend to restrict these
new approaches. Furthermore, there is a social dimension in that most developers focus their time on
acquiring knowledge, skills and experience with those technologies that will realistically be used, and
this in turn further cements the dominance of those technologies in architectural standards.
It was within this historical and present-day context that we set out to build something that would offer
both genuine innovation and architectural desirability. We sought to build something that would deliver
compelling developer productivity without compromising on engineering integrity or discarding
mainstream existing technologies that benefit from architectural standards approval, excellent tooling
and a massive pool of existing developer knowledge, skills and experience.
Spring Roo is the modern-day answer to enterprise Java productivity. It's the normal Java platform
you know, but with productivity levels you're unlikely to have experienced before (at least on Java!).
It's simple to understand and easy to learn. Best of all, you can use Roo without needing to seek
architectural approval, as the resulting applications use nothing but the mainstream Java technologies
you already use. Plus all your existing Java knowledge, skills and experience are directly applicable
when using Roo, and applications built with Roo enjoy zero CPU or memory overhead at runtime.
Thank you for taking the time to explore Spring Roo. We hope that you enjoy using Roo as much as
we've enjoyed creating it.
1.1.3.BUILD-SNAPSHOT ix
Part I. Welcome to Spring Roo
Welcome to Spring Roo! In this part of the reference guide we will explore everything you need to know in order
to use Roo effectively. We've designed this part so that you can read each chapter consecutively and stop at any
time. However, the more you read, the more you'll learn and the easier you'll find it to work with Roo.
Parts II, III and IV of this manual are more designed for reference usage and people who wish to extend Roo itself.
1.1.3.BUILD-SNAPSHOT 1
Chapter 1. Introduction
1.1. What is Roo?
Spring Roo is an easy-to-use productivity tool for rapidly building enterprise applications in the Java
programming language. It allows you to build high-quality, high-performance, lock-in-free enterprise
applications in just minutes. Best of all, Roo works alongside your existing Java knowledge, skills and
experience. You probably won't need to learn anything new to use Roo, as there's no new language or
runtime platform needed. You simply program in your normal Java way and Roo just works, sitting
in the background taking care of the things you don't want to worry about. It's an approach unlike
anything you've ever seen before, we guarantee it!
You work with Roo by loading its "shell" in a window and leaving it running. You can interact with Roo
via commands typed into the shell if you like, but most of the time you'll just go about programming
in your text editor or IDE as usual. As you make changes to your project, Roo intelligently determines
what you're trying to do and takes care of doing it for you automatically. This usually involves
automatically detecting file system changes you've made and then maintaining files in response. We
say "maintaining files" because Roo is fully round-trip aware. This means you can change any code
you like, at any time and without telling Roo about it, yet Roo will intelligently and automatically
deal with whatever changes need to be made in response. It might sound magical, but it isn't. This
documentation will clearly explain how Roo works and you'll find yourself loving the approach - just
like so the many other people who are already using Roo.
Before you start wondering how Roo works, let's confirm a few things it is NOT:
• Roo is not a runtime. Roo is not involved with your project when it runs in production. You won't
find any Roo JARs in your runtime classpath or Roo annotations compiled into your classes. This is
actually a wonderful thing. It means you have no lock-in to worry about (you can remove Roo from
your project in just a couple of minutes!). It probably also means you won't need to get approval to
use Roo (what's to approve when it's more like a command line tool than a critical runtime library
like Spring Framework?). It also means there is no technical way possible for Roo to slow your
project down at runtime, waste memory or bloat your deployment artefacts with JARs. We're really
proud of the fact that Roo imposes no engineering trade-offs, as it was one of our central design
objectives.
• Roo is not an IDE plugin. There is no requirement for a "Roo Eclipse plugin" or "Roo IntelliJ plugin".
Roo works perfectly fine in its own operating system command window. It sits there and monitors
your file system, intelligently and incrementally responding to changes as appropriate. This means
you're perfectly able to use vi or emacs if you'd like (Roo doesn't mind how your project files get
changed).
• Roo is not an annotation processing library. There is a Java 6 feature known as the annotation
processing API. Roo does not use this API. This allows Roo to work with Java 5, and also gives us
access to a much more sophisticated and extensible internal model.
So how does Roo actually work then? The answer to that question depends on how much detail you'd
like. In super-summary form, Roo uses an add-on based architecture that performs a combination of
passive and active code generation of inter-type declarations. If you're interested in how that works at a
practical project level, we cover that shortly in the "Beginning With Roo: The Tutorial" chapter. Or for
an advanced look at Roo internals, we've covered that in Part III: Internals and Add-On Development.
1.1.3.BUILD-SNAPSHOT 2
Introduction
Anyone who has programmed Java for a few years and looked at the alternatives on other platforms
will be fully aware that enterprise Java suffers from productivity problems. It takes days to start a new
project and incredibly long cycle times as you go about normal development. Still, we remain with
Java because it's a highly attractive platform. It's the most widely used programming language on the
planet, with millions of competent developers. It has first-class tooling, excellent runtime performance,
numerous mature libraries and widely-supported standards. Java is also open source, has multiple
vendors and countless choice.
We built Roo because we want enterprise Java developers to enjoy the same productivity levels that
developers on other platforms take for granted. Thanks to Roo, Java developers can now enjoy this
higher productivity plus a highly efficient, popular, scalable, open, reliable platform. Best of all, in five
years time it will still be possible to hire millions of people who can look at those Roo-based projects
and understand what is going on and maintain them (even if you've stopped using Roo by then).
Roo's higher productivity is provided both at original project creation, and also as a developer builds
out the rest of the project. Because Roo provides round-trip support, the higher productivity is
automatically provided over the full lifespan of a project. This is particularly important given the
long-term maintenance costs of a project far outweigh the initial development costs. While you can
use Roo just for an initial jump-start if you so wish, your return on investment is exponential as you
continue using it throughout a project lifespan.
Finally, while individual productivity is important, most of us work in teams and know that someday
someone else will probably maintain the code we've written. As professionals we follow architectural
standards and conventions to try and ensure that our present and future colleagues will be able to
understand what we did, why, and have an easy time maintaining it. Our organisations often establish
standards for us to follow in an effort to ensure other projects are tackled in similar ways, thus
allowing people to transfer between projects and still be productive. Of course, most organisations also
have people of greatly differing backgrounds and experiences, with new graduates typically working
alongside more experienced developers and architect-level experts. Roo helps significantly in this
type of real-world environment because it automatically implements specific design patterns in an
optimal convention-over-configuration manner. This ensures consistency of implementation within a
given Roo-based project, as well as across all other Roo-based projects within an organisation (and
even outside your organisation, which greatly helps with hiring). Of course, the fact Roo builds on
stock-standard Java also means people of vastly different experience levels can all be highly productive
and successful with Roo.
1.1.3.BUILD-SNAPSHOT 3
Introduction
would feel right at home. If you've ever built an enterprise application with Java, some or all of the
technologies that Roo uses by default will already be familiar to you.
Some of the common technologies Roo projects use include Spring (such as Spring Framework, Spring
Security and Spring Web Flow), Maven, Java Server Pages (JSP), Java Persistence API (JPA, such
as Hibernate), Tiles and AspectJ. We've chosen technologies which are extremely commonly used in
enterprise Java projects, ensuring you've probably either already used them or at least will have no
difficulty finding hundreds of thousands of other people who have (and the resultant books, blogs,
samples etc that exist for each). Also, because most of these technologies are implemented using
add-ons, if you'd like Roo to use a different technology on your project it's quite easy to do so.
By using standard Java technologies, Roo avoids reinventing the wheel or providing a limited-value
abstraction over them. The technologies are available to you in their normal form, and you can use
them in the same way as you always have. What Roo brings to the table is automatic setup of those
technologies into a SpringSource-certified best-practice application architecture and, if you wish,
automatic maintenance of all files required by those technologies (such as XML, JSP, Java etc). You'll
see this in action when you complete the ten minute test.
You'll also find that Roo adopts a very conservative, incremental approach to adding technologies to
your project. This means when you first start a new project Roo will only assume you want to build
a simple JAR. As such it will have next to no dependencies. Only when you ask to add a persistence
provider will JPA be installed, and only when you add a field using JavaBean Validation annotations
will that library be installed. The same holds true for Spring Security, Spring Web Flow and the other
technologies Roo supports. With Roo you really do smart small and incrementally add technologies
if and when you want to, which is consistent with Roo's philosophy of there being no engineering
trade-offs.
With Roo we took these ideas to heart and designed a highly usable interface that lets you follow your
locus of attention. This means you can do things in whatever order you feel is appropriate and never
be subservient to the Roo tool. You want to delete a file? Just do it. You want to edit a file? Just do it.
You want to change the version of Spring you're using? Just do it. You want to remove Roo? Just do it.
You want to hand-write some code Roo was helping you with? Just do it. You want to use Emacs and
Vim at the same time? No problem. You forgot to load Roo when you were editing some files? That's
no problem either (in fact you can elect to never load Roo again and your project will remain just fine).
Because Roo uses a text-based interface, there is the normal design trade-off between learnability,
expressability and conciseness. No text-based interface can concurrently satisfy all three dimensions.
With Roo we decided to focus on learnability and expressability. We decided conciseness was less
important given the Roo shell would provide an intuitive, tab-based completion system. We also added
other features to deliver conciseness, such as contextual awareness (which means Roo determines the
target of your command based on the command completed before it) and command abbreviation (which
means you need only type in enough of the command so Roo recognises what you're trying to do).
1.1.3.BUILD-SNAPSHOT 4
Introduction
The learnability of Roo is concurrently addressed on three fronts. First, we favor using standard Java
technologies that you probably already know. Second, we are careful to keep Roo out of your way.
The more Roo simply works in the background automatically without needing your involvement, the
less you need to learn about it in the first place. This is consistent with Raskin's recommendation to
never interrupt your locus of attention. Third, we offer a lot of learnability features in Roo itself. These
include the "hint" command, which suggests what you may wish to do next based on your present
project's state. It's quite easy to build an entire Roo project simply by typing "hint", pressing enter, and
following the instructions Roo presents (we do this all the time during conference talks; it's always
easier than remembering commands!). There's also the intelligent tab completion, which has natural,
friendly conventions like completing all mandatory arguments step-by-step (without distracting you
with unnecessary optional arguments). There's also the online "help" command, sample scripts, this
documentation and plenty of other resources.
Roo also follows a number of well-defined conventions so that you always know what it's doing. Plus
it operates in a "fail safe" manner, like automatically undoing any changes it makes to the file system
should something go wrong. You'll quickly discover that Roo is a friendly, reliable companion on your
development journey. It doesn't require special handling and it's always there for you when you need it.
In summary, we've spent a lot of time thinking about usability and learnability to help ensure you enjoy
your Roo experience.
Roo doesn't impose any engineering trade-offs on your project. In fact, compared with most
Spring-based enterprise applications, we're almost certain you'll find a Roo application will have a
smaller deployment artefact, operate more quickly in terms of CPU time, and consume less memory.
You'll also find you don't miss out on any of the usual IDE services like code assist, debugging and
profiling. We'll explore how Roo achieves this below, but this information is relatively advanced and is
provided mainly for architects who are interested in Roo's approach. As this knowledge is not required
to simply use Roo, feel free to jump ahead to the next section if you wish.
Smaller deployment artefacts are achieved due to Roo's incremental dependency addition approach.
You start out with a small JAR and then we add dependencies only if you actually need them. As
of Roo 1.0.0, a typical Roo-based web application WAR is around 13 Mb. This includes major
components like Spring, Spring JavaScript (with embedded Dojo) and Hibernate, plus a number of
smaller components like URL rewriting. As such Roo doesn't waste disk space or give you 30+ Mb
WARs, which results in faster uploads and container startup times.
Speaking of startup times, Roo uses AspectJ's excellent compile-time weaving approach. This gives us
a lot more power and flexibility than we'd ordinarily have, allowing us to tackle advanced requirements
like advising domain objects and dependency injecting them with singletons. It also means the dynamic
proxies typically created when loading Spring are no longer required. Roo applications therefore
startup more quickly, as there's no dynamic proxy creation overhead. Plus Roo applications operate
more quickly, as there's no dynamic proxy objects adding CPU time to the control flow.
Because Roo's AspectJ usage means there are no proxy objects, you also save the memory expense
of having to hold them. Furthermore, Roo has no runtime component, so you won't lose any memory
or CPU time there either. Plus because Roo applications use Java as their programming language,
there won't be any classes being created at runtime. This means a normal Roo application won't suffer
exhaustion of permanent generation memory space.
1.1.3.BUILD-SNAPSHOT 5
Introduction
While some people would argue these deployment size, CPU and memory considerations are minor,
the fact is they add up when you have a large application that needs to scale. With Roo your applications
will use your system resources to their full potential. Plus as we move more and more enterprise
applications into virtualized and cloud-hosted environments, the requirement for performant operation
on shared hardware will become even more relevant.
You'll also find that Roo provides a well thought out application architecture that delivers pragmatism,
flexibility and ease of maintainability. You'll see we've made architectural decisions like eliminating
the DAO layer, using annotation-based dependency injection, and automatically providing dependency
injection on entities. These decisions dramatically reduce the amount of Java and XML code you have
to write and maintain, plus improve your development cycle times and refactoring experiences.
With Roo, you don't have to make a trade-off between productivity or performance. Now it's easy to
have both at the same time.
One of the biggest risks when adopting a new tool like Roo is the ease at which you can change
your mind in the future. You might decide to remove a tool from your development ecosystem for
many different reasons, such as changing requirements, a more compelling alternative emerging, the
tool having an unacceptable number of bugs, or the tool not adequately supporting the versions of
other software you'd like to use. These risks exist in the real world and it's important to mitigate the
consequences if a particular tool doesn't work out in the long-term.
Because Roo does not exist at runtime, your risk exposure from using Roo is already considerably
diminished. You can decide to stop using Roo and implement that decision without even needing to
change any production deployment of the application.
If you do decide to stop using Roo, this can be achieved in just a few minutes. There is no need to
write any code or otherwise make significant changes. We've covered the short removal process in a
dedicated removing Roo chapter, but in summary you need to perform a "push in refactor" command
within Eclipse and then do a quick regular expression-based find and replace. That's all that is needed
to 100% remove Roo from your project. We often remove Roo from a project during conference
demonstrations just to prove to people how incredibly easy it is. It really only takes two to three minutes
to complete.
We believe that productivity tools should earn their keep by providing you such a valuable service that
you want to continue using them. We've ensured Roo will never lock you in because (a) it's simply the
right and credible thing to do engineering-wise and (b) we want Roo to be such an ongoing help on
your projects that you actually choose to keep it. If you're considering alternative productivity tools,
consider whether they also respect your right to decide to leave and easily implement that decision, or
if they know you're locked in and can't do much about it.
1.3. Installation
Roo is a standard Java application that is fully self-contained within the Roo distribution ZIPs. You
can download Roo from one of the download sites, or build a distribution ZIP yourself from our source
control repository.
If you are upgrading from an existing version of Spring Roo, you should consult the upgrade notes
for important information.
1.1.3.BUILD-SNAPSHOT 6
Introduction
Before attempting to install Roo, please ensure you have the following system dependencies:
• A Linux, Apple or Windows-based operating system (other operating systems may work but are
not guaranteed)
• A Sun, JRocket or IBM Java 5 or Java 6 installation, with the $JAVA_HOME environment variable
pointing to the installation
• Apache Maven 2.0.9 or above installed and in the path (for use with Roo-created projects; Roo itself
does require Maven)
We have listed various considerations concerning the Java Development Kit (JDK) and operating
systems in the known issues section of this documentation. We always recommend you use the latest
version of Java and Maven that are available for your platform. We also recommend that you use
SpringSource Tool Suite (STS), which is our free Eclipse-based IDE that includes a number of features
that make working with Roo even easier (you can of course use Roo with normal Eclipse or without
an IDE at all if you prefer).
If you use OS X, we strongly recommend the use of the iTerm application for terminal emulation.
iTerm provides full ANSI support, which isn't provided by the default OSX Terminal application.
Some Roo operations update the "flash message area", and if you have full ANSI support in your
terminal this will look more visually pleasing. Of course, you don't need to use iTerm - Roo will just
display the updates with other console messages in that case. Windows and Linux users need not do
anything special, as those operating systems work perfectly fine out-of-the-box.
Once you have satisfied the initial requirements, you can install Roo by following these steps:
1. Unzip the Roo installation ZIP to a directory of your choice; this will be known as $ROO_HOME in
the directions below
3. If using Linux or Apple, create a symbolic link using a command such as sudo ln -s
$ROO_HOME/bin/roo.sh /usr/bin/roo
Next verify Roo has been installed correctly. This can be done using the following commands:
$ mkdir roo-test
$ cd roo-test
$ roo quit
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ W.X.Y.ZZ [rev RRR]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
$ cd ..
$ rmdir roo-test
If you see the logo appear, you've installed Roo successfully. For those curious, the "[rev RRR]" refers
to the Git commit ID used to compile that particular build of Roo.
1.1.3.BUILD-SNAPSHOT 7
Introduction
At present the only configuration settings available is roo.bright. This causes forground messages in
the shell to be displayed with brighter colors. This is potentially useful if your background color is
light (eg white). You can set the variable using the following commands:
There is an enhancement request within our issue tracker for customisable shell color schemes. If
you're interested in seeing this supported by Roo, you may wish to consider voting for ROO-549.
The purpose of this application is just to try out Roo. We won't explain what's going on in these steps,
but don't worry - we'll do that in the next chaper, Beginning With Roo: The Tutorial. We will try to
teach you about some usability features as we go along, though.
$ mkdir ten-minutes
$ cd ten-minutes
$ roo
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ W.X.Y.ZZ [rev RRR]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo> hint
Welcome to Roo! We hope you enjoy your stay!
Before you can use many features of Roo, you need to start a new project.
To do this, type 'project' (without the quotes) and then hit TAB.
Note that Roo frequently allows the use of TAB, so press TAB regularly.
Once your project is created, type 'hint' and ENTER for the next suggestion.
You're also welcome to visit http://forum.springframework.org for Roo help.
Notice the output from the "hint" command guides you through what to do next. Let's do that:
1.1.3.BUILD-SNAPSHOT 8
Introduction
Created /home/balex/ten-minutes/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
Created SRC_TEST_JAVA
Created SRC_TEST_RESOURCES
Created SRC_MAIN_WEBAPP
Created SRC_MAIN_RESOURCES/META-INF/spring
Created SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
roo> hint
Roo requires the installation of a JPA provider and associated database.
Once JPA is installed, type 'hint' and ENTER for the next suggestion.
At this point you've now got a viable Maven-based project setup. But let's make it more useful by
setting up JPA. In the interests of time, I'll just include the commands you should type below. Be sure
to try using the TAB key when using the shell, as it will save you from having to type most of these
commands:
The "perform" commands could have been easily undertaken from the command prompt using "mvn"
instead. We just did them from within Roo to benefit from TAB completion. You could have also
skipped the "perform eclipse" command if you are using the m2eclipse plugin. If you are using
SpringSource Tool Suite (STS), it automatically includes m2eclipse and as such you do not need to use
the "perform eclipse" command. Indeed if you're an STS user, you could have started your Roo project
right from within the IDE by selecting the File > New > Spring Roo menu option and completing the
steps. In that case a Roo Shell view will open within STS and from there you can enter the remaining
commands.
Now that you've loaded Tomcat, let's run the Selenium tests. You can do this by loading
a new command window, changing into the ten-minutes directory, and then executing mvn
selenium:selenese. You should see your FireFox web browser execute the generated Selenium tests.
You can also visit your new web application at http://localhost:8080/tenminutes, which should look
similar to the picture below.
1.1.3.BUILD-SNAPSHOT 9
Introduction
Naturally in this short ten minute test we've skipped dozens of features that Roo can provide, and didn't
go into any detail on how you could have customised the application. We just wanted to show you that
Roo works and you can build an application in record-time. The Beginning With Roo: The Tutorial
chapter will go through the process of building an application in much more depth, including how to
work with your IDE and so on.
$ mkdir sample
$ cd sample
$ roo
roo> script --file filename.roo
roo> quit
$ mvn tomcat:run
The filename.roo shown in the statements above should be substituted with one of the filenames from
this list (note that you get filename completion using TAB):
• clinic.roo: The Petclinic sample script is our most comprehensive. It builds a large number of
entities, controllers, Selenium tests and dynamic finders. It also sets up Log4J and demonstrates
entity relationships of different cardinalities.
• vote.roo: The Voting sample script was built live on-stage during SpringOne Europe 2009, as
detailed in the project history section. This is a nice sample script because it's quite small and only
has two entities. It also demonstrates Spring Security usage.
• wedding.roo: The Wedding RSVP sample script is the result of the wedding RSVP tutorial. If you're
looking for another Roo tutorial, this sample script (along with the associated blog entry) is a good
choice. This project includes Selenium tests, dynamic finders and Log4j configuration.
• expenses.roo: The Expenses sample script produces a Google Web Toolkit (GWT) application using
Spring Roo. This shows you the new GWT scaffolding support we added to Roo 1.1.
1.1.3.BUILD-SNAPSHOT 10
Introduction
The next step is to complete the Beginning With Roo: The Tutorial chapter. In the tutorial chapter you'll
learn how to use Roo with your preferred IDE and how flexible and natural is to develop with Roo.
After that you should read the application architecture chapter to understand what Roo applications
look like. From there you might wish to wrap up the recommended tour of Roo with a skim over the
usage and conventions chapter. This final recommended chapter will focus more on using the Roo tool
and less on the applications that Roo creates.
If you can't find the information you're looking for in this reference guide, the resources chapter
contains numerous Roo-related web sites and other community resources.
We welcome your comments and suggestions as you go about using Roo. One convenient way to
share your experiences is to Tweet with the @springroo hash code. You can also follow Roo's core
development team via Twitter for the latest Roo updates. In any event, we thank you for exploring
Roo and hope that you enjoy your Roo journey.
1.1.3.BUILD-SNAPSHOT 11
Chapter 2. Beginning With Roo: The Tutorial
In this chapter we'll build an app step-by-step together in a relatively fast manner so that you can see
how to typically use Roo in a normal project. We'll leave detailed features and side-steps to other
sections of this manual.
• project creation
• customizing the look and feel of the Web UI for our business domain
1.1.3.BUILD-SNAPSHOT 12
Beginning With Roo: The Tutorial
After this short discussion with the Pizza Shop owner, we have created a simple class diagram for the
initial domain model:
While this class diagram represents a simplified model of the problem domain for the pizza shop
problem domain, it is a good starting point for the project at hand in order to deliver a first prototype of
the application to the Pizza Shop owner. Later tutorials will expand this domain model to demonstrate
more advanced features of Spring Roo.
Next, we start Spring Roo and type 'hint' to obtain context-sensitive guidance from the Roo shell:
pizza> roo
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ 1.0.0.RELEASE [rev XXX]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo>
roo> hint
Welcome to Roo! We hope you enjoy your stay!
Before you can use many features of Roo, you need to start a new project.
To do this, type 'project' (without the quotes) and then hit TAB.
Note that Roo frequently allows the use of TAB, so press TAB regularly.
1.1.3.BUILD-SNAPSHOT 13
Beginning With Roo: The Tutorial
Once your project is created, type 'hint' and ENTER for the next suggestion.
You're also welcome to visit http://forum.springframework.org for Roo help.
roo>
There are quite a few usability features within the Roo shell. After typing hint you may have noticed
that this command guides you in a step-by-step style towards the completion of your first project. Or
if you type help you will see a list of all commands available to you in the particular context you
are in. In our case we have not created a new project yet so the help command only reveals higher
level commands which are available to you at this stage. To create an actual project we can use the
project command:
When you used the project command, Roo created you a Maven pom.xml file as well as a Maven-style
directory structure. The top level package you nominated in this command was then used as the
<groupId> within the pom.xml. When typing later Roo commands, you can use the "~" shortcut key to
refer to this top-level-package (it is read in by the Roo shell from the pom.xml each time you load Roo).
For those familiar with Maven you will notice that this folder structure follows standard Maven
conventions by creating separate folders for your main project resources and tests. Roo also installs a
default application context and a log4j configuration for you. Finally, the project pom file contains all
required dependencies and configurations to get started with our Pizza Shop project.
1.1.3.BUILD-SNAPSHOT 14
Beginning With Roo: The Tutorial
Once the project structure is created by Roo you can go ahead and install a persistence configuration
for your application. Roo leverages the Java Persistence API (JPA) which provides a convenient
abstraction to achieve object-relational mapping. JPA takes care of mappings between your persistent
domain objects (entities) and their underlying database tables. To install or change the persistence
configuration in your project you can use the persistence setup command (note: try using the <TAB>
as often as you can to auto-complete your commands, options and even obtain contextual help):
Once JPA is installed, type 'hint' and ENTER for the next suggestion.
com.springsource.roo.pizzashop roo>
com.springsource.roo.pizzashop roo> persistence setup --provider HIBERNATE --database HYPERSONIC_IN_ME
Created SRC_MAIN_RESOURCES/META-INF/persistence.xml
Created SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Managed SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
Managed ROOT/pom.xml
com.springsource.roo.pizzashop roo>
When you are ready to test or install your application in a production setting, the persistence
setup command can be repeated. This allows you to nominate a different database, or even
ORM. Roo offers TAB completion for production databases including Postgres, MySQL, Microsoft
SQL Server, Oracle, DB2, Sybase, H2, Hypersonic and more. Another important step is to edit
the SRC_MAIN_RESOURCES/META-INF/persistence.xml file and modify your JPA provider's DDL
(schema management) configuration setting so it preserves the database between restarts of your
application. To help you with this, Roo automatically lists the valid settings for your JPA provider as
a comment in that file. Note that by default your JPA provider will drop all database tables each time
it reloads. As such you'll certainly want to change this setting.
Please note: The Oracle and DB2 JDBC drivers are not available in public maven repositories.
Roo will install standard dependencies for these drivers (if selected) but you may need to
adjust the version number or package name according to your database version. You can use
the following maven command to install your driver into your local maven repository: mvn
install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.2.0.2
-Dpackaging=jar -Dfile=/path/to/file (example for the Oracle driver)
1.1.3.BUILD-SNAPSHOT 15
Beginning With Roo: The Tutorial
--class attribute we use the --testAutomatically attribute which conveniently creates integration
tests for a domain object. So let's start with the Topping domain object:
After specify a --name argument, press SPACE then TAB. Note nothing appears.
Because nothing appears, it means you've entered all mandatory arguments.
However, optional arguments do exist for this command (and most others in Roo).
To see the optional arguments, type '--' and then hit TAB. Mostly you won't
need any optional arguments, but let's select the --testAutomatically option
and hit ENTER. You can always use this approach to view optional arguments.
You will notice that besides the creation of Java and AspectJ sources, the entity command in the Roo
shell takes care of creating the appropriate folder structure in your project for the top level package you
defined earlier. You will notice that we used the '~' character as a placeholder for the project's top level
package. While this serves a convenience to abbreviate long commands, you can also tab-complete
the full top level package in the Roo shell.
As a next step we need to add the 'name' field to our Topping domain class. This can be achieved by
using the field command as follows:
To add a new field, type 'field' and then hit TAB. Be sure to select
your entity and provide a legal Java field name. Use TAB to find an entity
name, and '~' to refer to the top level package. Also remember to use TAB
to access each mandatory argument for the command.
Afer completing the mandatory arguments, press SPACE, type '--' and then TAB.
The optional arguments shown reflect official JSR 303 Validation constraints.
Feel free to use an optional argument, or delete '--' and hit ENTER.
After adding your fields, type 'hint' for the next suggestion.
To learn about setting up many-to-one fields, type 'hint relationships'.
~.domain.Topping roo>
~.domain.Topping roo> field string --fieldName name --notNull --sizeMin 2
Managed SRC_MAIN_JAVA/com/springsource/roo/pizzashop/domain/Topping.java
Created SRC_MAIN_JAVA/com/springsource/roo/pizzashop/domain/Topping_Roo_JavaBean.aj
1.1.3.BUILD-SNAPSHOT 16
Beginning With Roo: The Tutorial
Managed SRC_TEST_JAVA/com/springsource/roo/pizzashop/domain/ToppingDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA/com/springsource/roo/pizzashop/domain/Topping_Roo_ToString.aj
As explained in the documentation by typing the hint command you can easily add constraints to
your fields by using optional attributes such as --notNull and --sizeMin 2. These attributes result
in standards-compliant JSR-303 annotations which Roo will add to your field definition in your Java
sources. You will also notice that the Roo shell is aware of the current context within which you are
using the field command. It knows that you have just created a Topping entity and therefore assumes
that the field command should be applied to the Topping Java source. Roo's current context is visible
in the Shell (enclosed by a red rectangle for illustration):
If you wish to add the field to a different target type you can specify the --class attribute as part of
the field command which then allows you to tab complete to any type in your project.
As a next step you can create the Base and the Pizza domain object in a similar fashion by issuing the
following commands (shell output omitted):
After adding the name and the price field to the Pizza domain class we need to deal with its
relationships to Base and Topping. Let's start with the m:m (one Pizza can have many Toppings and
one Topping can be applied to many Pizzas) relationship between Pizza and Toppings. To create
such many-to-many relationships Roo offers the field set command:
As you can see it is easy to define this relationship even without knowing about the exact JPA
annotations needed to create this mapping in our Pizza domain entity. In a similar way you can
define the m:1 relationship between the Pizza and Base domain entities by using the field reference
command:
In a similar fashion we can then continue to create the PizzaOrder domain object and add its fields by
leveraging the field date and field number commands:
This concludes this step since the initial version of the domain model is now complete.
1.1.3.BUILD-SNAPSHOT 17
Beginning With Roo: The Tutorial
Results :
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17 seconds
[INFO] Finished at: Tue Dec 29 15:58:04 EST 2009
[INFO] Final Memory: 25M/79M
[INFO] ------------------------------------------------------------------------
As you can see Roo has issued a Maven command (equivalent to running 'mvn test' outside the Roo
shell) in order to execute the integration tests. All tests have passed, Roo has generated 9 integration
tests per domain object resulting in a total of 36 integration tests for all 4 domain objects.
By default Roo projects do not contain any IDE-specific workspace configuration artifacts. This means
your IDE won't be able to import your Pizza Shop project by default. The Roo shell can help us create
IDE-specific workspace configuration artifacts by means of the perform eclipse command. However,
you should not use this command if you have the m2eclipse plugin installed. If you're an STS user,
you have the m2eclipse plugin installed and as such you can skip the "perform eclipse" command. All
people not using STS or m2eclipse should use the following command:
1.1.3.BUILD-SNAPSHOT 18
Beginning With Roo: The Tutorial
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Tue Dec 29 16:11:38 EST 2009
[INFO] Final Memory: 24M/79M
[INFO] ------------------------------------------------------------------------
Note, when issuing this command for the first time you can expect delays while Maven downloads
the dependencies and their sources into your local repository. Once this command has completed you
are ready to import your project into STS by clicking 'File > Import > General > Existing Projects
into Workspace'. Once your project is imported into STS you can take a look at the Java sources. For
example you can run the included JUnit tests by right clicking the pizzashop project and then selecting
'Run As > JUnit Test'.
If you're using STS or have installed m2eclipse into an Eclipse-based IDE, as mentioned earlier you
can skip the perform eclipse command entirely. In this case you simply need to select in STS/Eclipse
the 'File > Import > General > Maven Projects' menu option.
As detailed in the Application Architecture chapter of this documentation Roo projects leverage
AspectJ Intertype declarations extensively. This does not, however, affect your ability to use code
completion features offered by STS. To see code completion working in action you can open an existing
integration test and use the testMarkerMethod() method to test it. For example you can open the
BaseIntegrationTest.java source file and try it out:
Note, most of the methods visible in the STS code assist are actually not in the Java sources but rather
part of the AspectJ ITD and are therefore introduced into the Java bytecode at compile time.
1.1.3.BUILD-SNAPSHOT 19
Beginning With Roo: The Tutorial
This command will scan the Pizza Shop project for any domain entities and scaffold a Spring MVC
controller for each entity detected. The --package attribute is needed to specify in which package the
controllers should be installed. This command can be issued from your normal Roo shell or from the
Roo shell, which ships with STS. In order to use the integrated Roo shell within STS you need to right
click on the pizzashop application and select 'Spring Tools > Open Roo Shell'.
Note, that with the first use of the controller command the nature of the project changes from a normal
Java project nature to a Web project nature in STS. The first use of the controller command will
also add additional dependencies such as Spring MVC, Tiles, etc to your project. In order to update
the project classpath within STS with these new dependencies you can issue 'perform eclipse' again,
followed by a project refresh in STS.
All newly added Web artifacts which are needed for the view scaffolding can be found under the
src/main/webapp folder. This folder includes graphics, cascading style sheets, Java Server pages,
Tiles configurations and more. The purpose of these folders is summarized in the UI customization
section. The Roo generated Spring MVC controllers follow the REST pattern as much as possible
by leveraging new features introduced with the release of Spring Framework v3. The following URI
- Resource mappings are applied in Roo generated controllers:
• Deploy from your shell / command line (without the need to assemble a war archive):
1.1.3.BUILD-SNAPSHOT 20
Beginning With Roo: The Tutorial
• run 'mvn tomcat:run' in the root of your project (not inside the Roo shell) to deploy to a Tomcat
container
• run 'mvn jetty:run' in the root of your project (not inside the Roo shell) to deploy to a Jetty
container
• Drag your project to the desired Web container inside the STS server view
• Right-click your project and select 'Run As > Run on Server' to deploy to the desired Web
container
After selecting your preferred deployment method you should see the Web container starting and the
application should be available under the following URL http://localhost:8080/pizzashop
1.1.3.BUILD-SNAPSHOT 21
Beginning With Roo: The Tutorial
Note, the Roo shell will hide the security setup command until you have created a Web layer. As
shown above, the security setup command manages the project pom.xml file. This means additional
dependencies have been added to the project. To add these dependencies to the STS workspace you
should run the perform eclipse command again followed by a project refresh (if you're using STS
or m2eclipse, the "perform eclipse" command should be skipped as it will automatically detect and
handle the addition of Spring Security to your project).
In order to secure the views for the Topping, Base, and Pizza resources in the
Pizza Shop application you need to open the applicationContext-security.xml file in the
src/main/resources/META-INF/spring folder:
As a next step you can use the Spring Security JSP tag library to restrict access to the relevant menu
items in the menu.jspx file:
This leaves the pizza order view visible to the public. Obviously the delete and the update use case
for the pizza order view are not desirable. The easiest way to take care of this is to adjust the
@RooWebScaffold annotation in the PizzaOrderController.java source:
@RooWebScaffold(path = "pizzaorder",
formBackingObject = PizzaOrder.class,
delete=false,
update=false)
This will trigger the Roo shell to remove the delete and the update method from the
PizzaOrderController and also adjust the relevant view artifacts.
With these steps completed you can restart the application and the 'admin' user can navigate to
http://localhost:8080/pizzashop/login to authenticate.
1.1.3.BUILD-SNAPSHOT 22
Beginning With Roo: The Tutorial
The easiest way to customize the look & feel of the Roo Web UI is to change CSS and image resources
to suit your needs. The following look & feel was created for the specific purpose of the Pizza Shop
application:
Spring Roo also configures theming support offered by Spring framework so you can leverage this
feature with ease.
To achieve a higher level of customization you can change the default Tiles template
(WEB-INF/layouts/default.jspx) and adjust the JSP pages (WEB-INF/views/*.jspx). WIth release 1.1
1.1.3.BUILD-SNAPSHOT 23
Beginning With Roo: The Tutorial
of Spring Roo jspx artifacts can now be adjusted by the user while Roo can still make adjustments as
needed if domain layer changes are detected. See the JSP Views section for details.
Furthermore the Spring Roo 1.1 release introduced a set of JSP tags which not only reduce the
scaffolded jspx files by 90% but also offer the most flexible point for view customization. Roo will
install these tags into the user project where they can be accessed and customized to meet specific
requirements of the project. For example it would be fairly easy to remove the integrated Spring JS
/ Dojo artifacts and replace them with your JS framework of choice. To make these changes available
for installation in other projects you can create a simple add-on which replaces the default tags installed
by Roo with your customized tags.
The generated tests are located in the src/main/webapp/selenium folder and can be run via the
following maven command (executed from command line, not the Roo shell):
Running the maven selenium addon will start a new instance of the FireFox browser and run tests
against the Pizza Shop Web UI by using Roo generated seed data.
Please note that the maven selenium plugin configured in the project pom.xml assumes that the FireFox
Web browser is already installed in your environment. Running the maven selenium plugin also
assumes that your application is already started as discussed in step 6. Finally, there are limitations
with regards to locales used by the application. Please refer to the known issues section for details.
Finally, you may wish to deploy your application to a production Web container. For this you can
easily create a war archive by taking advantage of the perform package command:
1.1.3.BUILD-SNAPSHOT 24
Beginning With Roo: The Tutorial
[INFO] ------------------------------------------------------------------------
...
[INFO] [war:war {execution: default-war}]
[INFO] Exploding webapp...
[INFO] Assembling webapp pizzashop in /Users/sschmidt/pizza/target/pizzashop-0.1.0-SNAPSHOT
[INFO] Copy webapp webResources to /Users/sschmidt/pizza/target/pizzashop-0.1.0-SNAPSHOT
[INFO] Generating war /Users/sschmidt/pizza/target/pizzashop-0.1.0-SNAPSHOT.war
[INFO] Building war: /Users/sschmidt/pizza/target/pizzashop-0.1.0-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17 seconds
[INFO] Finished at: Wed Dec 30 11:36:40 EST 2009
[INFO] Final Memory: 26M/79M
[INFO] ------------------------------------------------------------------------
~.web roo>
This command produces your war file which can then be easily copied into your production Web
container.
• Dynamic Finders
• Logging addon
• JMS addon
1.1.3.BUILD-SNAPSHOT 25
Chapter 3. Application Architecture
In this chapter we'll introduce the architecture of Roo-created projects. In later chapters we'll cover
the architecture of Roo itself.
This chapter focuses on web applications created by Roo, as opposed to add-on projects.
While most people will be focusing on developing these Spring MVC-based web applications, it's
important to recognise that Roo does not impose any restrictions on the sort of Java applications that
can be built with it. Even with Roo 1.0.0 it was easy to build any type of self-contained application.
Some examples of the types of requirements you can easily address with the current version of Roo
include (but are not limited to):
• Listening for messages on a JMS queue and sending replies over JMS or SMTP (Roo can easily
setup JMS message producers, consumers and SMTP)
• Writing a services layer (perhaps annotated with Spring's @Service stereotype annotation) and
exposing it using a remoting protocol to a rich client (Spring's remoting services will help here)
• Executing a series of predefined actions against the database, perhaps in conjunction with Spring's
new @Scheduled or @Async timer annotations
• Experimentation with the latest Spring and AspectJ features with minimal time investment
One of the major differences between Roo and traditional, hand-written applications is we don't add
layers of abstraction unnecessarily. Most traditional Java enterprise applications will have a DAO
layer, services layer, domain layer and controller layer. In a typical Roo application you'll only use
an entity layer (which is similar to a domain layer) and a web layer. As indicated by the list above, a
services layer might be added if your application requires it, although a DAO layer is extremely rarely
added. We'll look at some of these layering conventions (and the rationale for them) as we go through
the rest of this chapter.
3.2.1. AspectJ
AspectJ is a powerful and mature aspect oriented programming (AOP) framework that underpins many
large-scale systems. Spring Framework has offered extensive support for AspectJ since 2004, with
Spring 2.0 adopting AspectJ's pointcut definition language even for expressing Spring AOP pointcuts.
Many of the official Spring projects offer support for AspectJ or are themselves heavily dependent
1.1.3.BUILD-SNAPSHOT 26
Application Architecture
on it, with several examples including Spring Security (formerly Acegi Security System for Spring),
Spring Insight, SpringSource tc Server, SpringSource dm Server, Spring Enterprise and Spring Roo.
While AspectJ is most commonly known for its aspect oriented programming (AOP) features such as
applying advice at defined pointcuts, Roo projects use AspectJ's powerful inter-type declaration (ITD)
features. This is where the real magic of Roo comes from, as it allows us to code generate members
(artifacts like methods, fields etc) in a different compilation unit (ie source file) from the normal .java
code you'd write as a developer. Because the generated code is in a separate file, we can maintain
that file's lifecycle and contents completely independently of whatever you are doing to the .java files.
Your .java files do not need to do anything unnatural like reference the generated ITD file and the
whole process is completely transparent.
Let's have a look at how ITDs work. In a new directory, type the following commands and note the
console output:
Notice how there is a standard Hello.java file, as well as a series of Hello_Roo_*.aj files. Any file
ending in *_Roo_*.aj is an AspectJ ITD and will be managed by Roo. You should not edit these files
directly, as Roo will automatically maintain them (this includes even deleting files that aren't required,
as we'll see shortly).
package com.aspectj.rocks;
import javax.persistence.Entity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.roo.addon.entity.RooEntity;
@Entity
@RooJavaBean
@RooToString
@RooEntity
public class Hello {
As shown, there's very little in the .java file. There are some annotations, plus of course the field we
added. Note that Roo annotations are always source-level retention, meaning they're not compiled into
your .class file. Also, as per our usability goals you'll note that Roo annotations also always start
with @Roo* to help you find them with code assist.
By this stage you're probably wondering what the ITD files look like. Let's have a look at one of them,
Hello_Roo_ToString.aj:
1.1.3.BUILD-SNAPSHOT 27
Application Architecture
package com.aspectj.rocks;
import java.lang.String;
Notice how the ITD is very similar to Java code. The main differences are that it is declared with
"privileged aspect", plus each member identifies the target type (in this case it is "Hello.toString",
which means add the "toString" method to the "Hello" type). The compiler will automatically
recognize these ITD files and cause the correct members to be compiled into Hello.class. We can see
that quite easily by using Java's javap command. All we need to do is run the compiler and view the
resulting class. From the same directory as you created the project in, enter the following commands
and observe the final output:
$ mvn compile
$ javap -classpath target/classes/.:target/test-classes/. com.aspectj.rocks.Hello
Compiled from "Hello.java"
public class com.aspectj.rocks.Hello extends java.lang.Object implements org.springframework.beans.fac
transient javax.persistence.EntityManager entityManager;
public com.aspectj.rocks.Hello();
public static java.lang.String ajc$get$comment(com.aspectj.rocks.Hello);
public static void ajc$set$comment(com.aspectj.rocks.Hello, java.lang.String);
public static java.lang.Long ajc$get$id(com.aspectj.rocks.Hello);
public static void ajc$set$id(com.aspectj.rocks.Hello, java.lang.Long);
public static java.lang.Integer ajc$get$version(com.aspectj.rocks.Hello);
public static void ajc$set$version(com.aspectj.rocks.Hello, java.lang.Integer);
static {};
public static long countHelloes();
public static final javax.persistence.EntityManager entityManager();
public static java.util.List findAllHelloes();
public static com.aspectj.rocks.Hello findHello(java.lang.Long);
public static java.util.List findHelloEntries(int, int);
public void flush();
public java.lang.String getComment();
public java.lang.Long getId();
public java.lang.Integer getVersion();
public com.aspectj.rocks.Hello merge();
public void persist();
public void remove();
public void setComment(java.lang.String);
public void setId(java.lang.Long);
public void setVersion(java.lang.Integer);
public java.lang.String toString();
}
While the javap output might look a little daunting at first, it represents all the members that
Roo has added (via AspectJ ITDs) to the original Hello.java file. Notice there isn't just the
toString method we saw in the earlier ITD, but we've also made the Hello class implement
Spring's ConfigurableObject interface, provided access to a JPA EntityManager, included a range
of convenient persistence methods plus even getters and setters. All of these useful features are
automatically maintained in a round-trip compatible manner via the ITDs.
1.1.3.BUILD-SNAPSHOT 28
Application Architecture
A careful reader might be wondering about the long field names seen for introduced fields. You can
see that these field names start with "ajc$" in the output above. The reason for this is to avoid name
collisions with fields you might have in the .java file. The good news is that you won't ever need
to deal with this unless you're trying to do something clever with reflection. It's just something to be
aware of for introduced fields in particular. Note that the names of methods and constructors are never
modified.
Naturally as a normal Roo user you won't need to worry about the internals of ITD source code and
the resulting .class files. Roo automatically manages all ITDs for you and you never need deal with
them directly. It's just nice to know how it all works under the hood (Roo doesn't believe in magic!).
The benefit of this ITD approach is how easily and gracefully Roo can handle code generation for you.
To see this in action, go and edit the Hello.java in your favourite text editor with Roo
running. Do something simple like add a new field. You'll notice the Hello_Roo_ToString.aj and
Hello_Roo_JavaBean.aj files are instantly and automatically updated by Roo to include your new
field. Now go and write your own toString method in the .java file. Notice Roo deletes the
Hello_Roo_ToString.aj file, as it detects your toString method should take priority over a generated
toString method. But let's say you want a generated toString as well, so change the Hello.java's
@RooToString annotation to read @RooToString(toStringMethod="generatedToString"). Now
you'll notice the Hello_Roo_ToString.aj file is immediately re-created, but this time it introduces
a generatedToString method instead of the original toString. If you comment out both fields in
Hello.java you'll also see that Roo deletes both ITDs. You can also see the same effect by quitting
the Roo shell, making any changes you like, then restarting the Roo shell. Upon restart Roo will
automatically perform a scan and discover if it needs to make any changes.
Despite the admittedly impressive nature of ITDs, AspectJ is also pretty good at aspect oriented
programming features like pointcuts and advice! To this end Roo applications also use AspectJ for all
other AOP requirements. It is AspectJ that provides the AOP so that classes are dependency injected
with singletons when instantiated and transactional services are called as part of method invocations.
All Roo applications are preconfigured to use the Spring Aspects project, which ships as part of Spring
Framework and represents a comprehensive "aspect library" for AspectJ.
3.2.2. Spring
Spring Roo applications all use Spring. By "Spring" we not only mean Spring Framework, but also the
other Spring projects like Spring Security and Spring Web Flow. Of course, only Spring Framework
is installed into a user project by default and there are fine-grained commands provided to install each
additional Spring project beyond Spring Framework.
All Roo applications use Spring Aspects, which was mentioned in the AspectJ section and ensures
Spring Framework's @Configurable dependency injection and transactional advice is applied.
Furthermore, Roo applications use Spring's annotation-driven component scanning by default and
also rely on Spring Framework for instantiation and dependency injection of features such as JPA
providers and access to database connection pools. Many of the optional features that can be used
in Roo applications (like JMS and SMTP messaging) are also built upon the corresponding Spring
Framework dependency injection support and portable service abstractions.
Those Roo applications that include a web controller will also receive Spring Framework 3's MVC
features such as its conversion API, web content negotiation view resolution and REST support. It is
possible (and indeed encouraged) to write your own web Spring MVC controllers in Roo applications,
and you are also free to use alternate page rendering technologies if you wish (ie not just JSP).
1.1.3.BUILD-SNAPSHOT 29
Application Architecture
Generally speaking Roo will not modify any Spring-related configuration or setting file (eg properties)
unless specifically requested via a shell command. Roo also ensures that whenever it creates, modifies
or deletes a file it explicitly tells you about this via a shell message. What this means is you can safely
edit your Spring application context files at any time and without telling Roo. This is very useful if the
default configuration offered by Roo is unsuitable for your particular application's needs.
Because Spring projects are so extensively documented, and Roo just uses Spring features in the normal
manner, we'll refrain from duplicating Spring's documentation in this section. Instead please refer to
the excellent Spring documentation for guidance, which can be found in the downloadable distribution
files and also on the Spring web site.
The role of an entity in your Roo-based application is to model the persistent "domain layer" of your
system. As such, a domain object is specific to your problem domain but an entity is a special form
of a domain object that is stored in the database. By default a single entity will map to a single table
in your database, and a single field within your entity class will map to a single column within the
corresponding table. However, like most things in Roo this is easily customised using the relevant
standard (in this case, JPA annotations). Indeed most of the common customisation options (like
specifying a custom column or table name etc) can be expressed directly in the relevant Roo command,
freeing you from even needing to know which annotation(s) should be used.
Let's consider a simple entity that has been created using the entity command and following it with
a single field command:
package com.springsource.vote.domain;
import javax.persistence.Entity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.roo.addon.entity.RooEntity;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Entity
@RooJavaBean
@RooToString
@RooEntity
public class Choice {
@NotNull
@Size(min = 1, max = 30)
private String namingChoice;
@Size(max = 80)
private String description;
}
At its heart, the above entity is simple a JPA entity that contains two fields. The two fields contain
JavaBean Validation API (JSR 303) annotations, which are useful if your JPA provider supports
this standard (as is the case if you nominate Hibernate as your JPA provider) or you are using a
1.1.3.BUILD-SNAPSHOT 30
Application Architecture
Roo-scaffolded web application front end (in which case Roo will use Spring Framework 3's JSR 303
support). Of course you do not need to use the JavaBean Validation API annotations at all, but if you
would like to use them the relevant Roo field commands provide tab-completion compatible options
for each. The first time you use one of these Roo field commands, Roo will add required JavaBean
Validation API libraries to your project (ie these libraries will not be in your project until you decide
to first use JavaBean Validation).
What's interesting about the above entity is what you can actually do with it. There are a series of
methods automatically added into the Choice.class courtesy of Roo code-generated and maintained
AspectJ ITDs. These include static methods for retrieving instances of Choice, JPA facade methods
for persisting, removing, merging and flushing the entity, plus accessors and mutators for both the
identifier and version properties. You can fine-tune these settings by modifying attributes on the
@RooEntity annotation. You can also have Roo remove these services by simply removing the
@RooEntity annotation from the class, in which case you'll be left with a normal JPA @Entity that
you'll need to manage by hand (eg provide your own persistence methods, identifier, version etc).
The @RooJavaBean annotation causes an accessor and mutator (getter and setter) to automatically be
generated for each field in the class. These accessors and mutators are automatically maintained in
an AspectJ ITD by Roo. If you write your own accessor or mutator in the normal .java file, Roo
will automatically remove the corresponding generated method from the ITD. You can also remove
the @RooJavaBean annotation if you don't want any generated accessors or mutators (although those
related to the version and identifier fields will remain, as they are associated with @RooEntity instead
of @RooJavaBean).
Finally, the @RooToString annotation causes Roo to create and maintain a public String toString()
method in a separate ITD. This method currently is used by any scaffolded web controllers if they
need to display a related entity. The generated method takes care to avoid circular references that
are commonly seen in bidirectional relationships involving collections. The method also formats Java
Calendar objects in an attractive manner. As always, you can write your own toString() method by
hand and Roo will automatically remove its generated toString() method, even if you still have the
@RooToString annotation present. You can of course also remove the @RooToString annotation if you
no longer wish to have a generated toString() method.
Before leaving this discussion on entities, it's worth mentioning that you are free to create your own
entity .java classes by hand. You do not need to use the Roo shell commands to create entities or
maintain their fields - just use any IDE. Also, you are free to use the @RooToString or @RooJavaBean
(or both) annotations on any class you like. This is especially useful if you have a number of domain
objects that are not persisted and are therefore not entities. Roo can still help you with those objects.
In Spring Roo 1.1 we also added comprehensive support for Google Web Toolkit (GWT). This allows
you to build Generation IV web HTML5-based web front-ends. These front-ends access the Spring
1.1.3.BUILD-SNAPSHOT 31
Application Architecture
backend using highly optimized remoting protocols, and the GWT application represents the GWT
team's recommended best practice architecture. In fact, the GWT team at Google wrote most of the
Roo GWT add-on, so you can be sure it uses the best GWT 2.1 features.
Scaffolded web controllers always delegate directly to methods provided on an @RooEntity class. For
maximum compatibility with scaffolded controllers, it is recommended to observe the default identifier
and version conventions provided by @RooEntity implementations. If you write a web controller by
hand (perhaps with the assistance of the controller class command), it is recommended you also use the
methods directly exposed on entities. Most Roo applications will place their business logic between
the entities and web controllers, with only occasional use of services layers. Please refer to the services
layer section for a more complete treatment of when you'd use a services layer.
• There is business logic that spans multiple entities and that logic does not naturally belong in a
specific entity
• You need to invoke business logic outside the scope of a natural web request (eg a timer task)
• Remote client access is required and it is therefore more convenient to simply expose the methods
via a remoting ptotocol
• A higher level of cohesion is sought in the web layer, with the web layer solely responsible for
HTTP-related management and the services layer solely responsible for business logic
• A greater level of testing is desired, which is generally easier to mock than simulating web requests
• it is preferred to place transactional boundaries and security authorization metadta on the services
layer (as opposed to a web controller)
As shown, there are a large number of reasons why services layers remain valuable. However, Roo
does not code generate services layers because they are not strictly essential to building a normal web
application and Roo achieves separation of concern via its AspectJ ITD-based architecture.
If you would like to use a services layer, it's as simple as creating a new class (and optional interface)
and annotating that class with Spring's @Services stereotype annotation. Just ensure the services layer
class appears under the same package as you nominated in the create project command, and Spring
Framework will then automatically detect your services layer class when it launches your application.
1.1.3.BUILD-SNAPSHOT 32
Application Architecture
If we reflect for a moment on the main motivations for DAOs, it is easy to see why these are not
applicable in Roo applications:
• Testing: In a normal application a DAO provides an interface that could be easily stubbed as part of
unit testing. The interesting point about testing is that most people use mocking instead of stubbing
in modern applications, making it attractive to simply mock the persistence method or two that
you actually require for a test (rather than the crudeness of stubbing an entire DAO interface). In
Roo-based applications you simply mock the persistence-related methods that have been introduced
to the entity. You can use normal mocking approaches for the instance methods on the Roo entity,
and use Spring Aspect's @MockStaticEntityMethods support for the static finder methods.
• Separation of concern: One reason for having a DAO layer is that it allows a higher cohesion
object-oriented design to be pursued. The high cohesion equates to a separation of concern that
reduces the conceptual weight of implementing the system. In a Roo-based application separation
of concern is achieved via the separate ITDs. The conceptual weight is also reduced because Roo
handles the persistence methods rather than force the programmer to deal with them. Therefore
separation of concern still exists in a Roo application without the requirement for a DAO layer.
• Pluggable implementations: A further benefit of DAOs is they simplify the switching from one
persistence library to another. In modern applications this level of API abstraction is provided via
JPA. As Roo uses JPA in its generated methods, the ability to plug in an alternate implementation
is already fully supported despite there being no formal DAO layer. You can see this yourself by
issuing the persistence setup command and specifying alternate implementations.
• Non-JPA persistence: It is possible that certain entities are stored using a technology that does not
have a JPA provider. In this case Roo does not support those entities out of the box. However, if
only a small number of entities are effected by this consideration there is no reason one or more
hand-written ITDs could not be provided by the user in order to maintain conceptual parity with
the remainder of the Roo application (which probably does have some JPA). If a large number of
entities are affected, the project would probably benefit from the user writing a Roo add-on which
will automatically manage the ITDs just as Roo does for JPA.
• Security authorisation: Sometimes DAOs are used to apply security authorisation rules. It
is possible to protect persistence methods on the DAOs and therefore go relatively low
in the control flow to protecting the accessibility of entities. In practice this rarely works
well, though, as most authorisation workflows will target a use case as opposed to the
entities required to implement a use case. Further, the approach is unsafe as it is possible
to transitively acquire one entity from another without observing the authorisation rules (eg
person.getPartner().getChildren().get(1).setFirstName("Ben")). It is also quite crude in
that it does not support transparent persistence correctly, in that the example modification of the
first name would flush to the database without any authorisation check (assuming this mutative
operation occurred within the context of a standard transactional unit of work). While it's possible
to work around many of these issues, authorisation is far better tackled using other techniques than
the DAO layer.
• Security auditing: In a similar argument to authorisation, sometimes DAOs are advocated for
auditing purposes. For the same types of reasons expressed for authorisation, this is a suboptimal
approach. A better way is to use AOP (eg AspectJ field set pointcuts), a JPA flush event handle, or
a trigger-like model within the database.
• Finders: If you review existing DAOs, you'll find the main difference from one to another is the
finder methods they expose. Dynamic finders are automatically supported by Roo and introduced
1.1.3.BUILD-SNAPSHOT 33
Application Architecture
directly to the entity, relieving the user from needing DAOs for this reason. Furthermore, it is quite
easy to hand-write a finder within the entity (or an ITD that adds the finder to the entity if a separate
compilation unit is desired).
• Architectural reasons: Often people express a preference for a DAO because they've always done
it that way. While maintaining a proven existing approach is generally desirable, adopting Roo for
an application diminishes the value of a DAO layer to such an extent that it leaves little (if any)
engineering-related reasons to preserve it.
It's also worth observing that most modern RAD frameworks avoid DAO layers and add persistence
methods directly to entities. If you review similar technologies to Roo, you will see this is avoidance
of a DAO layer is commonplace, mainstream and does not cause problems.
Naturally you can still write DAOs by hand if you want to, but the majority of Roo add-ons will not be
compatible with such DAOs. As such you will not receive automated testing or MVC controllers that
understand your hand-written DAOs. Our advice is therefore not to hand write DAOs. Simply use the
entity methods provided by @RooEntity, as it's engineering-wise desirable and it's also far less effort
for you to write and maintain.
If you are interested in DAO support despite the above, ROO-301 represents an enhancement request
for more flexibility around DAOs. You are invited to track this enhancement request or vote for it if
you would like to see this. We plan on actioning this enhancement request in the next version of Roo.
1.1.3.BUILD-SNAPSHOT 34
Chapter 4. Usage and Conventions
In this chapter we'll introduce how to use the Roo tool itself. We'll cover typical conventions you'll
experience when using Spring Roo.
• Numerous shell features which ensure the primary Roo-specific user interface is friendly and
learnable
• Only using popular, mainstream technologies and standards within Roo applications
• Making sure Roo works the way a reasonable person would expect it to
• Forgiving mistakes
The last two points are what we're going to discuss in this section.
Making sure Roo works the way you would expect it to is reflected in a number of key design
decisions that basically boil down to "you can do whatever you want, whenever you want, and Roo
will automatically work in with you". There are obviously limits to how far we can take this, but as
you use Roo you'll notice a few operational conventions that underpin this.
Let's start by looking at file conventions. Roo will never change a .java file in your project unless you
explicitly ask it to via a shell command. In particular, Roo will not modify a .java file just because
you apply an annotation. Roo also handles .xml files in the same manner. There are only two file types
that may be created, updated or deleted by Roo in an automatic manner, those being .jspx files and
also AspectJ files which match the *_Roo_*.aj wildcard.
In terms of the AspectJ files, Roo operates in a very specific manner. A given AspectJ filename
indicates the "target type" the members will be introduced into and also the add-on which governs the
file. Roo will only ever permit a given AspectJ file to be preserved if the target type exists and the
corresponding add-on requests an ITD for that target type. Nearly all add-ons will only create an ITD
if there is a "trigger annotation" on the target type, with the trigger annotation always incorporating an
@Roo prefix. As such, if you never put any @Roo annotation on a given .java file, you can be assured
Roo will never create any AspectJ ITD for that target type. Refer to the file system conventions section
for related information.
You'll also notice when using Roo that it automatically responds to changes you make outside Roo.
This is achieved by an auto-scaling file system monitoring mechanism. This basically allows you to
create, edit or delete any file within your project and if the Roo shell is running it will immediately
1.1.3.BUILD-SNAPSHOT 35
Usage and Conventions
detect your change and take the necessary action in response. This is how round-tripping works without
you needing to include Roo as part of your build system or undertake any crude mass generation steps.
What happens if the Roo shell isn't running? Will there be a problem if you forget to load it and make
a change? No. When Roo starts up it performs a full scan of your full project file system and ensures
every automatically-managed file that should be created, updated or deleted is handled accordingly.
This includes a full in-memory rebuild of each file, and a comparison with the file on disk to detect
changes. This results in a lot more robust approach than relying on relatively coarsely-grained file
system timestamp models. It also explains why if you have a very big project it can take a few moments
for the Roo shell to startup, as there is no alternative but to complete this check for actions that happened
when Roo wasn't running.
The automated startup-time scan is also very useful as you upgrade to newer versions of Roo. Often a
new version of Roo will incorporate enhancements to the add-ons that generate files in your project.
The startup-time scan will therefore automatically deliver improvements to all generated files. This is
also why you cannot edit files that Roo is responsible for managing, because Roo will simply consider
your changes as some "old format" of the file and rewrite the file in accordance with its current add-ons.
Not being able to edit the generated files may sound restrictive, as often you'll want to fine-tune just
some part of the file that Roo has emitted. In this case you can either write a Roo add-on, or more
commonly just write the method (or field or constructor etc) directly in your .java file. Roo has a
convention of detecting if any member it intends to introduce already exists in the target type, and if
it does Roo will not permit the ITD to include that member. In plain English that means if you write a
method that Roo was writing, Roo will remove the method from its generated file automatically and
without needing an explicit directive to do so. In fact the Roo core infrastructure explicitly detects
buggy add-ons that are trying to introduce members that an end user has written and it will throw an
exception to prevent the add-on from doing so.
This talk of exceptions also lets us cover the related usability feature of being forgiving. Every time
Roo changes your file system or receives a shell command, it is executed within a quasi-transactional
context that supports rollback. As a result, if anything goes wrong (such as you made a mistake when
entering a command or an add-on has a problem for whatever reason) the file system will automatically
rollback to the state it was before the change was attempted. The cascading nature of many changes (ie
you add a field to a .java file and that changes an AspectJ ITD and that in turn changes a web .jspx
etc) is handled in the same unit of work and therefore rolled back as an atomic group when required.
Before leaving this discussion on usability, it's probably worth pointing out that although the Roo
shell contains numerous commands, you don't need to use them. You are perfectly free to perform
any change to your file system by hand (without the help of the Roo shell). For example, there are
commands which let you create .java files or add fields to them. You can use these commands or you
can simply do this within your IDE or text editor. Roo's automatic file system monitoring will detect the
changes and respond accordingly. Just work the way you feel most comfortable - Roo will respect it.
1.1.3.BUILD-SNAPSHOT 36
Usage and Conventions
• Tab completion: The cornerstone of command-line usability is tab assist. Hit TAB (or
CTRL+SPACE if you're in SpringSource Tool Suite) and Roo will show you the applicable options.
• Command hiding: Command hiding will remove commands which do not make sense given the
current context of your project. For example, if you're in an empty directory, you can type project,
hit TAB, and see the options for creating a project. But once you've created the project, the project
command is no longer visible. The same applies for most Roo commands. This is nice as it means
you only see commands which you can actually use right now. Of course, a full list of commands
applicable to your version of Roo is available in the command index appendix and also via help.
• Contextual awareness: Roo remembers the last Java type you are working with in your current shell
session and automatically treats it as the argument to a command. You always know what Roo
considers the current context because the shell prompt will indicate this just before it writes roo>. In
the command index you might find some options which have a default value of '*'. This is the marker
which indicates "the current context will be used for this command option unless you explicitly
specify otherwise". You change the context by simply working with a different Java type (ie specify
an operation that involves a different Java type and the context will change to that Java type).
• Hinting: Not sure what to do next? Just use the hint command. It's the perfect lightweight substitute
for documentation if you're in a hurry!
• Inbuilt help: If you'd like to know all the options available for a given command, use the help
command. It lists every option directly within the shell.
• Automatic inline help: Of course, it's a bit of a pain to have to go to the trouble of typing help then
hitting enter if you're in the middle of typing a command. That's why we offer inline help, which
is automatically displayed whenever you press TAB. It is listed just before the completion options.
To save screen space, we only list the inline help once for a given command option. So if you type
project --template TAB TAB TAB, the first time you press TAB you'd see the inline help and
the completion options
• Scripting and script recording: Save your Roo commands and play them again later.
The scripting and script recording features are particularly nice, because they let you execute a series
of Roo commands without typing them in.
To execute a Roo script, just use the script command. When you use the script command you'll need
to indicate the script to run. We ship a number of sample scripts with Roo, as discussed earlier in the
Exploring Roo Samples section.
What if you want to create your own scripts? All you need is a text editor. The syntax of the script is
identical to what you'd type at the Roo shell. Both the Roo shell and your scripts can contain inline
comments using the ; and // markers, as well as block comments using the /* */ syntax.
A really nice script-related feature of the Roo shell is that it will automatically build a script containing
the commands you entered. This file is named log.roo and exists in your current working directory.
Here's a quick example of the contents:
// Spring Roo ENGINEERING BUILD [rev 553:554M] log opened at 2009-12-31 08:10:58
project --topLevelPackage roo.shell.is.neat
// [failed] persistence setup --database DELIBERATE_ERROR --provider HIBERNATE
persistence setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE
quit
1.1.3.BUILD-SNAPSHOT 37
Usage and Conventions
// Spring Roo ENGINEERING BUILD [rev 553:554M] log closed at 2009-12-31 08:11:37
In the recorded script, you can see the version number, session start time and session close times are
all listed. Also listed is a command I typed that was intentionally incorrect, and Roo has turned that
command into a comment within the script (prefixed with // [failed]) so that I can identify it and it
will not execute should I run the script again later. This is a great way of reviewing what you've done
with Roo, and sharing the results with others.
Before we cover how to use an IDE, it's worth mentioning that you don't strictly need one. With Roo
you can build an application at the command line, although to be honest you'll get more productivity via
an IDE if it's anything beyond a trivial application. If you would prefer to use the command line, you
can start a fresh application using the Roo shell, edit your .java and other files using any text editor,
and use the perform commands to compile, test and package your application ready for deployment.
You can even use mvn tomcat:run to execute a servlet container, and Roo add-ons let you deploy
straight to a cloud environment like Google App Engine. Again, you'll be more productive in an IDE,
but it's nice to know Roo doesn't force you to use an IDE unless you'd like to use one.
In relation to IDEs, we highly recommend that you use SpringSource Tool Suite (STS). STS is a
significantly extended version (and free!) of the pervasive Eclipse IDE. From a Roo perspective, STS
preintegrates the latest AspectJ Development Tools (AJDT) and also offers an inbuilt Roo shell. The
inbuilt Roo shell means you do not need to run the normal Roo shell if you are using STS. You'll also
have other neat Roo-IDE integation features, like the ability to press CTRL+R (or Apple+R if you're
on an Apple) and a popup will allow you to type a Roo command from anywhere within the IDE.
Another nice feature is the shell message hotlinking, which means all shell messages emitted by Roo
are actually links that you can click to open the corresponding file in an Eclipse editor. There are other
goodies too, like extra commands to deploy to SpringSource tc Server.
You'll need to use STS 2.5 if you'd like to use Roo 1.1, which at the time of writing represents the
latest version of both tools. Because the release cycle of STS and Roo differ, when you download
STS you'll generally find it includes a version of Roo that might not be the absolute latest. This is
not a problem. All you need to do is ensure you're using the latest release of STS and then within the
IDE select Window > Preferences > Spring > Roo Support. Next select "Add..." and find the directory
which contains the latest Roo release. You probably also want to tick the newly-selected Roo release,
making it the default for your projects when they're imported into STS.
Naturally Roo works well with standard Eclipse as well. All you need to do is ensure you install
the latest AspectJ Development Tools (AJDT) plugin. This will ensure code assist and incremental
compilation works well. We also recommend you go into Window > Preferences > General >
Workspace and switch on the "Refresh automatically" box. That way Eclipse will detect changes made
to the file system by the externally-running Roo shell. It's also recommended to install the m2eclipse
plugin, which is automatically included if you use STS and is particularly suitable for Roo-based
projects.
When using AJDT you may encounter a configuration option enabling you to "weave" the JDT. This
is on by default in STS, so you're unlikely to see the message if using STS. If you are prompted (or
1.1.3.BUILD-SNAPSHOT 38
Usage and Conventions
locate the configuration settings yourself under the Window > Preferences > JDT Weaving menu), you
should enable weaving. This ensures the Java Editor in Eclipse (or STS) gives the best AspectJ-based
experience, such as code assist etc. You can also verify this setting is active by loading Eclipse (or
STS) and selecting Window > Preferences > JDT Weaving.
If you're using m2eclipse, you won't need to use the perform eclipse command to setup your
environment. A simple import of the project using Eclipse's File > Import > General > Maven Projects
menu option is sufficient.
Irrespective of how you import your project into Eclipse (ie via the perform eclipse command or
via m2eclipse) you should be aware that the project will not be a Web Tools Project (WTP) until
such time as you install your first web controller. This is usually undertaken via the controller all or
controller scaffold command. If you have already imported your project into Eclipse, simply complete
the relevant controller command and then re-import. The project will then be a WTP and offer the
ability to deploy to an IDE-embedded web container. If you attempt to start a WTP server and receive
an error message, try right-clicking the project and selecting Maven > Update Project Configuration.
This often resolves the issue.
If you're using IntelliJ, we are pleased to report that IntelliJ now supports Roo. This follows the
completion of ticket IDEA-26959, where you can obtain more information about the AspectJ support
now available in IntelliJ.
If you're using any IDE other than STS, the recommended operating pattern is to load the standalone
Roo shell in one operating system window and leave it running while you interact with your IDE.
There is no formal link between the IDE and Roo shell. The only way they "talk" to each other is by
both monitoring the file system for changes made by the other. This happens so quickly that you're
unlikely to notice, and indeed internally to Roo we have an API that allows the polling-based approach
to be replaced with a formal notification API should it ever become necessary. As discussed in the
usability section, if you forget to load the Roo shell and start modifying your project anyway, all you
need to do is load the Roo shell again and it will detect any changes it needs to make automatically.
Roo will create a new pom.xml file whenever you use the project command. The POM will contain
the following Roo-specific considerations:
• A reference to the Roo annotations JAR. This JAR exists at development time only and has a scope
that prevents it from being included in resultant WAR files.
• A correct configuration of the Maven AspectJ plugin. This includes a reference to the Spring Aspects
library, which is important to Roo-based applications. Spring Aspects is included within Spring
Framework.
There are no other Roo changes to the POM. In particular, there is no requirement for the POM to
include Roo as part of any code generation step. Roo is never used in this "bulk generation style".
1.1.3.BUILD-SNAPSHOT 39
Usage and Conventions
If you are interested in ensuring a build includes the latest Roo code generation output, you can cause
Maven or equivalent build system to execute roo quit. The presentation of the quit command line
option will cause the Roo shell to load, perform its startup-time scan (which identifies and completes
any required changes to generated files) and then exit.
Those seeking Ant/Ivy instead of Maven support are encouraged to vote for issue ROO-91. The
internals of Roo do not rely on Maven at all. Nonetheless we have deferred it until we see sufficient
community interest to justify maintaining two build system environments.
Roo applications follow the standard Maven-based directory layout. We have also placed Spring
application context-related files (both .xml and .properties) in the recommended classpath
sub-directory for Spring applications, META-INF/spring.
• Don't edit any files that Roo code generates (see the Usability Philosophy for details).
• Before installing any new technology, check if Roo offers a setup command and use it if present
(this will ensure the seutp reflects our recommendations and the expectations of other add-ons).
• Ensure you leave the Roo shell running when creating, updating or deleting files in your project.
• Remember you'll still need to write Java code (and JSPs for custom controllers). Have the right
expectations before you start using Roo. It just helps you - it doesn't replace the requirement to
program.
• Check the Known Issues section before upgrading or if you experience any problems.
• Refer to the Roo Resources section for details of how to get assistance with Roo, such as the forum
and issue tracking database. We're happy to hear from you.
1.1.3.BUILD-SNAPSHOT 40
Usage and Conventions
As detailed in the main text, Roo supports a special protocol scheme called httppgp://. This
performs a Pretty Good Privacy (PGP) detached signature verification before proceeding to
download the main resource. We use this as a key foundation of our add-on security model.
Many Roo commands download items from the Internet, and anytime a httppgp:// scheme is
encountered a PGP verification will take place.
One common case is if you are using the addon install command. An example of the error if the
PGP detached signature is untrusted is shown below:
Essentially you need to decide if you trust the PGP key ID or not. There is a pgp key view
command that will help you learn more about a given key ID if you would like to use it. You
can also view keys at public PGP key servers such as http://pgp.mit.edu/. You essentially have
two options to cause an untrusted httppgp download to be performed by Roo:
1. Use the pgp trust command to trust the PGP key ID shown in the error message. This will
permanently trust the key ID, and it will show up if you use the pgp list trusted keys command
(you can of course remove it via the pgp untrust command as well). All of the keys you trust
are stored in ~/.spring_roo_pgp.bpg, which is a binary encoded PGP key store which you
can also view and manage using normal PGP tools. An example of the command to trust a
key is shown below:
2. Alternately, you can decide to simply switch off key verification and automatically trust any
keys encountered. Such keys are stored in your ~/.spring_roo_pgp.bpg file. You should use
caution with this command, although it can be convenient if you'd simply like to install some
new add-ons and their dependencies without considering every key used to sign them. To use
automatic trust, simply type pgp automatic trust and press enter:
Once one of the above have been completed, you can repeat the command that attempted to
download a httppgp:// resource and it should succeed.
It is easy to extend the capabilities of Spring Roo with installable add-ons. This section will offer
a basic overview of Roo's add-on distribution model and explain how to install new add-ons. If
you're considering writing an add-on, please refer to the more advanced information in Part III of this
reference guide.
First of all, it's important to recognize that Roo ships with a large number of base add-ons. These
built-in add-ons may be all you ever require. Nevertheless, there is a growing community of add-ons
1.1.3.BUILD-SNAPSHOT 41
Usage and Conventions
written by people outside the core Roo team. Because the core Roo team do not write these add-ons,
we've needed to implement an infrastructure so that external people can share their add-ons and make
it easy for you to install them.
Roo's add-on distribution system encourages individual add-on developers to host their add-on
web site (we don't believe in a central model where we must host add-ons on our servers).
The main requirement an add-on developer needs to fulfill is their add-ons must be in OSGi
format and their web site must include an OSGi Bundle Repository (OBR) index file. While
Roo internally uses OSGi and all modules are managed as OSGi bundles, this is transparent
and you do not need any familiarity with OSGi or bundles to work with the Roo add-on
installation system. An OBR file is usually named repository.xml and it is available over HTTP.
If you're curious what these OBR files look like, you can view the Spring Roo OBR repository
at http://spring-roo-repository.springsource.org/repository.xml. Within an OBR file each available
Roo-related add-on is listed, along with the URL where it is published. The URLs look similar to
normal URLs, except they will usually specify a httppgp:// protocol scheme (instead of the more
common http://).
The httppgp:// protocol scheme is how we achieve a level of security with add-ons. Obviously with
every add-on developer able to host add-ons on any web site they nominate, it would be difficult for
you to know whether a particular add-on can be trusted. You probably only want to trust add-ons
from people you already trust or have cause to trust. To this end Roo offers automatic PGP-related
signature capabilities for any URL that uses the httppgp:// scheme. Most Roo add-ons use this
scheme. The internal step-by-step process that takes place is Roo essentially downloads the URL +
".asc" over HTTP. This file is a standard PGP detached signature file. PGP detached signature files
are increasingly common, with most Maven Central artifacts now also offering a signature file. If the
user's Roo installation trusts the key ID that signed the PGP detached signature, Roo will proceed to
download the URL. If the user's Roo installation does not trust the key ID, an error will be displayed and
the download will fail (and in turn the add-on installation process will fail if the bundle was specified
as a httppgp:// URL). Please see the side-bar for details on how you can trust different key IDs and
use the PGP-related commands in Roo.
Completing the picture of Roo's add-on distribution infrastructure is RooBot. This is a VMware-hosted
service that essentially indexes the important content in all public Roo OBR files. RooBot ensures that
add-ons it indexes are only available over httppgp://, reflecting the security model above. Add-on
developers can be added into RooBot's index in just a couple of minutes via an automated process.
Every time Roo loads, it automatically downloads the latest RooBot index file. This is how it knows
which public add-ons are available.
Enough with the theory, let's move on to the fun piece. In Spring Roo you simply use the shell to
locate new add-ons. To review the list of known add-ons you can use the addon list or addon search
command. This lists all add-ons that are in the RooBot-maintained index mentioned above:
1.1.3.BUILD-SNAPSHOT 42
Usage and Conventions
There are various options you can pass to the search command to see more lines per result, perform
filtering and so on. Just use --TAB as usual to see these options.
If you can't see the add-on you're looking for, you can repeat the command with the optional --refresh
option. This will refresh your local RooBot index from our server.
To review details about a specific add-on, use the addon info id command as mentioned in the hint
at the bottom of the search results. There is also a related command called addon info bundle which
requires a "bundle symbolic name", which is usually the add-on's top-level package. However, it's
often more convenient to use the search result "ID" number (to the left hand side of each row) rather
than typing out a bundle symbolic name. Let's try this. To view details about the second add-on listed,
enter this command:
In the above output "BSN" means bundle symbolic name, which is the alternate way of referring to a
given add-on. The output also shows you the Roo shell commands that are available via the add-on.
These commands are automatically seen by the Roo shell, so if you typed in this case "hades install"
without first having installed the add-on, Roo would have performed a search and shown you this
add-on offered the command. This is a great feature and means you can often just type commands you
think you might need and find out which add-ons offer them without performing an explicit search. A
similar feature exists for JDBC resolution if you try to reverse engineer a database for which there is
no installed JDBC driver (Roo will automatically suggest the add-on you need and instruct you which
command to use to install it).
If you decide to install a specific add-on, simply use the addon install id command:
1.1.3.BUILD-SNAPSHOT 43
Usage and Conventions
If the add-on installation is aborted with a warning that the add-on author is currently not trusted, please
review the sidebar about modifying PGP trusts. To simplify identifying add-ons from developers you
already trust, the addon search results include a "T" column which means "trusted developer". If you
see a "Y" in that column, you've already trusted that developer's PGP key and thus installation will
work without needing to add their key. If you see a "-" in that column, you'll need to first tell Roo you
trust their key (as explained in the PGP sidebar).
As per the [HINT] messages that appear immediately after installing an add-on, we appreciate your
feedback about the add-ons you use. You can use the addon feedback bundle command for this purpose,
as shown in the console text above. If you provide a rating or comment, it will show up for other people
to see when they use the addon info command.
It is generally recommended to restart Roo to ensure the add-on is properly initialized. This
theoretically isn't necessary in most cases, but it doesn't hurt.
You can also upgrade your existing add-ons by using the addon upgrade commands. To do this you
should first run the addon upgrade settings command which allows you to define the desired stability
level which is taken into account when performing the addon upgrade all command:
If you don't define a stability level through the addon upgrade settings command it defaults to
RELEASE - meaning only release versions will be upgraded (if upgrades for this level are available).
Other stability levels to choose from are RELEASE_CANDIDATE, MILESTONE, and ANY (ie
snapshots).
To list all available upgrades for currently installed add-ons you can use the addon upgrade available
command. This will provide an overview of add-ons which can be upgraded and their respective
stability levels. Furthermore, you can also upgrade individual add-ons by using the addon upgrade
bundle command which allows you to specify the add-on bundle symbolic name (and the add-on
version in case multiple versions are available). Finally, you can use the addon upgrade id command
to upgrade a specific add-on which has appeared in a search result to the latest version available.
Of course, you can remove add-ons as well. To uninstall any given add-on, just use the addon
remove command. On this occasion we'll use the bundle symbolic name (which is available via TAB
completion as is usual with Roo):
Note that all of the "addon" commands only work with add-ons listed in the central RooBot index file.
This is fine, as most public Roo add-ons are listed there. However, sometimes an add-on cannot be
published into the RooBot index file. The most common reason is that it's an add-on internal to your
organization, or perhaps it's simply not ready for public consumption.
Even if an add-on is not listed in RooBot, you can still install it. The "osgi obr url add" command can
be used to add the add-on's OBR URL to your Roo installation. This command is typically followed
by an "osgi obr start" command to download and start the add-on. Importantly, the additional security
verifications performed by RooBot are skipped given RooBot is not used with these commands (or
other related commands such as osgi start). That means bundles you start using the "osgi obr start"
command may not use httppgp:// for PGP signature verification. As such you should exercise caution
when using any installation-related commands that do not start with "addon", as such commands do
1.1.3.BUILD-SNAPSHOT 44
Usage and Conventions
not use resources subject to the RooBot security verifications. Noneless there remain legitimate use
cases for such distribution styles, so it's good to know Roo supports them as well as the more common,
user-friendly and more secure "addon" commands.
1.1.3.BUILD-SNAPSHOT 45
Chapter 5. Existing Building Blocks
Sometimes you have an existing project or database. This chapter covers how to make Spring Roo
work with it.
1. Decide whether your project files are easier to migrate to a new Roo project or it's easier to amend
your current project into a Roo project. Both approaches are valid. The following steps reflect
migrating your current project into a Roo project.
2. Convert the project to use Maven. Ensure you use the correct Maven directory layouts.
3. Move your Spring configuration and other files to the same directories as used by Roo. Start a new
Roo-based project if you're unsure where these files are typically stored.
4. Add the Roo annotations JAR and Maven AspectJ plugin to your POM. Use the same syntax as a
new Roo-based project would use.
5. Load Roo on your project and verify it does not report any errors. Resolve any errors before
continuing.
6. Add a test @RooToString annotation to one of your existing classes. Verify the ITD is created and
can be used within your IDE (if you're using an IDE). Check the new toString() method is used.
7. Start incrementally using the simpler Roo add-ons like toString support and JavaBeans. When you're
confident, move onto other Roo commands and add-ons.
If you encounter any difficulty, we recommend you consult the Roo Resources section of the reference
guide for help.
A significant new feature added to Spring Roo 1.1 was support for incremental database reverse
engineering. This feature is robust and comprehensive, and allows you to reverse engineer an existing
database in a single command. The single command doesn't even ask you any questions as it operates,
and it gracefully handles changes to your schema over time.
We recommend that you consult the incremental database reverse engineering chapter if you'd like to
work with an existing relational database.
1.1.3.BUILD-SNAPSHOT 46
Chapter 6. Removing Roo
While we'll be sad to see you go, we're happy that Roo was able to help you in some way with your
Spring-based projects. We also know that most people reading this chapter aren't actually likely to
remove Roo at all, and are simply wondering how they'd go about it in the unlikely event they ever
actually wanted to. If you have a source control system, it's actually a good idea to complete these
instructions (without checking in the result!) just to satisfy yourself that it's very easy and reliable to
remove Roo.
Roo avoids locking you in by adopting an active code generation approach, but unlike other code
generators, we place Roo generated code in separate compilation units that use AspectJ inter-type
declarations. This is vastly better than traditional active code generation alternatives like forcing you
to extend a particular class, having the code generator extend one of your classes, or forcing you to
program a model in an unnatural diagrammatic abstraction. With Roo you just get on with writing Java
code and let Roo take care of writing and maintaining the code you don't want to bother writing.
The other aspect of how Roo avoids lock-in is using annotations with source-level retention. What this
means is the annotations are not preserved in your .class files by the time they are compiled. This
in turn means you do not need the Roo annotation library in your runtime classpath. If you look at
your WEB-INF/lib directory (if you're building a web project), you will find absolutely no Roo-related
JARs. They simply don't exist. In fact if you look at your development-time classpath, only the Roo
annotation JAR library will be present - and that JAR doesn't contain a single executable line of code.
The entire behaviour of Roo is accomplished at development time when you load the Roo shell. If you
also think about the absence of executable code anywhere in your project classpath, there is no scope
for possible Roo bugs to affect your project, and there is no risk of upgrading to a later version of Roo.
Because we recommend people check their Roo-generated *_Roo_*.aj files into source control, you
don't even need to load Roo to perform a build of your project. The source-level annotation library
referred to in the previous paragraph is in a public Maven repository and will automatically be
downloaded to your computer if it's not already present. This means Roo is not part of your build
process and your normal source control system branching and tagging processes will work.
This also means that a project can "stop using Roo" by simply never loading the Roo shell again.
Because the *_Roo_*.aj files are written to disk by the Roo shell when it last ran, even if it's never
loaded again those files will still be present. The removal procedures in this chapter therefore focus on
a more complete removal, in that you no longer even want the *_Roo_*.aj files any more. That said,
there's nothing wrong with just never loading Roo again and keeping the *_Roo_*.aj files. The only
possible problem of adopting the "never load Roo again" approach is that someone might load Roo
again and those files will be updated to reflect the latest optimisations that Roo can provide for you.
1.1.3.BUILD-SNAPSHOT 47
Removing Roo
Even though it's easy to do so, there are downsides of removing Roo from your project:
• Cluttered Java classes: If the *_Roo_*.aj files are removed, their contents need to go somewhere.
That somewhere is into your .java source files. This means your .java source files will be
considerably longer and contain code that no developer actually wrote. When developers open your
.java source files, they'll need to figure out what was written by hand and is unique to the class,
what was automatically generated and then modified, and what was automatically generated and
never modified. If using Roo this problem is eliminated, as anything automatically generated is in
a separate, easily-identified source file.
• No round-trip support: Let's imagine for a moment that you've written (either by hand or via your
IDE's code generation feature) a toString() method and getter/setter pairs for all your fields. You
then decide to rename a field. Suddenly the getter, setter and toString() methods are all in error. If
you use Roo, it automatically detects your change and appropriately updates the generated code. If
you remove Roo, you'll lose this valuable round-trip support and be doing a lot more tedious work
by hand.
• No optimisations to generated files: With each version of Roo we make improvements to the
automatically-created *_Roo_*.aj files. These improvements are automatically made to your
*_Roo_*.aj files when you load a new version of Roo. These improvements occasionally fix bugs,
but more often provide new features and implement existing features more efficiently (remember
eliminating engineering trade-offs and therefore maximising efficiency is a major objective in our
mission statement). If you remove the *_Roo_*.aj files, you'll receive the code as of that date and
you'll miss out on further improvements we make.
• Loss of Roo commands: There are dozens of Roo commands available to assist you adapt to evolving
project requirements. Next month you might be asked to add JMS services to your project. With Roo
you just "jms setup". The month after you're asked about SMTP, so you just "email sender setup".
If you've eliminated Roo, you'll need to resort to much more time-consuming manual configuration
(with its associated trial and error).
• Deprecated library versions: Because Roo automatically updates your code and has a good
knowledge of your project, it's easy to always use the latest released versions of important runtime
technologies like Spring and JPA. If you stop using Roo, you'll need to manually do all of the work
involved in upgrading your project to newer versions. This will mean you're likely to end up on
older runtime library versions that have bugs, fewer features and are not maintained or supported.
With Roo you significantly mitigate this risk.
• Undesirable architectural outcomes: With Roo you achieve team-wide consistency and a solution
with a high level of engineering integrity. If developers are forced to write repetitious code
themselves and no longer enjoy optimised Roo commands, you'll likely find that over time you lose
some of the consistency and engineering advantages of having used Roo in the first place.
1.1.3.BUILD-SNAPSHOT 48
Removing Roo
• Higher cost: With the above in mind, you'll probably find development takes longer, maintenance
takes longer and your runtime solution will be less efficient than if you'd stayed with Roo.
As such we believe using Roo and continuing to use Roo makes a lot of sense. But if you're willing
to accept the trade-offs of removing Roo (which basically means you switch to writing your project
the unproductive "old fashioned way"), you can remove Roo very easily. Don't forget when in doubt
you can always defer the decision. It's not as if Roo won't let you remove it just as easily in six months
or two years from now!
As mentioned above, a simple way of stopping to use Roo is to simply never load it again. The
*_Roo_*.aj files will still be on disk and your project will continue to work regardless of whether the
Roo shell is never launched again. You can even uninstall the Roo system from your computer and
your project will still work. The advantage of this approach is you haven't lost most of the benefits of
using Roo and it's very easy to simply reload the Roo shell again in the future. This section covers the
more complete removal option should you not even want the *_Roo_*.aj files any more.
Please be aware that enhancement request ROO-222 exists to replace step 1 with a Roo command, and
ROO-330 similarly focuses on steps 2 and 3. Please vote for these enhancement requests if you'd like
them actioned, although the instructions below still provide a fast and usable removal procedure.
To remove Roo from a project, you need to import the project into Eclipse or SpringSource Tool Suite.
Once the project has been imported into Eclipse, right-click the project name in Package Explorer
and select Refactor > Push-In Refactor. If this option is missing, ensure that you have a recent
version of AJDT installed. After selecting the push-in refactor menu option, a list of all Roo inter-type
declarations will be displayed. Simply click OK. AJDT will have now moved all of the Roo inter-type
declarations into your standard .java files. The old *_Roo_*.aj files will have automatically been
deleted.
1.1.3.BUILD-SNAPSHOT 49
Removing Roo
and continue. All of the Roo statements will have now been removed. We have noticed for an unknown
reason that sometimes this operation needs to be repeated twice in Eclipse.
Roo has now been entirely removed from your project and you should re-run your tests and user
interface for verification of expected operation. It's probably a good idea to perform another branch or
tag in your source control repository so the change set is documented.
Once you've added the dependency, you're free to load Roo from within your project's directory and
start using the Roo commands again. You're also free to add @Roo annotations to any .java file that
would benefit from them, but remember that Roo is "hands off by default". What that means is if you
used the push-in refactor command to move members (eg fields, methods, annotations etc) into the
.java file, Roo has no way of knowing that they originated from a push-in refactor as opposed to
you having written them by hand. Roo therefore won't delete any members from your .java file or
override them in an inter-type declaration.
Our advice is therefore (a) don't remove Roo in the first place or (b) if you have removed Roo and go
back to using Roo again, delete the members from your .java files that Roo is able to automatically
manage for you. By deleting the members that Roo can manage for you from the .java files, you'll
gain the maximum benefit of your decision to resume using Roo. If you're unsure which members Roo
can automatically manage, simply comment them out and see if Roo provides them automatically for
you. Naturally you'll need the relevant @Roo annotation(s) in your .java files before Roo will create
any members automatically for you.
A final tip if you'd like to return to having ITDs again is that AJDT 2.0 and above offers a Refactor
> Push Out command. This may assist you in moving back to ITDs. The Edit > Undo command also
generally works if you decide to revert immediately after a Refactor > Push In operation.
1.1.3.BUILD-SNAPSHOT 50
Part II. Base Add-Ons
This part of the reference guide provides a detailed reference to the major Roo base add-ons and how they work.
This part goes into more detail than the tutorial chapter and offers a "bigger picture" discussion than the command
reference appendix.
1.1.3.BUILD-SNAPSHOT 51
Chapter 7. Base Add-On Overview
When you download the Spring Roo distribution ZIP, there are actually two major logical components
in use. The first of these is the "Roo core", which provides an environment in which to host add-ons
and provide services to them. The other component is what we call "base add-ons". A base add-on
is different from a third party add-on only in that it is included in the Roo distribution by default and
does not require you to separately install it. In addition, you cannot remove a base add-on using normal
Roo commands.
Base add-ons always adopt the package name prefix org.springframework.roo.addon. We also
have a part of Roo known as "Roo core". This relates to the core modules, and these always have
package names that start with org.springframework.roo (but excluding those with "addon" as the
next package name segment, as in that case they'd be a "base add-on"). Roo core provides very few
commands, and whatever commands it provides are generally internal infrastructure-related features
(like "poll status" or "metadata for id") or sometimes aggregate the features provided by several
individual base add-ons (eg "entity --testAutomatically").
Add-ons that do not ship with Spring Roo but are nevertheless about to be used with it are known as
"installable add-ons" (these were previously called "third-party add-ons", but we decided to change
the name in Roo 1.1 in view that SpringSource itself was publishing add-ons that were not shipping
as part of Roo and the use of the term "third-party" was confusing). Such add-ons do not appear under
the org.springframework.roo package name space. A large number of individuals and organizations
publish installable add-ons, and indeed even within the SpringSource division of VMware we have
teams publishing installable add-ons. The decision as to whether an add-on becomes a base add-on or
an installable add-on depends on a large number of factors, but in general we prefer installable add-ons
over base add-ons. This offers flexibility around release cycles, licenses, deployment footprint, code
maintenance and so on.
Of course as a user of Roo you do not need to be aware of whether a particular component is part
of Roo core, a base add-on or an installable add-on. It's just useful for us to formally define these
commonly-used terms and explain the impact on whether you need to install or uninstall a component
or not.
The individual base add-ons provided by Roo provide capabilities in the following key functional areas:
• General type management (like creation of types, toString method, JavaBean methods)
• Field management (like JSR 303 and field creation with JPA compliance)
• Dynamic finders (creation of finders without needing to write the JPA-QL for them)
1.1.3.BUILD-SNAPSHOT 52
Base Add-On Overview
• Spring Security
• Selenium testing
• Log4J configuration
We have added dedicated chapters for many of these functional areas in this, Part II of our
documentation. You can also find more introductory material concerning these areas in Part I, along
with our samples, the command reference and project resources.
1.1.3.BUILD-SNAPSHOT 53
Chapter 8. Persistence Add-On
The persistence add-on provides a convenient way to create Java Persistence API (JPA v2) compliant
entities. There are different commands available to configure JPA, create new JPA-compliant entities,
and add fields to these entities. In the following a summary of the features offered by the Spring Roo
persistence add-on:
Database Options:
• HSQL (persistent)
• H2 (in memory)
• MySQL
• Postgres
• MS SQL Server
• Sybase
• Oracle *
• DB2 *
• DB2/400
• Firebird
* The JDBC driver dependencies for these databases are not available in public Maven repositories. As
such, Roo configures a default dependency in your project pom.xml. You need to adjust it according
to your specific version of your database driver available in your private Maven repository.
Some useful hints to get started with Oracle Express (Oracle XE): After installing Oracle XE you need
to find the JDBC driver under ${oracle-xe}/app/oracle/product/10.2.0/server/jdbc/lib and
run the command:
Also, if you dont want Jetty (or Tomcat) to be conflicting with oracle-xe web-server, you should use
the following command: mvn jetty:run -Djetty.port=8090.
• EclipseLink
• Hibernate
1.1.3.BUILD-SNAPSHOT 54
Persistence Add-On
• OpenJPA
• Data Nucleus
In relation to Data Nucleus, both version 1 and version 2 are supported. Version 1 does not support
JPA 2 and should only be used if you are intending to deploy to Google App Engine. Version 2 should
be used if you are intending to deploy to VMforce cloud environments. In most cases we recommend
you use Hibernate, OpenJPA or EclipseLink.
In addition, the persistence setup command accepts optional databaseName, userName and password
attributes for your convenience. However, it's not necessary to use this command. You can easily
edit these details in the database.properties file at any time. Finally, you can also specify a
pre-configured JNDI datasource via the jndiDataSource attribute.
The persistence setup command can be re-run at any time. This means you can change your ORM
provider or database when you plan to move your application between your development setup (eg
Hibernate with HSQLDB) to your production setup (eg EclipseLink with DB2). Of course this is a
convenience only. You'll naturally experience fewer deployment issues if you use the same platform
for both development and production.
Running the persistence setup command in the Roo shell takes care of configuring several aspects in
your project:
1. JPA dependencies are registered in the project pom.xml Maven configuration. It includes the JPA
API, ORM provider (and its dependencies), DB driver, Spring ORM, Spring JDBC, Commons
DBCP, and Commons Pool
2. Persistence XML configuration with a persistence-unit preconfigured based on your choice of ORM
provider and Database. Here is an example for the EclipseLink ORM provider and HSQL database:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
By default the persistence unit is configured to build a new database on each application restart.
This helps to avoid data inconsistencies during application development when the domain model
is not yet finalized (new fields added to an entity will yield new table columns). If you feel that
your domain model is stable you can manually switch to a mode which allows data persistence
1.1.3.BUILD-SNAPSHOT 55
Persistence Add-On
across application restarts in the persistence.xml file. This is documented in the comment above the
relevant property. Each ORM provider uses different property names and values to achieve this.
database.url=jdbc\:hsqldb\:mem\:foo
database.username=sa
database.password=
database.driverClassName=org.hsqldb.jdbcDriver
This file can be edited manually, or you can use the properties set command, or by using the
databaseName, userName and password attributes of the persistence setup command. You can edit
the properties file or use any of these commands at any time.
4. A DataSource definition and a transaction manager are added to the Spring application context:
[...]
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
As you can see from the Roo shell messages there are 4 files generated (also, note that the context has
changed to the Person type in the Roo shell):
1. Person.java:
@RooJavaBean
@RooToString
@RooEntity
public class Person {
}
1.1.3.BUILD-SNAPSHOT 56
Persistence Add-On
You will notice that by default, the Person type does not contain any fields (these will be added
with the field commands or manually in the type) or methods.
2. Person_Roo_JavaBean.aj (this will only be generated when fields are added to the Person type)
The first annotation added by the entity command is the @RooJavaBean annotation. This annotation
will automatically add public accessors and mutators via an ITD for each field added to the Person
type. This annotation (like all Roo annotations) has source retention (so it will not be present in
the generated byte code).
3. Person_Roo_ToString.aj
The second annotation added to the Person type is the @RooToString annotation. This annotation
will generate a toString method for the Person type via an ITD. The toString() method will
contain a concatenated representation of all field names and their values. If you want to provide
your own toString() method alongside the Roo generated toString() method you can declare the
toStringMethod attribute in the @RooToString annotation. This attribute allows you to change the
default method name of the Roo-managed toString() (default name) method, thereby allowing your
custom toString() method alongside the Roo-managed method.
4. Person_Roo_Configurable.aj
The third annotation takes care of marking the Person type with Spring's @Configurable annotation.
This annotation allows you to inject any types from the Spring bean factory into the Person type.
The injection of the JPA entity manager (which is defined as a bean in the application context) is
possible due to the presence of the @Configurable annotation.
5. Person_Roo_Entity.aj
The fourth annotation is the @RooEntity annotation. This annotation will introduce a number of
persistence related methods into your Person type via an ITD:
@PersistenceContext
transient EntityManager Person.entityManager;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long Person.id;
@Version
@Column(name = "version")
private Integer Person.version;
1.1.3.BUILD-SNAPSHOT 57
Persistence Add-On
@Transactional
public void Person.persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
@Transactional
public void Person.remove() {
if (this.entityManager == null) this.entityManager = entityManager();
if (this.entityManager.contains(this)) {
this.entityManager.remove(this);
} else {
Person attached = this.entityManager.find(this.getClass(), this.id);
this.entityManager.remove(attached);
}
}
@Transactional
public void Person.flush() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.flush();
}
@Transactional
public Person Person.merge() {
if (this.entityManager == null) this.entityManager = entityManager();
Person merged = this.entityManager.merge(this);
this.entityManager.flush();
return merged;
}
@SuppressWarnings("unchecked")
public static List<Person> Person.findAllPeople() {
return entityManager().createQuery("select o from Person o", Person.class).getResultList();
}
@SuppressWarnings("unchecked")
public static List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
return entityManager().createQuery("select o from Person o", Person.class)
.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
}
1.1.3.BUILD-SNAPSHOT 58
Persistence Add-On
The JPA @Entity annotation is added to the Person_Roo_Entity.aj ITD. This annotation marks
the Person as persistable. By default, the JPA implementation of your choice will create a table
definition in your database for this type. Once fields are added to the Person type, they will be added
as columns to the Person table.
As can be seen, the Person_Roo_Entity.aj ITD introduces three fields by default. An id field
(which is auto-incremented), a version field (used for JPA-managed optimistic locking), and an
entityManager field which can be used by the developer to create additional persistence-related
functionality.
In addition to these three fields, the Person_Roo_Entity.aj ITD introduces a number of methods such
as persist(), remove(), merge(), flush() which allow the execution of ActiveRecord-style persistence
operations on each Roo-managed JPA entity. Furthermore, a number of persistence-related
convenience methods are provided. These methods are countPeople(), findAllPeople(),
findPerson(..), and findPersonEntries(..).
Similar to the @RooToString annotation you can change the default method name for all
persistence-related methods generated through the @RooEntity annotation. Furthermore, if you
don't want Roo to generate certain methods as part of this addon at all you can assign an empty
String as the method name which will instruct Roo to not generate the method:
@RooEntity(countMethod = "")
The entity command offers a number of optional (but very useful) attributes worth mentioning. For
example the --testAutomatically attribute can be used to have Roo to generate and maintain integration
tests for the Person type (and the persistence methods generated as part of it). Furthermore, the
--abstract and --extends attributes allow you to mark classes as abstract or inheritance patterns. Of
course this can also be done directly in the Java sources of the Person type but sometimes it is useful to
do this through a Roo command which can be scripted and replayed if desired. Other attributes allow
you to define the identifier field name as well as the identifier field type which, in turn, allows the use
of complex identifier types.
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "S-")
1.1.3.BUILD-SNAPSHOT 59
Persistence Add-On
You'll notice that the @Temporal annotation is part of the JPA specification and defines how date
values are persisted to and retrieved from the database in a transparent fashion. The @DateTimeFormat
annotation is part of the Spring framework and takes care of printing and parsing Dates to and from
String values when necessary (especially Web frontends frequently take advantage of this formatting
capability).
Also note that Roo created a Person_Roo_JavaBean.aj ITD to generate accessors and mutators for the
birthDay field and it also updated the toString() method to take the birthDay field into account.
Aside from the Date (and Calendar) type, the field command offers String, Boolean, Enum, Number,
Reference and Set types. The Reference and Set types are of special interest here since they allow you
to define relationships between your entities:
1. The field reference command will create a JPA many-to-one (default) or one-to-one relationship:
The field definition added to the Person type contains the appropriate JPA annotations:
@ManyToOne
@JoinColumn
private Car car;
The optional --cardinality command attribute allows you to define a one-to-one relationship (via
JPAs @OneToOne annotation) between Person and Car if you wish:
@OneToOne
@JoinColumn
private Car car;
You can add the mappedBy attribute to the @OneToOne annotation to define the FK name handled
by the inverse side (Car) of this relationship.
Consider the following constraint: when you delete a Person, any Car they have should also be
deleted, but not vice versa (i.e. you should be able to delete a Car without deleting its owner). In
the database, the foreign key should be in the "car" table.
@Entity
@RooJavaBean
@RooEntity
public class Person {
@Entity
@RooJavaBean
@RooEntity
public class Car {
1.1.3.BUILD-SNAPSHOT 60
Persistence Add-On
If you delete a Person from the Person list, both the Person and the Car are deleted. So the cascading
works. But if you delete a Car, the transaction will roll back and you will see an exception due
it being referenced by a person. To overcome this situation you can add the following method to
your Car.java:
@PreRemove
private void preRemove() {
this.getOwner().setCar(null);
}
This hooks into the JPA lifecycle callback function and will set the reference between Person and
Car to null before attempting to remove the record.
2. The field set command will allow you to create a many-to-many (default) or a one-to-many
relationship:
The field definition added to the Person type contains the appropriate JPA annotation:
@ManyToMany(cascade = CascadeType.ALL)
private Set<Car> cars = new HashSet<Car>();
To change the mapping type to one-to-many simply use the --cardinality attribute. To achieve a
true m:n relationship you will need to issue the field set commands for both sides of the relationship.
Like the entity command, the field command offeres a number of optional (but very useful) attributes
worth mentioning. For example, you can change the field / column name translations with the --column
attribute. Furthermore there are a number of attributes which translate directly to their equivalents
defined in JSR 303 (Bean Validation). These attributes include --notNull, --sizeMin, --sizeMax and
other related attributes. Please refer to the field command in the appendix to review the different
attributes offered.
1.1.3.BUILD-SNAPSHOT 61
Chapter 9. Incremental Database Reverse
Engineering (DBRE) Add-On
The incremental database reverse engineering (DBRE) add-on allows you to create an application tier
of JPA 2.0 entities based on the tables in your database. DBRE will also incrementally maintain your
application tier if you add or remove tables and columns.
9.1. Introduction
Traditional JPA reverse engineering tools are designed to introspect a database schema and produce
a Java application tier once. Roo's incremental database reverse engineering feature differs because
it has been designed to enable developers to repeatedly re-introspect a database schema and update
their Java application. For example, consider if a column or table has been dropped from the database
(or renamed). With Roo the re-introspection process would discover this and helpfully report errors
in the Java tier wherever the now-missing field or entity was referenced. In simple terms, incremental
database reverse engineering ensures Java type safety and easy application maintenance even if the
database schema is constantly evolving. Just as importantly, Roo's incremental reverse engineering
is implemented using the same unique design philosophy as the rest of Roo. This means very fast
application delivery, clutter-free .java source files, extensive usability features in the shell (such as tab
completion and hinting) and so on.
The DBRE commands (see Section 9.3, “DBRE Add-On commands” below) make live connections
to the database configured in your Roo project and obtain database metadata from the JDBC driver's
implementation of the standard java.sql.DatabaseMetadata interface. When the database is reverse
engineered, the metadata information is converted to XML and is stored and maintained in the .roo-dbre
file in the root directory of your project. DBRE creates JPA entities based on the table names in your
database and fields based on the column names in the tables. Simple and composite primary keys are
supported (see Section 9.5.2, “Composite primary keys” for more details) and relationships between
entities are also created using the imported and exported key information obtained from the metadata.
DBRE creates entity classes with names that are derived from the associated table name using a simple
algorithm. If a table's name contains an underscore, hyphen, forward or back slash character, an upper
case letter is substituted for each of these characters. This is also similar for column and field names.
The following tables contain some examples.
order Order.java
line_item LineItem.java
1.1.3.BUILD-SNAPSHOT 62
Incremental Database Reverse Engineering (DBRE) Add-On
EAM_MEASUREMENT_DATA_1H EamMeasurementData1h.java
COM-FOO\BAR ComFooBar.java
order order
EMPLOYEE_NUMBER employeeNumber
USR_CNT usrCnt
9.2. Installation
DBRE supports most of the relational databases that can be configured for Roo-managed projects
such as MySQL, MS SQL, and PostgreSQL. These drivers are auto-detected by Roo and you will
be prompted by the Roo shell to download your configured database's JDBC driver when you first
issue the database introspect or database reverse engineer commands (see Section 9.3, “DBRE Add-On
commands” below). For example, if you have configured your Roo project to use a MySQL database,
when the database introspect command is first issued, you will see the following console output:
You can get further information about the search result with the following command:
You can then install the latest MySQL JDBC driver by entering the following Roo command:
Alternatively, to install a different version (if available) of the driver you can use the following
command:
The JDBC driver for MySQL is immediately available for you to use. You can now enter the database
introspect and database reverse engineer commands (see Section 9.3, “DBRE Add-On commands”
below).
Note: currently there are no open-source JDBC drivers for Oracle or DB2 and Roo does not provide
OSGi drivers for these databases. If you are an Oracle or DB2 user, you will need to obtain an
1.1.3.BUILD-SNAPSHOT 63
Incremental Database Reverse Engineering (DBRE) Add-On
OSGi-enabled driver from Oracle or IBM respectively or wrap your own Oracle or DB2 driver jars
using Roo's wrapping facility. Use the addon create wrapper to turn an existing DB2 or Oracle JDBC
driver into an OSGi bundle you can install into Roo.
This command displays the database structure, or schema, in XML format. The --schema is
mandatory and for databases which support schemas, you can press tab to display a list of schemas
from your database. You can use the --file option to save the information to the specified file.
The --enableViews option when specified will also retrieve database views and display them with
the table information.
Note: the term "schema" is not used by all databases, such as MySQL and Firebird, and for these
databases the target database name is contained in the JDBC URL connection string. However the
--schema option is still required but Roo's tab assist feature will display "no-schema-required".
This command creates JPA entities in your project representing the tables and columns in your
database. As for the database introspect command, the --schema option is required and tab assistance
is available. You can use the --package option to specify a Java package where your entities will
be created. If you do not specify the --package option on second and subsequent executions of the
database reverse engineer command, new entities will be created in the same package as they were
previously created in.
Use the --testAutomatically option to create integration tests automatically for each new entity
created by reverse engineering.
The --enableViews option when specified will also retrieve database views and reverse engineer
them into entities. Note that this option should only be used in specialised use cases only, such as
those with database triggers.
You can use the --includeTables and --excludeTables option to specify tables that you want or do
not want reverse engineered respectively. The options can take one or more table names. If more
than one table is required, the tables must be enclosed in double quotes and each separated by a
space. Wild-card searching is also permitted using the asterisk (*) character to match one or more
characters or the '?' character to match exactly one character. For example:
roo> database reverse engineer --schema order --package ~.domain --includeTables "foo* bar?"
This will reverse engineer all tables who table whose name starts with 'foo' and any table called bar
with one extra character, such as 'bar1' or 'bars'.
roo> database reverse engineer --schema order --package ~.domain --excludeTables "foo* bar?"
1.1.3.BUILD-SNAPSHOT 64
Incremental Database Reverse Engineering (DBRE) Add-On
This will reverse engineer all tables except any table whose name starts with 'foo' and any table
called bar with one extra character, such as 'bar1' or 'bars'.
Note: excluding tables not only prevent entities from being created but associations are also not
created in other entities. This is done to prevent compile errors in the source code.
Since the DBRE Add-on provides incremental database reverse engineering, you can execute the
command as many times as you want and your JPA entities will be maintained by Roo, that is, new
fields will be added if new columns are added to a table, or fields will be removed if columns are
deleted. Entities are also deleted in certain circumstances if their corresponding tables are dropped.
The presence of the @RooDbmanaged annotation on an entity class triggers the creation of an AspectJ
inter-type declaration (ITD) ".aj" file where fields and their getters and setters are stored matching
the columns in the table. For example, if an entity called Employee.java is created by the database
reverse engineer command, a file called Employee_Roo_DbManaged.aj is also created and maintained
by Roo. All the columns of the matching employee table will cause fields to be created in the entity's
DbManaged ITD. An example of a DBRE-created entity is as follows:
@RooJavaBean
@RooToString
@RooDbManaged(automaticallyDelete = true)
@RooEntity(table = "employee", schema = "expenses")
public class Employee {
}
Along with the standard entity, toString, configurable ITDs, a DbManaged ITD is created if there are
more columns in the employee table apart from a primary key column. For example, if the employee
table has mandatory employee name and employee number columns, and a nullable age column the
ITD could look like this:
@Column(name = "employee_number")
@NotNull
private String Employee.employeeNumber;
1.1.3.BUILD-SNAPSHOT 65
Incremental Database Reverse Engineering (DBRE) Add-On
@NotNull
private String Employee.employeeName;
@Column(name = "age")
private Integer Employee.age;
...
}
If you do not want DBRE to manage your entity any more, you can "push-in" refactor the fields and
methods in the DbManaged ITD and remove the @RooDbManaged annotation from the .java file.
@RooJavaBean
@RooToString
@RooDbManaged(automaticallyDelete = true)
@RooEntity(identifierType = LineItemPK.class, table = "line_item", schema = "order")
public class LineItem {
}
@RooIdentifier(dbManaged = true)
public class LineItemPK {
}
1.1.3.BUILD-SNAPSHOT 66
Incremental Database Reverse Engineering (DBRE) Add-On
Roo will automatically create the entity ITD containing a field annotated with @EmbeddedId with
type LineItemPK as follows:
@PersistenceContext
transient EntityManager LineItem.entityManager;
@EmbeddedId
private LineItemPK LineItem.id;
...
}
and an identifier ITD for the LineItemPK class containing the primary key fields and the type
annotation for @Embeddable, as follows:
private LineItemPK.new() {
super();
}
...
}
If you decide that your table does not require a composite primary key anymore, the next time you
execute the database reverse engineer command, Roo will automatically change the entity to use a
single primary key and remove the identifier class if it is permitted.
One of the powerful features of DBRE is its ability to create relationships between entities
automatically based on the foreign key information in the .roo-dbre XML file. The following sections
describe the associations that can be created.
1.1.3.BUILD-SNAPSHOT 67
Incremental Database Reverse Engineering (DBRE) Add-On
For example, the database contains a product table and a supplier table. The database has been modelled
such that a product can have many suppliers and a supplier can have many products. A join table called
product_supplier also exists and links the two tables together by having a composite primary key made
up of the product id and supplier id and foreign keys pointing to each of the primary keys of the product
and supplier tables. DBRE will create a bi-directional many-to-many association. DBRE will designate
which entities are the owning and inverse sides of the association respectively and annotate the fields
accordingly as shown in the following code snippets:
@ManyToMany
@JoinTable(name = "product_supplier",
joinColumns = {
@JoinColumn(name = "prod_id") },
inverseJoinColumns = {
@JoinColumn(name = "supp_id") })
private Set<Supplier> Product.suppliers;
...
}
@ManyToMany(mappedBy = "suppliers")
private Set<Product> Supplier.products;
...
}
DBRE will also create many-to-many associations where the two tables each have composite primary
keys. For example:
@ManyToMany
@JoinTable(name = "foo_bar",
joinColumns = {
@JoinColumn(name = "foo_bar_id1", referencedColumnName = "foo_id1"),
@JoinColumn(name = "foo_bar_id2", referencedColumnName = "foo_id2") },
inverseJoinColumns = {
@JoinColumn(name = "foo_bar_id1", referencedColumnName = "bar_id1"),
@JoinColumn(name = "foo_bar_id2", referencedColumnName = "bar_id2") })
private Set<Bar> Foo.bars;
...
}
If the foreign key column represents the entire primary key (or the entire index) then the relationship
between the tables will be one to one and a bi-directional one-to-one association is created.
For example, the database contains a customer table and an address table and a customer can only have
one address. The following code snippets show the one-to-one mappings:
1.1.3.BUILD-SNAPSHOT 68
Incremental Database Reverse Engineering (DBRE) Add-On
@OneToOne
@JoinColumn(name = "address_id")
private Party Address.customer;
...
}
@OneToOne(mappedBy = "customer")
private Address Party.address;
...
}
If the foreign key column is part of the primary key (or part of an index) then the relationship between
the tables will be one to many. An example is shown below:
@OneToMany(mappedBy = "order")
private Set<LineItem> Order.lineItems;
...
}
When a one-to-many association is created, for example a set of LineItem entities in the Order entity
in the example above, DBRE will also create a corresponding many-to-one association in the LineItem
entity, as follows:
@ManyToOne
@JoinColumn(name = "order_id", referencedColumnName = "order_id")
private Order LineItem.order;
...
}
DBRE will ensure field names are not duplicated. For example, if an entity has more than one
association to another entity, the field names will be created with unique names. The following code
snippet illustrates this:
@ManyToMany
@JoinTable(name = "foo_bar",
joinColumns = {
@JoinColumn(name = "foo_bar_id1", referencedColumnName = "foo_id1"),
@JoinColumn(name = "foo_bar_id2", referencedColumnName = "foo_id2") },
inverseJoinColumns = {
@JoinColumn(name = "foo_bar_id1", referencedColumnName = "bar_id1"),
@JoinColumn(name = "foo_bar_id2", referencedColumnName = "bar_id2") })
1.1.3.BUILD-SNAPSHOT 69
Incremental Database Reverse Engineering (DBRE) Add-On
@ManyToMany
@JoinTable(name = "foo_com",
joinColumns = {
@JoinColumn(name = "foo_com_id1", referencedColumnName = "foo_id1"),
@JoinColumn(name = "foo_com_id2", referencedColumnName = "foo_id2") },
inverseJoinColumns = {
@JoinColumn(name = "foo_com_id1", referencedColumnName = "bar_id1"),
@JoinColumn(name = "foo_com_id2", referencedColumnName = "bar_id2") })
private Set<Bar> Foo.bars1;
...
}
DBRE will detect column types from the database metadata and create and maintain fields and
field annotations appropriately. Strings, dates, booleans, numeric fields, CLOBs and BLOBs are all
supported by DBRE, as well as the JSR 303 @NotNull validation constraint.
Roo checks the .java file for a field before it creates it in the ITD. If you code a field in the entity's
.java file, Roo will not create the field in the DbManaged ITD if detected in the database metadata.
For example, if your table has a column called 'name' and you have added a field called 'name' to the
.java file, Roo will not create this field in the ITD when reverse engineered.
Roo also ensures the entity's identity field is unique. For example if the @Id field is called 'id' but you
also add a field with the same name to the .java file, DBRE will automatically rename the @Id field
by prefixing it with an underscore character.
9.6. Troubleshooting
This section explains scenarios that may be encountered when using the DBRE feature.
• Executing the database introspect or database reverse engineer commands causes the message
'JDBC driver not available for oracle.jdbc.OracleDriver' to be displayed
This is due to the Oracle JDBC driver not having been installed. The driver must be installed if
you have installed Roo for the first time. See Section 9.2, “Installation”. This also applies to other
databases, for example, HSQL and H2.
• Executing the database introspect or database reverse engineer commands with the
Firebird database configured causes the message 'Exception in thread "JLine Shell"
java.lang.NoClassDefFoundError: javax/resource/ResourceException' to be displayed
This is due to the Firebird JDBC driver not having been installed. The driver must be installed if
you have installed Roo for the first time. See Section 9.2, “Installation”
When the database reverse engineer command is first run, the property determining whether tables
are created and dropped which is defined in the persistence.xml file is modified to a value that
1.1.3.BUILD-SNAPSHOT 70
Incremental Database Reverse Engineering (DBRE) Add-On
prevents new database artifacts from being created. This is done to avoid deleting the data in your
tables when unit tests are run or a web application is started. For example, if you use Hibernate as
your JPA 2.0 provider the property is called 'hibernate.hbm2ddl.auto' and is initially set to 'create'
when the project is first created. This value causes Hibernate to create tables and sequences and
allows you to run unit tests and start a web application. However, the property's value is changed
to 'validate' when the database reverse engineer command is executed. Other JPA providers such
as EclipseLink and OpenJPA have a similar property which are also changed when the command
is run. If you see this issue when running unit tests or when starting your web application after
reverse engineering, you may need to change the property back to 'create' or 'update'. Check your
persistence.xml for the property values for other JPA providers.
• The message 'Unable to maintain database-managed entity <entity name> because its
associated table name could not be found' appears in the Roo console during reverse
engineering
When DBRE first creates an entity it puts in the table name in the 'table' attribute of the @RooEntity
annotation. This is the only mechanism DBRE has for associating an entity with a table. If you
remove the 'table' attribute, DBRE has no way of determining what the entity's corresponding table
is and as a result cannot maintain the entity's fields and associations.
1.1.3.BUILD-SNAPSHOT 71
Chapter 10. Web MVC Add-On
CSS considerations: The Web UI has been tested successfully with FireFox, Opera, Safari,
Chrome, and IE. Given that IE6 is not supported any more by most players in the market, it has
a number of severe technical limitations and it has a fast declining user base Spring Roo does
not support IE6. Your mileage may vary - there will likely be issues with CSS support.
The Web MVC addons allow you to conveniently scaffold Spring MVC controllers and JSP(X) views
for an existing domain model. Currently this domain model is derived from the Roo supported JPA
integration through the entity and related field commands. As shown in the Introduction and the
Beginning With Roo: The Tutorial the Web MVC scaffolding can deliver a fully functional Web
frontend to your domain model. The following features are included:
• Automatic update of JSPX view artifacts reflecting changes in the domain model
• A fully customizable set JSP of tags is provided, all tags are XML only (no tag-backing Java source
code is required)
• Tags offer integration with the Dojo Ajax toolkit for client-side validation, date pickers, tool tips,
filtering selects etc
• Integration of Apache Tiles templating framework to allow for structural customization of the Web
user interface
• Use of cascading stylesheets to allow for visual customization of the Web user interface
• Use of Spring MVC themeing support to dynamically adjust Web user interface by changing CSS
• Internationalization of complete Web UI is supported by simply adding new message bundles (6+
languages are already suppprted)
• Client- and server-side validation based on JSR 303 constraints defined in the domain layer
The following sections will offer further details about available commands to generate Web MVC
artifacts and also the new JSP(X) round-tripping model introduced in Roo 1.1.
The first time a controller command is executed Roo will install all artifacts required for the Web
UI. The controller scaffold command will also create a Spring MVC controller for the Person entity
with the following method signatures:
1.1.3.BUILD-SNAPSHOT 72
Web MVC Add-On
public String create(@Valid Person person, The create method is triggered by HTTP POST
BindingResult result, ModelMap modelMap) {..} requests to /<app-name>/people. The submitted form
data will be converted to a Person object and validate
against JSR 303 constraints (if present). Response i
redirected to the show method.
public String createForm(ModelMap modelMap) {..} The create form method is triggered by a HTTP GET
request to /<app-name>/people?form. The resultin
form will be prepopulated with a new instance o
Person, referenced Cars and datepatterns (if needed
Returns the Tiles view name.
public String show(@PathVariable("id") Long id, The show method is triggered by a HTTP GET reques
ModelMap modelMap) {..} to /<app-name>/people/<id>. The resulting form i
populated with a Person instance identifier by the i
parameter. Returns the Tiles view name.
public String list(@RequestParam(value = "page", The list method is triggered by a HTTP GET reques
required = false) Integer page, @RequestParam(value to /<app-name>/people. This method has optiona
= "size", required = false) Integer size, ModelMap parameters for pagination (page, size). Returns th
modelMap) {..} Tiles view name.
public String update(@Valid Person person, The update method is triggered by a HTTP PUT
BindingResult result, ModelMap modelMap) {..} request to /<app-name/people. The submitted form
data will be converted to a Person object and validate
against JSR 303 constraints (if present). Response i
redirected to the show method.
public String updateForm(@PathVariable("id") Long The update form method is triggered by a HTT
id, ModelMap modelMap) { GET request to /<app-name>/people/<id>?form. Th
resulting form will be prepopulated with a Perso
instance identified by the id parameter, referenced Car
and datepatterns (if needed). Returns the Tiles view
name.
public String delete(@PathVariable("id") Long id, The delete method is triggered by a HTTP DELETE
@RequestParam(value = "page", required = false) request to /<app-name>/people/<id>. This metho
Integer page, @RequestParam(value = "size", required has optional parameters for pagination (page, size
= false) Integer size) {..} Response is redirected to the list method.
public Collection<Car> populateCars() {..} This method prepopulates the 'car' attribute. Thi
method can be adjusted to handle larger collections i
different ways (pagination, caching, etc).
void addDateTimeFormatPatterns(ModelMap Method to register date and time patterns used for dat
modelMap) {..} and time binding for form submissions.
As you can see Roo implements a number of methods to offer a RESTful MVC frontend to your
domain layer. All of these methods can be found in the PersonController_Roo_Controller.aj ITD.
Feel free to push-in any (or all) of these methods to change default behaviour implemented by Roo.
1.1.3.BUILD-SNAPSHOT 73
Web MVC Add-On
The controller scaffold command offers a number of optional attributes which let you refine
the way paths are managed and which methods should be generated in the controller. The
--disallowedOperations attribute helps you refine which methods should not be generated in the
scaffolded Roo controller. If you want to prevent several methods from being generated provide a
comma-separated list (ie: --disallowedOperations delete,update,create). You can also specify which
methods should be generated and which not in the PersonController.java source:
If you don't define a custom path Roo will use the plural representation of the simple name of the
form backing entity (in our case 'people'). If you wish you can define more complex custom paths
like /public/people or /my/special/person/uri (try to to stick to REST patterns if you can though). A
good use case for creating controllers which map to custom paths is security. You can, for example
create two controllers for the Person entity. One with the default path (/people) for public access
(possibly with delete, and update functionality disabled) and one for admin access (/admin/people).
This way you can easily secure the /admin/* path with the Spring Security addon.
Finally if you installed finders in your form backing entity you an choose to not expose these finders
through the Web MVC frontend.
The controller all command provides a convenient way to quickly generate Web MVC controllers
for all JPA entities Roo can find in your project. You need to specify the --package attribute to
define a package where these controllers should be generated. While the controller all command
is convenient, it does not give you the same level of control compared to the controller scaffold
command.
The controller class command is different from the other two controller commands shown above. It
does not generate an ITD with update, create, delete and other methods to integrate with a specific
form backing entity. Instead, this command will create a simple controller to help you get started
for developing a custom functionality by stubbing a simple get(), post() and index() method inside
the controller:
@RequestMapping("/public/car/**")
@Controller
public class CarController {
@RequestMapping
public void get(ModelMap modelMap, HttpServletRequest request,
HttpServletResponse response) {
}
1.1.3.BUILD-SNAPSHOT 74
Web MVC Add-On
@RequestMapping
public String index() {
return "public/car/index";
}
}
In addition, this controller is registered in the Web MVC menu and the application Tiles definition.
Furthermore, a simple view (under WEB-INF/views/public/car/index.jspx).
<mvc:annotation-driven conversion-service="applicationConversionService"/>
...
<bean id="applicationConversionService" class="com.springsource.vote.web.ApplicationConversionServiceF
Spring MVC uses the ConversionService when it needs to convert between two objects types -- e.g.
Date and String. To become more familiar with its features we recommend that you review the (brief)
sections on "Type Conversion" and "Field Formatting" in the Spring Framework documentation.
@RooConversionService
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
@Override
protected void installFormatters(FormatterRegistry registry) {
super.installFormatters(registry);
// Register application converters and formatters
}
As the comment indicates you can use the installFormatters() method to register any Converters and
Formatters you wish to add. In addition to that Roo will automatically maintain an ITD with Converter
registrations for every associated entity that needs to be displayed somewhere in a view. A typical use
case is where entities from a many-to-one association need to be displayed in one of the JSP views.
Rather than using the toString() method for that, a Converter defines the formatting logic for how to
present the associated entity as a String.
In some cases you may wish to customize how a specific entity is formatted as a String in JSP views.
For example suppose we have an entity called Vote. To customize how it is displayed in the JSP views
add a method like this:
@RooConversionService
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
// ...
1.1.3.BUILD-SNAPSHOT 75
Web MVC Add-On
At this point Roo will notice that the addition of the method and will remove it from the ITD much
like overriding the toString() method in a Roo entity works.
1.1.3.BUILD-SNAPSHOT 76
Web MVC Add-On
1.1.3.BUILD-SNAPSHOT 77
Web MVC Add-On
The i18n folder contains translations of the Web UI. The messages_XX.properties files are static
resources (which will never be adjusted after the initial installation) which contain commonly used
literals which are part of the Web UI. The application.properties file will be managed by Roo to contain
application-specific literals. New types or fields added to the domain layer will result in new key/value
combinations being added to this file. If you wish to translate the values generated by Roo in the
application.properties file, just create a copy of this file and rename it to application_XX.properties
(where XX represents your language abbreviation).
Roo uses XML compliant JSP files (JSPX) instead of the more common JSP format to allow
round-tripping of views based on changes in the domain layer of your project. Not all jspx files in the
target project are managed by Roo after the initial installation (although future addons may choose
to do so). Typically jspx files in sub folders under WEB-INF/views are maintained in addition to the
menu.jspx.
You will notice that this file is fairly concise compared to a normal jsp file. This is due to the extensive
use of the tag library which Roo has installed in your project in the WEB-INF/tags folder. Each tag
offeres a number of attributes which can be used to customize the appearance / behaviour of the tag
- please use code completion in your favourite editor to review the options or take a peek into the
actual tags.
All tags are completely self-reliant to provide their functionality (there are no Java sources needed to
implement specific behaviour of any tag). This should make it very easy to customize the behaviour of
the default tags without any required knowledge of traditional Java JSP tag development. You are free
to customize the contents of the Roo provided tag library to suit your own requirements. You could
even offer your customized tag library as a new addon which other Roo users could install to replace
the default Roo provided tag library.
Most tags have a few common attributes which adhere with Roo conventions to support round-tripping
of the jspx artifacts. The following rules should be considered if you wish to customize tags or jspx
files in a Roo managed project:
• The id attribute is used by Roo to find existing elements and also to determine message labels used
as part of the tag implementation. Changing a tag identifier will result in another element being
generated by Roo when the Roo shell is active.
1.1.3.BUILD-SNAPSHOT 78
Web MVC Add-On
• Roo provided tags are registered in the root element of the jspx document and are assigned a
namespace. You should be able to see element and attribute code completion when using a modern
IDE (ie SpringSource Tool Suite)
• The z attribute represents a hash key for a given element (see a detailed discussion of the hash key
attribute in the paragraph below).
The hash key attribute is important for Roo because it helps determining if a user has altered a Roo
managed element. This is the secret to round-trip support for JSPX files, as you can edit anything at
any time yet Roo will be able to merge in changes to the JSPX successfully. The hash key shown in
the "z" attribute is calculated as shown in the following table:
The hash code thus allows Roo to determine if the element is in its "original" Roo form, or if the
user has modified it in some way. If a user changes an element, the hash code will not match and this
indicates to Roo that the user has customized that specific element. Once Roo has detected such an
event, Roo will change the "z" attribute value to "user-managed". This helps clarify to the user that Roo
has adopted a "hands off" approach to that element and it's entirely the user's responsibility to maintain.
If the user wishes for Roo to take responsibility for the management of a "user-managed" element
once again, he or she can simply change the value of "z" to "?". When Roo sees this, it will replace
the questionmark character with a calculated hash code. This simple mechanism allows Roo to easily
round trip JSPX files without interfering with manual changes performed by the user. It represents a
significant enhancement from Roo 1.0 where a file was entirely user managed or entirely Roo managed.
Roo will order fields used in forms in the same sequence they appear in the domain object. The user can
freely change the sequence of form elements without interfering with Roo's round tripping approach
(Roo will honour user chosen element sequences as long as it can detect individual elements by their
id).
The user can nest Roo managed elements in in any structure he wishes without interfering with Roo
jspx round tripping. For example elements can be enclosed by HTML div or span tags to change visual
or structural appearance of a page.
Most default tags installed by Roo have a render attribute which is of boolean type. This allows users
to completely disable the rendering of a given tag (and potential sub tags). This is useful in cases where
you don't wish individual fields in a form to be presented to the user but rather have them autopopulated
through other means (ie input type="hidden"). The value of the render attribute can also be calculated
dynamically through the Spring Expression Language (SpEL) or normal JSP expression language. The
generated create.jspx in Roo application demonstrates this.
1.1.3.BUILD-SNAPSHOT 79
Web MVC Add-On
The Roo JSP addon will read JSR 303 (bean validation API) annotations found in a form-backing
object. The following convention is applied for the generation of create and update (and finder) forms:
Boolean Checkbox
Date / Calendar (@Future & @Past are recognized) Input (with JS Date chooser)
(Spring's @DateTimeFormat in combination with the
style or pattern attributes is recognized)
@OneToOne Select
@ManyToOne Select
* As mentioned above, Roo does not scaffold a HTML form element for the 'one' side of a
@OneToMany relationship. To make this relationship work, you need to provide a @ManyToOne
annotated field on the opposite side:
In case a field is annotated with @Pattern, the regular expression is passed on to the tag library where
it may be applied through the use of the JS framework of choice.
Roo will attempt to scaffold Spring MVC JSP views for all dynamic finders registered in the
form backing object. This is done automatically when the 'controller all' or 'controller scaffold'
commands are used. To prevent the automatic scaffolding of dynamic finders for the Web frontend, the
@RooWebScaffold annotation offers a attribute called 'exposeFinders' which can be set to false. This
will disable automatic scaffolding of controller methods for dynamic finders as well as the generation
of the relevant jsp artifacts.
1.1.3.BUILD-SNAPSHOT 80
Web MVC Add-On
characters Roo will silently skip the generation of jsp view artifacts for the dynamic finder in question).
More detail can be found in ticket ROO-1027.
1.1.3.BUILD-SNAPSHOT 81
Chapter 11. Google Web Toolkit Add-On
Google Web Toolkit (GWT) is a technolgy developed by Google to allow the use of existing Java
knowledge and tools to build high performance, desktop-esk web applications. Whilst GWT abstracts
away many complexities of web application development by not requiring you to learn Javascript and
HTML nor worry about browser quirks and memory leaks there is still a start-up cost associated
with GWT and the combination of Roo and GWT doesn’t absolve you completely from getting your
hands a little dirty. This chapter aims to explain how Roo can reduce the time cost involved with
getting started with GWT and does not attempt to provide a complete guide on GWT or its use. The
GWT team has written excellent documentation to help you in understanding and using GWT in your
project, the GWT documentation is especially useful when it comes to customising your application.
The GWT add-on enables you to create a complete web application for your domain model with a
single command. Once enabled, the GWT add-on will maintain your application to ensure it reflects
changes to the domain model. Currently the add-on only has a single command, which can be used to
setup GWT in any Roo project. As such, Beginning With Roo: The Tutorial can be leveraged when
starting out with Roo and GWT.
The first iteration of the add-on allowed you to generate a fully fledged GWT web application in
under a minute via the expenses script (to run the expenses script just execute the command script
expenses.roo from the Roo shell). The resulting application incorporated several hot new features
found in GWT 2.1, these include:
• data-binding support.
• incorporating all the improvements and fixes found in GWT 2.1.1, such as support for inheritance
in proxied entities; and,
• ensuring that user customisation remains intact upon each launch of Roo.
To demostrate the basic structure of the conjured GWT application a new Roo project, with a very
basic domain model, will be created using the following commands:
1.1.3.BUILD-SNAPSHOT 82
Google Web Toolkit Add-On
Upon running the gwt setup command, regardless of the presence of a domain model, a number of static
scaffold files will be copied into your project. Figure GWT.2 displays the new files and directories
(highlighted).
Figure 11.2. Figure GWT.2: New packages and files created from running “gwt setup”
1.1.3.BUILD-SNAPSHOT 83
Google Web Toolkit Add-On
Most of the interesting stuff happens in the client package so we will concentrate on its sub-packages
and files. The two sub-packages of interest are:
• managed
• this package contains all the files that are maintained by Roo. These are files that are created and
updated to reflect changes in the domain model. The GWT add-on enforces a number of rules
that mean that the add-on will not touch source. As GWT doesn’t currently support AspectJ the
standard definition of what constitutes source is different than in other add-ons, such as the entity
add-on. This will be expanded upon in the section ITDs: GWT Style below.
• scaffold
• this package contains static files that provide a framework for the other parts of the application.
The files in this package are never updated or changed, they are copied to the Roo project upon
running the gwt setup command.
After initial setup all the action occurs in the managed package. The managed package is comprised of:
• activity
• contains all classes that leverage the Activity infrastructure which is part of the new MVP
framework in GWT. These files are changed as new entities are added or removed from the
domain model.
• request
• contains all classes that revolve around the use of RequestFactory. For each entity in the domain
model a *Proxy and *Request class is created as highlighted in Figure GWT.3. More information
can be found on RequestFactory via the GWT documentation, a basic synopsis is: a *Proxy class
represents a server-side entity and a *Request class represents a server-side service.
• ui
• contains all the managed view and ui related classes and files. When an entity is added to the
domain model 8 view sets are created (a set generally includes a concrete-abstract type pair and
a ui.xml file, an example of two file sets appear in Figure GWT.4) and a ProxyRenderer class.
The file sets are as follows:
1. *DetailsView
2. *EditView
1.1.3.BUILD-SNAPSHOT 84
Google Web Toolkit Add-On
3. *ListEditor
4. *ListView
5. *MobileDetailsView
6. *MobileEditView
7. *MobileListView
8. *SetEditor
Development Mode
Development mode allows you to make changes to your application without having to recompile to
JavaScript, a time consuming operation, it also lets you to debug your application as if it were a standard
Java application. More can be found on Development Mode via the GWT team’s documentation here.
To run the application in Development Mode from the command line execute the Maven goal mvn
gwt:run, this will open the Development Mode console where you can launch the application by
clicking “Launch Default Browser”.
1.1.3.BUILD-SNAPSHOT 85
Google Web Toolkit Add-On
Development Mode requires that you are using a browser that supports the Development Mode plug-in,
you should be prompted to install the plug-in upon first launch of the application if the browser that
doesn’t currently have the plug-in installed. Alternatively you can check to see whether your browser
is supported and download the plug-in from here.
Jetty
To compile the application to JavaScript and run it in Jetty execute the Maven goal mvn
jetty:run-exploded from the command line. For larger applications compilation can take some time,
1.1.3.BUILD-SNAPSHOT 86
Google Web Toolkit Add-On
so running the application outside of Development Mode is often not practical but can be beneficial
when wanting to test the speed and size of the compiled application or to run the application in browsers
that are not currently supported by the Development Mode plug-in.
1.1.3.BUILD-SNAPSHOT 87
Google Web Toolkit Add-On
If you are viewing the application from a smartphone such as an Android device or an iPhone the
following Mobile views would be displayed:
1.1.3.BUILD-SNAPSHOT 88
Google Web Toolkit Add-On
To force the desktop browser to display the Mobile view instead of the Desktop the “m=true” query
string needs to be added to the URL used to access the application. For example to access the Mobile
view from a desktop browser whilst using Development Mode the URL would be:
http://127.0.0.1:8888/ApplicationScaffold.html?gwt.codesvr=127.0.0.1:9997&m=true
1.1.3.BUILD-SNAPSHOT 89
Google Web Toolkit Add-On
To demonstrate the changes a view class that is created, as part of running the expenses script, will
be examined, EmployeedMobileEditView.java. Prior to 1.1.1, only Roo managed source files were
created, so upon running expenses.roo a singular EmployeedMobileEditView.java was created. Any
changes that Roo needed to make to this file as result of modifying the server-side Employee entity
would cause user made changes to be overwritten.
As of Roo 1.1.1 two class files are created for each class that Roo may
need to manage as a result of changes to entities. In addition to the singular
EmployeedMobileEditView.java a EmployeedMobileEditView_Roo_Gwt.java file is also created
from which EmployeedMobileEditView extends. All changes that Roo needs to make to will occur
ONLY in EmployeedMobileEditView_Roo_Gwt and the end-user has the ability to leverage the Roo
managed code or override it.
Following Roo convention a managed abstract class from which a concrete class extends is suffixed
with “_Roo_Gwt”, a warning is also placed at the top of the source file. If a class is not referenced
by another type only a warning is placed at the top of the source file. These naming conventions and
warnings serve to highlight that this file is “owned” by Roo and a user shouldn’t make changes to
the file.
• To stop the add-on recreating a field just create an invisible element with an id attribute equal
to the field not be displayed. For example if the field “supervisor” wasn’t to be displayed the
declared element in “boundElementHolder” would need to be replaced by <div id=”supervisor”
style=”display:none”/>. Alternatively a adding “display:none” to the standard declared element’s
style attribute can just be added.
Roo will re-order elements based on the order found in the underlying entity.
• The add-on will only make changes to the abstract class, never the concrete type. NEVER.
1.1.3.BUILD-SNAPSHOT 90
Google Web Toolkit Add-On
• Roo managed files are suffixed with _Roo_Gwt and have a warning comment in the first line
notifying the user should not edit the file.
• When a user adds/deletes/edits a field in a monitored Entity the addon will make appropriate changes
in the mirrored types abstract classes.
• When an entity is deleted, or the @RooEntity annotation is removed, the mirrored types will remain
in play as to remain consistent with not touch user source.
• Roo non-destructively manages a UiBinder xml file, thought formatting is lost in the process.
The transition to the new abstract-concrete model and its associated benefits is not an automatic one.
To take advantage of the new abstract-construct model in GWT add-on you will need to inherit from
the respective *_Roo_Gwt files and optionally remove the methods in the concrete type that have been
declared in the *_Roo_Gwt file.
11.8. Troubleshooting
Known GWT Issues
Whilst a number of issues have been resolved in the GWT 2.1.1 there are still two problems you will
most likely come across.
• RequestFactory doesn't support is*()/had*() methods for primitive booleans and EditorModel
doesn't realise that primitive types are now supported in Proxies, which means that primitives are
still not supported in the GWT add-on.
• “mvn clean gwt:compile” doesn’t work and a “mvn clean compile gwt:compile” needs to be used.
1.1.3.BUILD-SNAPSHOT 91
Chapter 12. JSON Add-On
There are a number of ways to work with JSON document serialization and desrialization in
Roo projects:
Option 1: Built-in JSON handling managed in domain layer (discussed in this section)
Option 2: Spring MVC detects the Jackson library in the application classpath
The JSON add-on offers JSON support in the domain layer as well as the Spring MVC scaffolding. A
number of methods are provided to facilitate serialization and deserialization of JSON documents into
domain objects. The JSON add-on makes use of the Flexjson library.
1. Annotating a target type with the default @RooJson annotation will prompt Roo to create an ITD
with the following four methods:
This method has a String parameter representing the JSON document and returns a domain type
instance if the document can be serialized by the underlying deserializer.
This method will convert a collection of the target type, provided as method parameter, into a valid
JSON document containing an array.
This method will convert a JSON array document, passed in as a method parameter, into a collection
of the target type.
1.1.3.BUILD-SNAPSHOT 92
JSON Add-On
The @RooJson annotation can be used to customize the names of the methods being introduced
to the target type. Furthermore, you can disable the creation of any of the above listed methods
by providing an empty String argument for the unwanted method in the @RooJson annotation.
Example:
@RooJson(toJsonMethod="", fromJsonMethod="myOwnMethodName")
2. The json add command used from the Roo shell will introdroduce the @RooJson annotation into
the specified target type.
3. The json all command will detect all domain entities in the project and annotate all of them with
the @RooJson annotation.
@RooWebSAcaffold(..., exposeJson=false)
If Json scaffolding is enabled Roo will provide the following methods via its Spring MVC controllers:
1. @RequestMapping(headers = "Accept=application/json")
@ResponseBody
public String listJson() {
return Owner.toJsonArray(Owner.findAllOwners());
}
As you can see this method takes advantage of Springs request mappings and will respond to HTTP
GET requests which contain a 'Accept=application/json' header. The @ResponseBody annotation
is used to serialize the JSON document.
To test the functionality with curl you can try out the Roo pet clinic sample script (run roo> script
clinic.roo; then quit the Roo shell and start Tomcat 'mvn tomcat:run'):
This method accepts a HTTP GET request with a @PathVariable for the requested Owner ID. The
owner is serialized and returned as JSON document if found, otherwise a HTTP 404 (NOT FOUND)
status code is returned. The accompanying curl command is as follows:
1.1.3.BUILD-SNAPSHOT 93
JSON Add-On
This method accepts a JSON document sent via HTTP POST converts it into an Owner instance
and persists that new instance before returning a HTTP 201 (CREATED) status code. The
accompanying curl command is as follows:
This method accepts a document containing a JSON array sent via HTTP POST and converts the
array into Owner instances which are then persisted. The method returns a HTTP 201 (CREATED)
status code. The accompanying curl command is as follows:
This method accepts a JSON document sent via HTTP PUT and converts it into an Owner instance
before attempting to merge it with an existing record. If the xisting record is not found a HTTP 404
(NOT FOUND) status code is sent to the client, otherwise a HTTP 200 (OK) status code is sent.
The accompanying curl command is as follows:
1.1.3.BUILD-SNAPSHOT 94
JSON Add-On
}
return new ResponseEntity<String>(HttpStatus.OK);
}
This method accepts a document containing a JSON array sent via HTTP PUT and converts the
array into Owner instances which are then merged. The method returns a HTTP 201 (CREATED)
status code. The accompanying curl command is as follows:
This method accepts a HTTP DELETE request with a @PathVariable identifying the Owner record
marked for deletion. HTTP status code 200 (OK) is returned if an Owner record with the given ID
was found, otherwise HTTOP status code 404 (NOT FOUND) is returned. The accompanying curl
command is as follows:
8. [Optional] Roo will also generate a method to retrieve a document containing a JSON array if the
form backing object defines dynamic finders. Here is an example taken from VisitController in the
pet clinic sample application:
This method accepts a HTTP GET request with a number of request parameters which define the
finder method as well as the finder method arguments. The accompanying curl command is as
follows:
curl -i -H Accept:application/json
http://localhost:8080/petclinic/visits?find=ByDescriptionAndVisitDate%26description=test%26vis
If you need help configuring the serialization or deserialization process of JSON documents which is
handled by the FlexJson library please refer to their reference documentation.
1.1.3.BUILD-SNAPSHOT 95
Chapter 13. Apache Solr Add-On
The Apache Solr add-on provides integration between the Roo generated domain model and the
Apache Solr search platform. If you haven't heard of the open source Solr system, here's a quick
description from the project web site:
“Solr is the popular, blazing fast open source enterprise search platform from the Apache Lucene
project. Its major features include powerful full-text search, hit highlighting, faceted search, dynamic
clustering, database integration, and rich document (e.g., Word, PDF) handling. Solr is highly scalable,
providing distributed search and index replication, and it powers the search and navigation features of
many of the world's largest internet sites.”
“Solr is written in Java and runs as a standalone full-text search server within a servlet container
such as Tomcat. Solr uses the Lucene Java search library at its core for full-text indexing and
search, and has REST-like HTTP/XML and JSON APIs that make it easy to use from virtually
any programming language. Solr's powerful external configuration allows it to be tailored to almost
any type of application without Java coding, and it has an extensive plugin architecture when more
advanced customization is required.”
This command installs the SolrJ driver dependency into the project pom.xml and registers your Solr
server in application context so it can be injected whereever you need it in your project.
This command allows you to mark an individual entity for automatic Solr indexing. The
@RooSolrSearchable annotation will be added to the target entity (Person). Furthermore, the
following ITD is generated:
@Autowired
1.1.3.BUILD-SNAPSHOT 96
Apache Solr Add-On
@PostUpdate
@PostPersist
private void Person.postPersistOrUpdate() {
indexPerson(this);
}
@PreRemove
private void Person.preRemove() {
deleteIndex(this);
}
1.1.3.BUILD-SNAPSHOT 97
Apache Solr Add-On
The ITD introduces two search methods; one for conducting simple searches against Solr documents
for Person, and another one which works with a preconfigured SolrQuery object. The SolrQuery
object allows you to leverage all functionalities of the Solr search server (like faceting, sorting, term
highliting, pagination, etc).
The indexPerson(..) and indexPeople(..) methods allow you to add new person instances or even
collections of persons to the Solr index. The deleteIndex(..) method allows you to remove a person
from the Solr index.
All indexing, and delete operations are executed in s separate thread and will therefore
not impact the performance of your Web application (this is currently achieved through the
SolrSearchAsyncTaskExecutor.aj aspect).
Furthermore, to trigger automatic indexing of new person instances (or updated person instances)
this itd registers the postPersistOrUpdate() method which hooks into the JPA lifecycle through the
JPA @PostUpdate and @PostPersist annotations. Similarly, the preRemove() method hooks in the
JPA lifecylce through the @PreRemove annotation.
This command will mark all entities in the project for automatic Solr indexing. The generated
functionality is the same as shown above.
By default all fields in a domain entity are indexed as dynamic fields (defined in the default schema.xml
which Solr ships with). The default format of a field name is as follows:
<simple-entity-name>.<field-name>_<field-type>
person.birthday_dt
This ensures each field is uniquely mapped across your domain model by prepending the entity name
followed by the field name and field type (which is used to trigger the dynamic field mapping). You
can change field names by adding a @Field annotation to a field in the domain object (ie Person) which
contains your own field (you need to provide a field definition in the Solr schema for it as well):
@Field("my:field:name:birthday")
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "S-")
private Date birthDay;
1.1.3.BUILD-SNAPSHOT 98
Apache Solr Add-On
To index existing DB entity tables each entity exposes a convenience method (example for Person
entity):
Person.indexPeople(Person.findAllPeople());
The URL of the solr server location can be changed in the project
src/main/resources/META-INF/spring/solr.properties config file.
Front-end (controller and MVC/JSP views) are currently work-in-progress. However, the following
Ajax Library offers a neat front-end for those who want to take this a step further:
http://github.com/evolvingweb/ajax-solr It is planned to provide a out of the box integration with the
Ajax-Solr front-end through this addon in the medium term.
1.1.3.BUILD-SNAPSHOT 99
Part III. Internals and
Add-On Development
In this part of the guide we reveal how Roo works internally. With this knowledge you'll be well-positioned to
be able to check out the Roo codebase, build a development release, and write add-ons to extend Roo.
You should be familiar with Part I of this reference guide and ideally have used Roo for a period of time to gain
the most value from this part.
1.1.3.BUILD-SNAPSHOT 100
Chapter 14. Development Processes
In this chapter we'll cover how we develop Roo, and how you can check it out and get involved.
1. Design Goals
• Eliminate barriers to adoption , no runtime component, minimal size, best possible development
experience
• Avoid lock-in
• No runtime component
3. ITD Model
1.1.3.BUILD-SNAPSHOT 101
Development Processes
• Background monitoring of externally made changes (allows integration with any development
style)
6. Conventions we follow
1.1.3.BUILD-SNAPSHOT 102
Development Processes
Roo itself uses Maven, so it's very easy to build standard package, install, assembly and site goal PgP
should be installed see 'Setting Up for Development' section below for details.
To get started, you could build Roo from sources (as described above), and locally start changing
source code as you see fit. Then test your changes and if all works well, you can create a git patch and
attach it to a ticket in our bug tracker. To create a patch with Git you can simply use the following
command in Roo's source code root directory:
The resulting .patch file can then be attached to the ROO-XXXX ticket in our bug tracker.
If you're working on a large module that is part of the Roo Git repository, and you have a history of
providing quality patches and "looking after" the code you've previously written, we will likely invite
you to join us as a committer. We have certain commit policies which are more fully detailed in the
readme.txt that is in the root of the checkout location. We have numerous committers external to
VMware, so Roo is very much a welcoming project in terms of committers. We look forward to you
joining us.
1.1.3.BUILD-SNAPSHOT 103
Chapter 15. Simple Add-Ons
Pretty Good Privacy in Spring Roo
The introduction of PGP with Spring Roo 1.1 allows the Roo user to indicate exactly which
developers he trusts to sign software that Roo will download and activate in the Roo Shell. Roo
itself is now also PGP signed in every release. To support these capabilities a new protocol
handler called httppgp:// has been introduced into Roo. This tells Roo a given HTTP URL also
has a PGP armour detached signature available. By requiring PGP signatures for all add-ons,
we're able to conveniently and safely host all Roo add-ons for the community. It's up to the
user to decide if he trusts a given PGP key, and without trusting that key, Roo will refuse to
even spend time downloading the httppgp:// resource. Roo's approach also means you can also
use standalone PGP tools like GnuPG to perform signature-related operations to independently
verify Roo's correct operation.
This chapter will provide an introduction to Spring Roo add-on development. The intention is to
provide a step-by-step guide which walks the developer from zero code to a fully deployed and
published add-on which is immidiately available to all Spring Roo users. With the release of Spring
Roo 1.1 a new set of commands is available which are designed to provide a fast introduction to add-on
development as well as easy access to registered add-ons by Spring Roo 1.1 users.
Spring Roo runs in an OSGi container since version 1.1 This internal change is ideal for Roo’s
add-on model because it allows Roo users to install, uninstall, start, and stop different add-ons
dynamically without restarting the Roo shell. Furthermore, OSGi allows automatic provisioning
of external add-on repositories and provides very good infrastructure for developing modular, as
well as embedded, and service-oriented applications. Under the hood Spring Roo uses Apache
Felix OSGi implementation.
A new add-on named 'Add-On Creator' has been developed which facilitates the creation of a new
Spring Roo add-on. Furthermore, it offers out of the box support for SVN source code control
integration provided by Google Code as well as zero setup for hosting the add-on in a public Maven
repository hosted as part of a Google Code project. In order to register the add-on with RooBot - a
Spring Roo add-on registration service - the add-on is also required to be OSGi compliant, needs to
be signed with PgP keys and the addon bundle needs to be registered through the httppgp protocol.
Add-on developers get all these features automatically configured if they use the new 'Add-On Creator'
feature which ships with Spring Roo 1.1.
The following sections will present a complete step-by-step guide which demonstrates how to bootstrap
a new Spring Roo add-on, publish and release it on your own Google Code project, and register it
with the RooBot service.
1.1.3.BUILD-SNAPSHOT 104
Simple Add-Ons
1. Create a new project in Google Code: Sign in with your Google Account and navigate to
http://code.google.com/hosting/createProject where you can create your project:
• Project Summary - a summary of your project such as 'Spring Roo Add-On to provide French
translation for Spring MVC scaffolding'
• Project Description - description which could include a version compatibility matrix for your
add-on
2. By default, SVN hosting in Google Code will give you a trunk, tags, branches and a wiki folder. In
order to host a Maven repository in your Google code project you should also create a repo folder
as root for the new repository:
4. (optional) Enter your Google Code SVN credentials into your local maven repository settings.xml:
1.1.3.BUILD-SNAPSHOT 105
Simple Add-Ons
With release 1.1 Spring Roo offers three commands to help developers quickly create new
add-ons:
• When: Simple add-ons which want to add dependencies and/or configuration artifacts to
project
Once you have installed Java, Maven, PGP, SVN tools and have created and checked out your Google
Code project, you can change into the <project-name> directory which should contain only the .svn
directory at this stage. In the <project-name> directory you can start the Spring Roo shell and use one
of the new commands for add-on creation:
[1] pom.xml
[2] readme.txt
[3] legal/LICENSE.TXT
[4] src/main/java/com/foo/batch/BatchCommands.java
[5] src/main/java/com/foo/batch/BatchOperations.java
[5] src/main/java/com/foo/batch/BatchOperationsImpl.java
[6] src/main/java/com/foo/batch/BatchPropertyName.java
[7] src/main/assembly/assembly.xml
This newly created add-on project can be imported into the SpringSource Tool Suite via File > Import
> Maven > Existing Maven projects. Let's discuss some these artefacts in more detail:
1.1.3.BUILD-SNAPSHOT 106
Simple Add-Ons
1. pom.xml - This is the Maven project configuration. This configuration ships with a number of
preinstalled Maven plugins which take facilitate the PGP artefact signing process as well as the
project release process (including tagging etc). It also adds OSGi and Felix dependencies to the
add-on project which are needed for it to run in the Roo Shell. Furthermore, several commonly used
Spring Roo modules are preinstalled. These modules provide functionalities such as file system
monitoring, Roo shell command registration, etc. More information about these functionalities is
provided in the following sections.
The add-on developer should open up the pom.xml file and refine some project specific references
and documentation (marked in bold font):
Some of these properties can also be provided when issuing the addon create command.
2. readme.txt - You can provide any setup or installation information about your add-on in this
file. This file is used by other developers who checkout your add-on source code from the SVN
repository.
3. legal/LICENSE.TXT - Copy the appropriate license text for your add-on into this file.
1.1.3.BUILD-SNAPSHOT 107
Simple Add-Ons
[1] @Component
[1] @Service
[2] public class BatchCommands implements CommandMarker {
There are a few artefacts of interest when developing Spring Roo add-ons:
1. To register components and services in the Roo shell the type needs to be annotated with the
@Component & @Service annotations provided by Felix. These components can be injected into
other add-ons (more interesting for functionalities exposed by operations types).
2. The command type needs to implement the the CommandMarker interface which Spring Roo uses
to scan for types which contribute commands to the Roo Shell.
3. The Felix @Reference annotations are used to inject services and components offered by other
Spring Roo core components or even other add-ons. In this example we are injecting a reference to
the add-ons own BatchOperations and the StaticFieldConverter component offered by the Roo Shell
OSGi bundle. For Spring users, the Felix @Reference is similar in its purpose to the @Autowired
or @Inject annotations.
4. The activate and deactivate methods are methods which can optionally be implemented to get
access to the lifecycle of the bundle which is managed by the underlying OSGi container. Roo
add-on developers can use these lifecycle hooks for registration and deregistration of converters
(typical use in command types) or for the registration of metadata dependencies (typical for ITD
providing add-ons) or any other component initialization activities.
5. The use of Spring Roo's @CliAvailabilityIndicator is optional and allows you to specify when a
command should be made available in the Spring Roo Shell. Methods annotated with this annotation
need to return a boolean value to indicate when a command should be visible to the Roo Shell. For
example, many commands are hidden before a project has been created.
6. The @CliCommand annotation plays a central role for Roo add-on developers. It allows the
registration of new commands for the Roo Shell. Methods annotated with @CliCommand can
optionally return a String value to contribute a log statement to the Spring Roo Shell. Another, more
flexible, option to provide log statements in the Roo Shell is to register a standard JDK logger which
allows the developer to present color-coded messages to the user in the Roo shell. The color coding
depends on the log level (warning, info, error, etc).
1.1.3.BUILD-SNAPSHOT 108
Simple Add-Ons
7. The optional @CliOption annotation can be used to annotate method parameters. These parameters
define command attributes which are presented as part of a command. Roo will attempt to
automatically convert user entered values into the target type specified as the method parameter. In
the example above Roo will convert a String value to the BatchPropertyName type. By default Roo
offers converters for common number types, String, Date, Enum, Locale, boolean and Character.
See the org.springframework.roo.shell.converters package for examples if the implementation of
a custom converter is required.
15.4. Operations
Almost all Spring Roo add-ons provide operations types. These types do most of the work behind
Roo's passive generation principle (active generation is taken care of by AspectJ Intertype declarations
(ITDs) - more about that later). Methods offered by the operations types provided by the add-on are
typically invoked by the accompanying commands type. Alternatively, operations types can also be
invoked by other add-ons (this is a rather unusual case).
Implementations of the operations interface need to be annotated with the Felix @Component and
@Service annotations to make their functionality within Roo's OSGi container. Dependencies can
be injected into operations types via the Felix @Reference annotation. If the dependency exists in a
package which is not yet registered in the add-on pom.xml you need to add the dependency there to
make the relevant bundle to the add-on classpath.
The Add-On Creator generated project includes example code which uses Roo's source path
abstractions, file manager and various Util classes which take care of project file management.
• Adding new dependencies, plugins, & repositories to the Maven project pom.xml.
• Copying static artefacts from the add-on jar into the user project (ie CSS, images, tagx, configuration
files, etc).
• Adding trigger (or other) annotations to target types (most common), fields or methods.
Spring Roo offers a wide range of abstractions and metadata types which support these use cases. For
example, the following services are offered:
• org.springframework.roo.process.manager.FileManager
• use file manager for all file system operations in project (offers automatic undo on exception)
• org.springframework.roo.project.PathResolver
• org.springframework.roo.metadata.MetadataService
• offers access to Roo metadata bean info metadata for mutators/accessors of target type
1.1.3.BUILD-SNAPSHOT 109
Simple Add-Ons
• org.springframework.roo.project.ProjectMetadata
• project name, top level package read access to project dependencies, repositories, etc
• org.springframework.roo.project.ProjectOperations
• add, remove project Maven dependencies, plugins, repositories, filters, properties, etc
• org.springframework.roo.support.util.Assert
• similar to Spring’s Assert, exceptions thrown by Assert will cause Roo's File manager abstraction
to roll back.
• org.springframework.roo.support.util.FileCopyUtils
• org.springframework.roo.support.util.TemplateUtils
• org.springframework.roo.support.util.XmlUtils
• writeXml methods
This will generate your add-on OSGi bundle in the project target directory. In a separate directory you
can start the Spring Roo Shell and use the following command to test your new add-on:
This should install and activate your new Spring Roo Add-On. For trouble shooting Roo offers the
following OSGi commands:
• osgi ps - Displays OSGi bundle information & status. This should list your add-on as active.
• osgi log - Access OSGi container logs. This could identify possible issues during which occured
during activation of an add-on.
• osgi scr list - Lists all currently registered services and components. This should list your add-ons
commands and operations types.
1.1.3.BUILD-SNAPSHOT 110
Simple Add-Ons
• osgi scr info - Info about a specific component. This can be used to identify possible unresolvable
dependencies.
• osgi start - install a new add-on directly from a local or remote location.
Once the add-on has been tested successfully in your development environment you can release the
add-on source code to your Google Code project, create a tag and install all relevant artifacts in the
project's Maven repository:
The Maven release plugin will ask for tag and release artefact names. Typical conventions Roo follows
(in compliance with OSGi practices) is to use major, minor and micro version numbering as well as
textual identifier. Eg 0.1.1.RELEASE, 0.1.2.BUILD-SNAPSHOT.
Deployment for bundles created with Roo's wrapping command can be deployed rather than released.
For example, to create a wrapped bundle of the postgres JDBC driver you can use this command:
This can then be deployed to a Google code project (setup in the same way described above) with a
simple deploy command:
When reviewing file contents via the HTTP interface provided by Google Code, the reader
is presented with HTML documents (which provide syntax highlighting, etc). To get access
to the real (raw) URL of a document (eg repo/repository.xml) you need to click the
'View raw file' link found in the 'File info' section in the right-hand menu. Example of
a raw URL: http://<project-name>.googlecode.com/svn/repo/repository.xml. Make sure the
version appendix is removed from the URL before clinicking the 'View raw file' link (ie
http://<project-name>.googlecode.com/svn/repo/repository.xml?r=25)
The URL to the raw (see sidebar) repository.xml artefact can then be registered with RooBot:
1.1.3.BUILD-SNAPSHOT 111
Simple Add-Ons
Register your new add-on repository by sending an email to [email protected] where the subject
line MUST be the raw URL to OSGi repository.xml. The email body is currently not used (but you
can send greetings to the Roo team ;-). Other interaction forms planned (Web front-end, Roo shell
command, etc).
RooBot verifies a few aspects before publishing your new add-on to all users:
• The resource URI must use the httppgp prefix ie: <resource
uri="httppgp://fr-test.googlecode.com/svn/…/>
• The referenced bundle in the repository has a corresponding .asc file containing the PgP public key
• The public PGP key of the add-on signer needs to be available at http://keyserver.ubuntu.com/ A
guide to PGP key management can be found here. Make sure to publish your key with this command:
• RooBot will retrieve publicly accessible key information (key owner name, email) from public key
server
• The referenced bundle contains a OSGi compliant manifest.mf file. For example it will verify that
the add-on version defined in your repository.xml matches the version defined in the manifest of
your add-on.
• [Important] To ensure your repository is valid RooBot will download all defined resources in the
repository. To do that it will read the uri attribute and perform a HTTP GET request against the
defined URL (after replacing the httppgp:// protocol handler with http://). Should the download or
verification of any of the defined resources in the respository fail RooBot will abort the processing
of the entire repository and retry later again.
If all tests pass, RooBot will publish your add-on in a publicly accessible XML registry
http://spring-roo-repository.springsource.org/roobot/roobot.xml. This registry is available to RooBot
client which is integrated into the Spring Roo Shell.
Once you sent your email to [email protected] you should receive a response from
RooBot indicating that the processing of your repository has started. RooBot will not
update you on the sucess or failing of the processing. However, you should be able to
see your add-on listed at http://spring-roo-repository.springsource.org/roobot/roobot.xml within
a few hours. Should this not be the case, you can visit the RooBot error log at
http://spring-roo-repository.springsource.org/roobot/roobot-log.txt which is being published every 5
minutes.
Once RooBot has published your add-on sucessfully it will periodically process your repository to
verify its ongoing validity. As part of this periodic processing it will also automatically pickup new
versions (add-on releases) in your repository.xml. Therefore it should not be necessary to explicitly
notify RooBot of any changes in your repository.
1.1.3.BUILD-SNAPSHOT 112
Simple Add-Ons
As your plugin will result in an OSGi bundle you need to change the packaging from simple jar
to bundle. This will cause the Maven bundle plugin creating the necessary metadata for you out
of the box.
Similar to the point above you need to reference dependencies as bundles. Again, to let the Maven
bundle plugin do its job.
3. Sync build section of your pom with the one provided in the addon template
Compare changes between your original add-on pom.xml and a pom.xml generated by the addon
create command (see below). This is mostly related to the Maven bundle plugin as well as the
Maven SCR plugin (see next point for details).
The easiest way to do so is simply creating a dummy addon project using the template and copy
the plugin configuration into your pom.
Roo uses Apache Felix as OSGi runtime and thus uses @Component and @Service annotations in
combination with the Maven SCR plugin1 to create descriptors for the OSGi declarative services
infrastructure.
@Service
@Component
public class MyCommands implements CommandMarker {
So every @ScopeDevelopment annotation you used at your command and operations classes has to
be replaced by @Service and @Component. If you had injected other services into your command
or operations class you can use @Reference to wire that into your component instance. Note, that
your class will have to implement at least one interface Felix can publish the component instance
under. As there might be further tweaks necessary, have a closer look at the output the Maven SCR
plugin generates. It will log errors in case you still need to change something.
1.1.3.BUILD-SNAPSHOT 113
Chapter 16. Advanced Add-Ons
TBC.
16.1. Metadata
TBC
16.2. Annotations
TBC
16.4. Recommendations
TBC
1.1.3.BUILD-SNAPSHOT 114
Part IV. Appendices
The fourth and final part of the reference guide provides appendices and background information that does
not neatly belong within the other parts. The information is intended to be treated as a reference and not read
consecutively.
1.1.3.BUILD-SNAPSHOT 115
Appendix A. Command Index
This appendix was automatically built from Roo 1.1.2.RELEASE [rev 6fd10ea].
Commands are listed in alphabetic order, and are shown in monospaced font with any mandatory
options you must specify when using the command. Most commands accept a large number of options,
and all of the possible options for each command are presented in this appendix.
--bundleSymbolicName
The bundle symbolic name for the add-on of interest; no default value (mandatory)
--rating
How much did you like this add-on?; no default value (mandatory)
--comment
Your comments on this add-on eg "this is my comment!"; limit of 140 characters; no default value
--bundleSymbolicName
The bundle symbolic name for the add-on of interest; no default value (mandatory)
--searchResultId
The bundle ID as presented via the addon list or addon search command; no default value
(mandatory)
1.1.3.BUILD-SNAPSHOT 116
Command Index
--bundleSymbolicName
The bundle symbolic name for the add-on of interest; no default value (mandatory)
--searchResultId
The bundle ID as presented via the addon list or addon search command; no default value
(mandatory)
addon list
--refresh
Refresh the add-on index from the Internet; default if option present: 'true'; default if option not
present: 'false'
--linesPerResult
The maximum number of lines displayed per add-on; default: '2'
--maxResults
The maximum number of add-ons to list; default: '99'
--trustedOnly
Only display trusted add-ons in search results; default if option present: 'true'; default if option
not present: 'false'
--compatibleOnly
Only display compatible add-ons in search results; default if option present: 'true'; default if option
not present: 'false'
--bundleSymbolicName
The bundle symbolic name for the add-on of interest; no default value (mandatory)
addon search
--requiresDescription
A comma separated list of search terms; default: '*'
1.1.3.BUILD-SNAPSHOT 117
Command Index
--refresh
Refresh the add-on index from the Internet; default if option present: 'true'; default if option not
present: 'false'
--linesPerResult
The maximum number of lines displayed per add-on; default: '2'
--maxResults
The maximum number of add-ons to list; default: '20'
--trustedOnly
Only display trusted add-ons in search results; default if option present: 'true'; default if option
not present: 'false'
--compatibleOnly
Only display compatible add-ons in search results; default if option present: 'true'; default if option
not present: 'false'
--requiresCommand
Only display add-ons in search results that offer this command; no default value
Upgrade all relevant Spring Roo Add-ons / Components for the current stability level
--addonStabilityLevel
The stability level of add-ons or components which are presented for upgrading (default: ANY);
no default value
--bundleSymbolicName
The bundle symbolic name for the add-on to upgrade; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 118
Command Index
--searchResultId
The bundle ID as presented via the addon list or addon search command; no default value
(mandatory)
--addonStabilityLevel
The stability level of add-ons or components which are presented for upgrading; no default value
A.2.1. backup
backup
A.3.1. class
class --class
--class
The name of the class to create; no default value (mandatory)
--rooAnnotations
Whether the generated class should have common Roo annotations; default if option present: 'true';
default if option not present: 'false'
--path
Source directory to create the class in; default: 'SRC_MAIN_JAVA'
--extends
The superclass (defaults to java.lang.Object); default if option not present: 'java.lang.Object'
--abstract
Whether the generated class should be marked as abstract; default if option present: 'true'; default
if option not present: 'false'
1.1.3.BUILD-SNAPSHOT 119
Command Index
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--class
The name of the enum class to receive this field; default if option not present: '*'
--name
The name of the constant; no default value (mandatory)
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--class
The name of the enum to create; no default value (mandatory)
--path
Source directory to create the enum in; default: 'SRC_MAIN_JAVA'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
A.3.4. focus
focus --class
--class
The type to focus on; no default value (mandatory)
A.3.5. interface
interface --class
--class
The name of the interface to create; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 120
Command Index
--path
Source directory to create the interface in; default: 'SRC_MAIN_JAVA'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--package
The package in which new controllers will be placed; no default value (mandatory)
--class
The path and name of the controller object to be created; no default value (mandatory)
--entity
The name of the entity object which the controller exposes to the web tier; default if option not
present: '*'
--path
The base path under which the controller listens for RESTful requests (defaults to the simple name
of the form backing object); no default value
--disallowedOperations
A comma separated list of operations (only create, update, delete allowed) that should not be
generated in the controller; no default value
Create a new advanced add-on for Spring Roo (commands + operations + metadata + trigger annotation
+ dependencies)
1.1.3.BUILD-SNAPSHOT 121
Command Index
--topLevelPackage
The top level package of the new addon; no default value (mandatory)
--description
Description of your addon (surround text with double quotes); no default value
--projectName
Provide a custom project name (if not provided the top level package name will be used instead);
no default value
--topLevelPackage
The top level package of the new addon; no default value (mandatory)
--locale
The locale abbreviation (ie: en, or more specific like en_AU, or de_DE); no default value
(mandatory)
--messageBundle
Fully qualified path to the messages_xx.properties file; no default value (mandatory)
--language
The full name of the language (used as a label for the UI); no default value
--flagGraphic
Fully qualified path to flag xx.png file; no default value
--description
Description of your addon (surround text with double quotes); no default value
--projectName
Provide a custom project name (if not provided the top level package name will be used instead);
no default value
--topLevelPackage
The top level package of the new addon; no default value (mandatory)
--description
Description of your addon (surround text with double quotes); no default value
--projectName
Provide a custom project name (if not provided the top level package name will be used instead);
no default value
1.1.3.BUILD-SNAPSHOT 122
Command Index
Create a new add-on for Spring Roo which wraps a maven artifact to create a OSGi compliant bundle
--topLevelPackage
The top level package of the new wrapper bundle; no default value (mandatory)
--groupId
Dependency group id; no default value (mandatory)
--artifactId
Dependency artifact id); no default value (mandatory)
--version
Dependency version; no default value (mandatory)
--vendorName
Dependency vendor name); no default value (mandatory)
--licenseUrl
Dependency license URL; no default value (mandatory)
--docUrl
Dependency documentation URL; no default value
--description
Description of the bundle (use keywords with #-tags for better search integration); no default value
--projectName
Provide a custom project name (if not provided the top level package name will be used instead);
no default value
--osgiImports
Contents of Import-Package in OSGi manifest; no default value
--schema
The database schema name; no default value (mandatory)
--file
The file to save the metadata to; no default value
1.1.3.BUILD-SNAPSHOT 123
Command Index
--enableViews
Display database views; default if option present: 'true'; default if option not present: 'false'
--schema
The database schema name; no default value (mandatory)
--package
The package in which new entities will be placed; no default value
--testAutomatically
Create automatic integration tests for entities; default if option present: 'true'; default if option not
present: 'false'
--enableViews
Reverse engineer database views; default if option present: 'true'; default if option not present:
'false'
--includeTables
The tables to include in reverse engineering. Must be separated by spaces and enclosed by pairs
of double quotes
--excludeTables
The tables to exclude from reverse engineering. Must be separated by spaces and enclosed by pairs
of double quotes
--provider
The id of the document; no default value (mandatory)
--documentId
The id of the document; no default value (mandatory)
--viewName
The name of the jspx view; no default value
1.1.3.BUILD-SNAPSHOT 124
Command Index
--stockSymbol
The stock symbol; no default value (mandatory)
--viewName
The name of the jspx view; no default value
--url
The url of the source to be embedded; no default value (mandatory)
--viewName
The name of the jspx view; no default value
--location
The location of the map (ie "Sydney, Australia"); no default value (mandatory)
--viewName
The name of the jspx view; no default value
--provider
The provider of the photo gallery; no default value (mandatory)
--userId
The user id; no default value (mandatory)
--albumId
The album id; no default value (mandatory)
--viewName
The name of the jspx view; no default value
1.1.3.BUILD-SNAPSHOT 125
Command Index
--provider
The provider of the video stream; no default value (mandatory)
--streamId
The stream id; no default value (mandatory)
--viewName
The name of the jspx view; no default value
--searchTerm
The search term to display results for; no default value (mandatory)
--viewName
The name of the jspx view; no default value
--provider
The id of the video; no default value (mandatory)
--videoId
The id of the video; no default value (mandatory)
--viewName
The name of the jspx view; no default value
--waveId
The key of the wave; no default value (mandatory)
--viewName
The name of the jspx view; no default value
1.1.3.BUILD-SNAPSHOT 126
Command Index
A.8.1. dod
Creates a new data on demand for the specified entity
dod
--entity
The entity which this data on demand class will create and modify as required; default if option
not present: '*'
--class
The class which will be created to hold this data on demand provider (defaults to the entity name
+ 'DataOnDemand'); no default value
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
A.8.2. embeddable
Creates a new Java class source file with the JPA @Embeddable annotation in SRC_MAIN_JAVA
embeddable --class
--class
The name of the class to create; no default value (mandatory)
--serializable
Whether the generated class should implement java.io.Serializable; default if option present: 'true';
default if option not present: 'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
A.8.3. entity
Creates a new JPA persistent entity in SRC_MAIN_JAVA
entity --class
--class
Name of the entity to create; no default value (mandatory)
--extends
The superclass (defaults to java.lang.Object); default if option not present: 'java.lang.Object'
--abstract
Whether the generated class should be marked as abstract; default if option present: 'true'; default
if option not present: 'false'
--testAutomatically
Create automatic integration tests for this entity; default if option present: 'true'; default if option
not present: 'false'
1.1.3.BUILD-SNAPSHOT 127
Command Index
--table
The JPA table name to use for this entity; no default value
--schema
The JPA table schema name to use for this entity; no default value
--catalog
The JPA table catalog name to use for this entity; no default value
--identifierField
The JPA identifier field name to use for this entity; no default value
--identifierColumn
The JPA identifier field column to use for this entity; no default value
--identifierType
The data type that will be used for the JPA identifier field (defaults to java.lang.Long); default:
'java.lang.Long'
--versionField
The JPA version field name to use for this entity; no default value
--versionColumn
The JPA version field column to use for this entity; no default value
--inheritanceType
The JPA @Inheritance value; no default value
--mappedSuperclass
Apply @MappedSuperclass for this entity; default if option present: 'true'; default if option not
present: 'false'
--serializable
Whether the generated class should implement java.io.Serializable; default if option present: 'true';
default if option not present: 'false'
--persistenceUnit
The persistence unit name to be used in the persistence.xml file; no default value
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
test integration
--entity
The name of the entity to create an integration test for; default if option not present: '*'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
1.1.3.BUILD-SNAPSHOT 128
Command Index
A.9.1. exit
Exits the shell
exit
--bundleSymbolicName
A bundle symbolic name to find; no default value (mandatory)
--[default]
The command to pass to Felix (WARNING: no validation or security checks are performed);
default: 'help'
osgi headers
--bundleSymbolicName
Limit results to a specific bundle symbolic name; no default value
--url
The URL to obtain the bundle from; no default value (mandatory)
osgi log
1.1.3.BUILD-SNAPSHOT 129
Command Index
--maximumEntries
The maximum number of log messages to display; no default value
--level
The minimum level of messages to display; no default value
--bundleSymbolicName
The specific bundle to deploy; no default value (mandatory)
--bundleSymbolicName
The specific bundle to display information for; no default value (mandatory)
--keywords
Keywords to locate; no default value
--bundleSymbolicName
The specific bundle to start; no default value (mandatory)
--url
The URL to add (eg http://felix.apache.org/obr/releases.xml); no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 130
Command Index
--url
The URL to refresh (list existing URLs via 'osgi obr url list'); no default value (mandatory)
--url
The URL to remove (list existing URLs via 'osgi obr url list'); no default value (mandatory)
A.9.15. osgi ps
osgi ps
--format
The format of bundle information; default: 'BUNDLE_NAME'
--bundleSymbolicName
The specific bundle to resolve; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 131
Command Index
--componentId
The specific component identifier (use 'osgi scr list' to list component identifiers); no default value
(mandatory)
--componentId
The specific component identifier (use 'osgi scr list' to list component identifiers); no default value
(mandatory)
--componentId
The specific component identifier (use 'osgi scr list' to list component identifiers); no default value
(mandatory)
--bundleId
Limit results to a specific bundle; no default value
--url
The URL to obtain the bundle from; no default value (mandatory)
--bundleSymbolicName
The specific bundle to uninstall; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 132
Command Index
--bundleSymbolicName
The specific bundle to update ; no default value (mandatory)
--url
The URL to obtain the updated bundle from; no default value
osgi version
--fieldName
The name of the field to add; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--assertFalse
Whether this value must assert false; default if option present: 'true'
--assertTrue
Whether this value must assert true; default if option present: 'true'
--column
The JPA @Column name; no default value
--value
Inserts an optional Spring @Value annotation with the given content; no default value
--comment
An optional comment for JavaDocs; no default value
1.1.3.BUILD-SNAPSHOT 133
Command Index
--primitive
Indicates to use a primitive type; default if option present: 'true'; default if option not present: 'false'
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field to add; no default value (mandatory)
--type
The Java type of the entity; no default value (mandatory)
--persistenceType
The type of persistent storage to be used; no default value
--class
The name of the class to receive this field; default if option not present: '*'
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--future
Whether this value must be in the future; default if option present: 'true'
--past
Whether this value must be in the past; default if option present: 'true'
--column
The JPA @Column name; no default value
--comment
An optional comment for JavaDocs; no default value
--value
Inserts an optional Spring @Value annotation with the given content; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
1.1.3.BUILD-SNAPSHOT 134
Command Index
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--dateFormat
Indicates the style of the date format (ignored if dateTimeFormatPattern is specified); default:
'SHORT'
--timeFormat
Indicates the style of the time format (ignored if dateTimeFormatPattern is specified); default:
'NONE'
--dateTimeFormatPattern
Indicates a DateTime format pattern such as yyyy-MM-dd hh:mm:ss a; no default value
--fieldName
The name of the field to add; no default value (mandatory)
--type
The Java type of the @Embeddable class; no default value (mandatory)
--class
The name of the @Entity class to receive this field; default if option not present: '*'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field to add; no default value (mandatory)
--type
The enum type of this field; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--column
The JPA @Column name; no default value
--notNull
Whether this value cannot be null; default if option present: 'true'
1.1.3.BUILD-SNAPSHOT 135
Command Index
--nullRequired
Whether this value must be null; default if option present: 'true'
--enumType
The fetch semantics at a JPA level; no default value
--comment
An optional comment for JavaDocs; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field to add; no default value (mandatory)
--type
The Java type of the entity; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--decimalMin
The BigDecimal string-based representation of the minimum value; no default value
--decimalMax
The BigDecimal string based representation of the maximum value; no default value
--digitsInteger
Maximum number of integral digits accepted for this number; no default value
--digitsFraction
Maximum number of fractional digits accepted for this number; no default value
--min
The minimum value; no default value
--max
The maximum value; no default value
1.1.3.BUILD-SNAPSHOT 136
Command Index
--column
The JPA @Column name; no default value
--comment
An optional comment for JavaDocs; no default value
--value
Inserts an optional Spring @Value annotation with the given content; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--primitive
Indicates to use a primitive type if possible; default if option present: 'true'; default if option not
present: 'false'
--unique
Indicates whether to mark the field with a unique constraint; default if option present: 'true'; default
if option not present: 'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field; no default value (mandatory)
--type
The Java type of this field; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--comment
An optional comment for JavaDocs; no default value
--column
The JPA @Column name; no default value
--value
Inserts an optional Spring @Value annotation with the given content; no default value
1.1.3.BUILD-SNAPSHOT 137
Command Index
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field to add; no default value (mandatory)
--type
The Java type of the entity to reference; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--joinColumnName
The JPA @JoinColumn name; no default value
--referencedColumnName
The JPA @JoinColumn referencedColumnName; no default value
--cardinality
The relationship cardinarily at a JPA level; default: 'MANY_TO_ONE'
--fetch
The fetch semantics at a JPA level; no default value
--comment
An optional comment for JavaDocs; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
1.1.3.BUILD-SNAPSHOT 138
Command Index
--fieldName
The name of the field to add; no default value (mandatory)
--type
The entity which will be contained within the Set; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
--mappedBy
The field name on the referenced type which owns the relationship; no default value
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--sizeMin
The minimum number of elements in the collection; no default value
--sizeMax
The maximum number of elements in the collection; no default value
--cardinality
The relationship cardinarily at a JPA level; default: 'MANY_TO_MANY'
--fetch
The fetch semantics at a JPA level; no default value
--comment
An optional comment for JavaDocs; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--fieldName
The name of the field to add; no default value (mandatory)
--class
The name of the class to receive this field; default if option not present: '*'
1.1.3.BUILD-SNAPSHOT 139
Command Index
--notNull
Whether this value cannot be null; default if option present: 'true'
--nullRequired
Whether this value must be null; default if option present: 'true'
--decimalMin
The BigDecimal string-based representation of the minimum value; no default value
--decimalMax
The BigDecimal string based representation of the maximum value; no default value
--sizeMin
The minimum string length; no default value
--sizeMax
The maximum string length; no default value
--regexp
The required regular expression pattern; no default value
--column
The JPA @Column name; no default value
--value
Inserts an optional Spring @Value annotation with the given content; no default value
--comment
An optional comment for JavaDocs; no default value
--transient
Indicates to mark the field as transient; default if option present: 'true'; default if option not present:
'false'
--unique
Indicates whether to mark the field with a unique constraint; default if option present: 'true'; default
if option not present: 'false'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
--class
The controller or entity for which the finders are generated; default if option not present: '*'
1.1.3.BUILD-SNAPSHOT 140
Command Index
--finderName
The finder string as generated with the 'finder list' command; no default value (mandatory)
finder list
--class
The controller or entity for which the finders are generated; default if option not present: '*'
--depth
The depth of attribute combinations to be generated for the finders; default: '1'
--filter
A comma separated list of strings that must be present in a filter to be included; no default value
gwt setup
A.13.1. hint
Provides step-by-step hints and context-sensitive guidance
hint
--topic
The topic for which advice should be provided
test mock
1.1.3.BUILD-SNAPSHOT 141
Command Index
--entity
The name of the entity this mock test is targeting; default if option not present: '*'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
test stub
--entity
The name of the entity this mock test is targeting; default if option not present: '*'
--permitReservedWords
Indicates whether reserved words are ignored by Roo; default if option present: 'true'; default if
option not present: 'false'
A.15.1. */
End of block comment
*/
A.15.2. /*
Start of block comment
/*
A.15.3. //
Inline comment markers (start of line only)
//
A.15.4. date
Displays the local date and time
date
1.1.3.BUILD-SNAPSHOT 142
Command Index
flash test
A.15.6. script
Parses the specified resource file and executes its commands
script --file
--file
The file to locate and execute; no default value (mandatory)
--lineNumbers
Display line numbers when executing the script; default if option present: 'true'; default if option
not present: 'false'
system properties
A.15.8. version
Displays shell version
version
--[default]
Special version flags; no default value
--fieldName
The name of the field to add; default: 'jmsTemplate'
--class
The name of the class to receive this field; default if option not present: '*'
1.1.3.BUILD-SNAPSHOT 143
Command Index
--async
Indicates if the injected method should be executed asynchronously; default if option present:
'true'; default if option not present: 'false'
--class
The name of the class to create; no default value (mandatory)
--destinationName
The name of the destination; default: 'myDestination'
--destinationType
The type of the destination; default: 'QUEUE'
--provider
The persistence provider to support; no default value (mandatory)
--destinationName
The name of the destination; default: 'myDestination'
--destinationType
The type of the destination; default: 'QUEUE'
--key
The property key that should be removed; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 144
Command Index
--key
The property key that should be changed; no default value (mandatory)
--value
The new vale for this property key; no default value (mandatory)
--provider
The persistence provider to support; no default value (mandatory)
--database
The database to support; no default value (mandatory)
--applicationId
The Google App Engine application identifier to use; default if option not present: 'the project's
name'
--jndiDataSource
The JNDI datasource to use; no default value
--hostName
The host name to use; no default value
--databaseName
The database name to use; no default value
--userName
The username to use; no default value
--password
The password to use; no default value
--persistenceUnit
The persistence unit name to be used in the persistence.xml file; no default value
json add
1.1.3.BUILD-SNAPSHOT 145
Command Index
--class
The java type to apply this annotation to; default if option not present: '*'
--rootName
The root name which should be used to wrap the JSON document; no default value
json all
--class
The path and name of the controller object to be created; no default value (mandatory)
--preferredMapping
Indicates a specific request mapping path for this controller (eg /foo/); no default value
--code
The language code for the desired bundle; no default value (mandatory)
--path
The path the static view to create in (required, ie '/foo/blah'); no default value (mandatory)
--viewName
The view name the mapping this view should adopt (required, ie 'index'); no default value
(mandatory)
--title
The title of the view; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 146
Command Index
--level
The log level to configure; no default value (mandatory)
--package
The package to append the logging level to (all by default); no default value
--hostServer
The host server; no default value (mandatory)
--protocol
The protocol used by mail server; no default value
--port
The port used by mail server; no default value
--encoding
The encoding used for mail; no default value
--username
The mail account username; no default value
--password
The mail account password; no default value
--from
The 'from' email (optional); no default value
--subject
The message subject (obtional); no default value
1.1.3.BUILD-SNAPSHOT 147
Command Index
--fieldName
The name of the field to add; default: 'mailTemplate'
--class
The name of the class to receive this field; default if option not present: '*'
--async
Indicates if the injected method should be executed asynchronously; default if option present:
'true'; default if option not present: 'false'
--groupId
The group ID of the dependency; no default value (mandatory)
--artifactId
The artifact ID of the dependency; no default value (mandatory)
--version
The version of the dependency; no default value (mandatory)
Removes an existing dependency from the Maven project object model (POM)
--groupId
The group ID of the dependency; no default value (mandatory)
--artifactId
The artifact ID of the dependency; no default value (mandatory)
--version
The version of the dependency; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 148
Command Index
perform assembly
perform clean
--mavenCommand
User-specified Maven command (eg test:test); no default value (mandatory)
perform eclipse
perform package
perform tests
A.22.9. project
Creates a new Maven project
project --topLevelPackage
--topLevelPackage
The uppermost package name (this becomes the <groupId> in Maven and also the '~' value when
using Roo's shell); no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 149
Command Index
--projectName
The name of the project (last segment of package name used as default); no default value
--java
Forces a particular major version of Java to be used (will be auto-detected if unspecified; specify
5 or 6 or 7 only); no default value
--maximumCapacity
The maximum number of metadata items to cache; no default value (mandatory)
--metadataId
The metadata ID (should start with MID:); no default value (mandatory)
--type
The Java type name to display metadata for; no default value (mandatory)
metadata status
--level
The verbosity of notifications (0=none, 1=some, 2=all); no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 150
Command Index
--keyId
The key ID to view (eg 00B5050F or 0x00B5050F); no default value (mandatory)
pgp status
--keyId
The key ID to trust (eg 00B5050F or 0x00B5050F); no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 151
Command Index
--keyId
The key ID to remove trust from (eg 00B5050F or 0x00B5050F); no default value (mandatory)
development mode
--enabled
Activates development mode; default: 'true'
poll now
--ms
The number of milliseconds between each poll; no default value (mandatory)
poll status
1.1.3.BUILD-SNAPSHOT 152
Command Index
--enabled
Activates debug mode; default: 'true'
--name
Property file name (including .properties suffix); no default value (mandatory)
--path
Source path to property file; no default value (mandatory)
--name
Property file name (including .properties suffix); no default value (mandatory)
--path
Source path to property file; no default value (mandatory)
--key
The property key that should be removed; no default value (mandatory)
--name
Property file name (including .properties suffix); no default value (mandatory)
--path
Source path to property file; no default value (mandatory)
--key
The property key that should be changed; no default value (mandatory)
1.1.3.BUILD-SNAPSHOT 153
Command Index
--value
The new vale for this property key; no default value (mandatory)
proxy configuration
security setup
--controller
Controller to create a Selenium test for; no default value (mandatory)
--name
Name of the test; no default value
--serverUrl
URL of the server where the web application is available, including protocol, port and hostname;
default: 'http://localhost:8080/'
1.1.3.BUILD-SNAPSHOT 154
Command Index
A.31.1. help
Shows system help
help
--command
Command name to provide help for; no default value
reference guide
solr add
--class
The target type which is made searchable; default if option not present: '*'
solr all
solr setup
--searchServerUrl
The Url of the Solr search server; default: 'http://localhost:8983/solr'
1.1.3.BUILD-SNAPSHOT 155
Command Index
--privacyLevel
The new UAA privacy level to use; no default value (mandatory)
download status
download view
--file
The file to save the UAA JSON content to; no default value
web flow
--flowName
The name for your web flow; no default value
1.1.3.BUILD-SNAPSHOT 156
Appendix B. Upgrade Notes and Known
Issues
B.1. Known Issues
Because Spring Roo integrates a large number of other technologies, invariably some people using
Roo may experience issues when using certain combinations of technologies together. This section
aims to list such known issues in an effort to help you avoid experiencing any problems. If you are
able to contribute further information, a solution or workaround to any of these known issues, we'd
certainly appreciate hearing from you via the community forums.
• JDK compatibility: Spring Roo has been tested with Sun, IBM, JRockit and Apache Harmony JVMs
for Java 5 and Java 6. We do not formally support other JVMs or other versions of JVMs. We have
also had an issue reported with versions of Java 6 before 1.6.0_17 due to Java bug 6506304 and
therefore recommend you always use the latest released version of Java 6 for your platform. There
is also a known issue with OpenJDK. You can read about our testing of different JDKs in issue
ROO-106.
• Human language support: Pluralisation within Roo delegates to the Inflector library. Due to some
issues with Inflector, only English pluralisation is supported. If you wish to override the plural
selected by Inflector (and in turn used by Roo), you can specify a particular plural for either a Java
type or Java field by using the @RooPlural annotation. Longer term it would be nice if someone
ported the Inflector code into the Roo pluralisation add-on so that we can fix these issues and support
other languages. We are receptive to contributions from the community along these lines.
• Shell wrapping: In certain cases typing a long command into the shell that wraps over a single line
may prevent you from being able to backspace to the prior line. This is caused by the JLine library
(not Roo). We expect to rewrite the shell at some future time and will likely stop using JLine at
that point.
• Hibernate issues: Hibernate is one of the JPA providers we test with, however, Hibernate has issues
with --mappedSuperclass as detailed in ROO-292 and ROO-747. We recommend you do not
use --mappedSuperclass in combination with Hibernate. We have found OpenJPA works reliably
in all cases, so you might want to consider switching to OpenJPA if you are seriously impacted
by this issue (the "persistence setup" command can be used multiple times, which is useful for
experimentally switching between different JPA providers).
• Integration testing limitations: The data on demand mechanism (which is used for integration
tests) has limited JSR 303 (Bean Validator) compatibility. Roo supports fields using @NotNull,
@Past and @Future, @Size, @Min, and @Max. No other validator annotations are formally
supported, although many will work. To use other validator annotations, you may need to edit
your DataOnDemand.java file and add a manual getNewTransientEntity(int) method. Refer to a
generated *_Roo_DataOnDemand.aj file for an example. Alternately, do not use the integration test
functionality in Roo unless you have relatively simple validation constraints or you are willing to
provide this data on demand method.
• Tomcat 5.5: Tomcat 5.5 can not be supported by the scaffolded Spring MVC Web UI. Tomcat 5.5
does not support the JSP 2.1 API. Roo makes extensive use of the JSP 2.1 API in the scaffolded Web
UI (specifically expression language features). Furthermore, the JSP 2.0 API does not support JDK
1.1.3.BUILD-SNAPSHOT 157
Upgrade Notes and Known Issues
5 enums (a feature that Roo would need). See ROO-680 for more details. The following forum post
offers a workaround for the JSP 2.1 incompatibility issue. Please be aware that this has not been
tested by the Roo team and Tomcat 5.5 does officially support the JSP 2.0 API.
• Applications with a scaffolded Spring MVC UI are currently not deployable to Google App Engine
due to incompatibilities in the JSP support and JSTL. See ROO-1006 for details.
You can always rely on the natural sort order of the version numbers to arrive at the latest available
version. For example, 1.0.4.RELEASE is more recent than 1.0.4.RC2. This is because "RELEASE"
sorts alphabetically lower than "RC2". The TYPE segment can generally be broken into two further
undelimited portions, being the release type and a numeric increment. For example, RC1 means release
candidate 1 and RC4 means release candidate 4. One exception to this is RELEASE means the final
general availability of that release. Other common release types include "A" for alpha and "M" for
milestone.
We make no guarantees regarding the compatibility of any release that has a TYPE other than
"RELEASE". However, for "RELEASE" releases we aim to ensure you can use a given "RELEASE"
with any other "RELEASE" which has the same MAJOR.MINOR version number. As such you should
be able to switch from 1.0.4.RELEASE to 1.0.9.RELEASE without any changes. However, you might
have trouble with 1.0.4.RELEASE to 1.0.9.RC1 as RC1 is a work-in-progress and we may not have
identified all regression issues. Obviously this version portability is only our objective, and sometimes
we need to make exceptions or may inadvertently overlook an issue. We appreciate you logging a bug
report if you identify a version regression that violates the conventions expressed in this section, so that
at least we can confirm it and either attempt to remedy it on the next release of that MAJOR.MINOR
version range or bring it to people's attention in the other sections of this appendix.
When upgrading you should review the issue tracker for what has changed since the last version.
Because most releases include a large number of issues in the release notes, we attempt to highlight
any major issues that may require your attention in the sections below. These notes are not
all-encompassing but simply pointers to the main upgrade-related issues that most people should be
aware of. They are also written assuming you are maintaining currency with the latest public releases
of Spring Roo and therefore the changes you may need to make to your project are cumulative.
1.1.3.BUILD-SNAPSHOT 158
Upgrade Notes and Known Issues
• Run the backup command using your currently-installed (ie existing) version of Spring Roo. This
will help create a ZIP of your project, which may help if you need to revert. Don't install the new
version of Roo until you've firstly completed this backup. Naturally you can skip this step if you
have an alternate backup technique and have confidence in it.
• Edit your project's pom.xml and verify the Spring Roo annotations JAR matches the new Roo release
you are installing. Spring Roo 1.1.0.M3 and above will do this automatically on your behalf when
you load it on an existing project.
• Edit your project's pom.xml and verify that major libraries match the new versions that are now
used by Roo. The simplest approach to doing this is to create a new directory and use "roo script
clinic.roo" and then diff your existing pom.xml against the newly-created Petclinic pom.xml.
• After modifying the pom.xml as described above, you will need to update your Eclipse .classpath
file. The simplest way to achieve this is to use mvn eclipse:clean eclipse:eclipse from the
command prompt, or use the perform eclipse command at the roo> shell prompt. You can skip this
step if you use m2eclipse, as would be the case for any SpringSource Tool Suite user.
Please refer to the specific upgrade section of this appendix for further instructions concerning
upgrading to a particular version of Roo.
If you experience any difficulty with upgrading your projects, please use the community support forum
for assistance.
• Complete the steps recommended in the Upgrading To Any New Release section.
• Complete the steps recommended in the Upgrading To Any New Release section.
• Converters for displaying related entities on JSP pages are now registered from
a centralized ConversionService artifact rather than from individual controllers. The
change is transparent if you've never set @RooWebScaffold(registerConverters=false)
or plugged in a custom ConversionService through <mvc:annotation-driven
conversion-service="myConversionService"/>. If you have then read on.
1.1.3.BUILD-SNAPSHOT 159
Upgrade Notes and Known Issues
• Complete the steps recommended in the Upgrading To Any New Release section.
• Complete the steps recommended in the Upgrading To Any New Release section.
• There have been changes made to the web.xml configuration to allow deployment of GWT
scaffolded applications to GAE. Please compare a web.xml produced in a new Spring Roo project
with your current project's web.xml to identify differences.
• The GWT maven artifacts in your local maven repository should be removed so they can
be replaced with the latest versions. Make sure to delete ~/.m2/repository/com/google/gwt and
org/codehaus/mojo/gwt-maven-plugin.
• Complete the steps recommended in the Upgrading To Any New Release section.
• There have been changes made to the web.xml configuration following the adoption of Spring
Framework 3.0.4 improvements around root servlet mapping of DispatcherServlet. Please
compare a web.xml produced in a new Spring Roo project with your current project's web.xml to
identify differences.
• If you are trying the early-access Google Web Toolkit (GWT) support, please be aware that from
Spring Roo 1.1.0.M3 until Spring Roo 1.1.0.RELEASE we will be using GWT 2.1 "snapshot" JARs.
This enables you to have access to the latest improvements in GWT 2.1.
• Complete the steps recommended in the Upgrading To Any New Release section.
1.1.3.BUILD-SNAPSHOT 160
Upgrade Notes and Known Issues
• Complete the steps recommended in the Upgrading To Any New Release section.
• If you used Roo 1.0.2's web MVC scaffolding, be aware there are considerable changes to the
web tier to support our new MVC features (such as JSPX round-tripping and easy tags). The
recommended approach is therefore to start a new project with Roo 1.1.0.M1 to identify the changes
that are needed to src/main/webapp.
• Complete the steps recommended in the Upgrading To Any New Release section.
• If you are using Spring Security in your Roo application, it is recommended you review issue
ROO-579 and consider disabling the ShallowEtagHeaderFilter filter in your web.xml.
• Complete the steps recommended in the Upgrading To Any New Release section.
• Complete the steps recommended in the Upgrading To Any New Release section.
• Due to CSS issues discovered in the Roo RC4 release (ROO-480), the standard.css, alt.css and
the layout.jspx files required adjustment. To update these three files, please replace them with the
same files generated in a dummy project using Roo 1.0.0.RELEASE.
• Complete the steps recommended in the Upgrading To Any New Release section.
• Roo 1.0.0.RC4 takes advantage of the new type conversion API introduced in Spring Framework
3.0.0.RC3 (see chapter 5 of the Spring reference documentation) which is aimed to replace property
editors. To remove existing property editors from your current project you can issue the following
command: rm -rf src/main/java/com/foo/domain/*Editor.java (depending on your package
naming convention)
• The easiest way to update the web artifacts is to delete the old ones completely. You can use the
following command from a *nix prompt to achieve this: rm -rf src/main/webapp/*
1.1.3.BUILD-SNAPSHOT 161
Upgrade Notes and Known Issues
• Another (optional) step is to replace the web controllers. This step is only required if you have
used the dateFormat @RooWebScaffold(dateFormat="..") attribute in the @RooWebScaffold
annotation: rm -rf src/main/java/com/foo/web/* (depending on your package naming
convention). Alternatively, you can simply remove this attribute from the @RooWebScaffold
annotation. Note, date formats can now be defined via the field date command (see ROO-453
for further information).
• Run the controller command again to regenerate all necessary web artifacts. You might wish to use
either the controller all or controller scaffold command. This will recreate all web artifacts.
• Complete the steps recommended in the Upgrading To Any New Release section.
• If you had previously used the "test mock" or "persistence exception translation"
commands, we have moved the resulting AspectJ files to the Spring Aspects project
(which has always been a dependency of all Roo projects). This will mean you
automatically receive improvements made to these features in the future as part of the
Spring Framework release cycle. You should therefore delete the following files if your
project contains them: Jpa_Exception_Translator.aj, AbstractMethodMockingControl.aj,
JUnitStaticEntityMockingControl.aj and MockStaticEntityMethods.aj. You must also ensure
you use Spring Framework 3.0.0.RC2 or above (which is the project which contains the Spring
Aspects project). See ROO-315 and ROO-316 for further information.
• Do not attempt to use the Spring Roo integration built into SpringSource Tool Suite (STS) 2.2.0 or
earlier with Spring Roo 1.0.0.RC3 or above. You must upgrade to STS 2.2.1 or above if you wish to
use Roo 1.0.0.RC3 with the STS integration. This is due to an internal API change made to support
third-party add-on development. If you are using STS 2.2.0 (or earlier) and are unable to upgrade,
you can of course use Roo outside of any version of STS without any issue. The upgrade requirement
is simply to access the STS integration, such as CTRL + R commands and STS' embedded Roo shell.
1.1.3.BUILD-SNAPSHOT 162
Appendix C. Project Background
This chapter briefly covers the history of the Spring Roo project, and also explains its mission statement
in detail.
C.1. History
The Spring Roo available today is the result of relatively recent engineering, but the inspiration for
the project can be found several years earlier.
The historical motivation for "ROO" can be traced back to 2005. At that time the project's founder,
Ben Alex, was working on several enterprise applications and had noticed he was repeating the same
steps time and time again. Back in 2005 it was common to use a traditional layering involving DAOs,
services layer and web tier. A good deal of attention was also focused around that time on avoiding
anaemic domain objects and instead pursuing Domain Driven Design principles.
Pursuing a rich domain model led to domain objects that reflected proper object oriented principles,
such as careful application of encapsulation, immutability and properly defining the role of domain
objects within the enterprise application layering. Rich behaviour was added to these entities
via AspectJ and Spring Framework's recently-created @Configurable annotation (which enabled
dependency injection on entities irrespective of how the entities were instantiated). Naturally the web
frameworks of the era didn't work well with these rich domain objects (due to the lack of accessors,
mutators and no-argument constructors), and as such data transfer objects (DTOs) were created. The
mapping between DTOs and domain objects was approached with assembly technologies like Dozer.
To make all of this work nicely together, a code generator called Real Object Oriented - or "ROO" - was
created. The Real Object Oriented name reflected the rich domain object principles that underpinned
the productivity tool.
ROO was presented to audiences at the SpringOne Americas 2006 and TSSJS Europe 2007
conferences, plus the Stockholm Spring User Group and Enterprise Java Association of Australia. The
audiences were enthusiastic about the highly productive solution, with remarks like "it is the really
neatest and newest stuff I've seen in this conference" and "if ROO ever becomes an open source project,
I'm guessing it will be very polished and well-received". Nonetheless, other priorities (like the existing
Spring Security project) prevented the code from becoming release-ready. More than twelve months
later Ben was still regularly being asked by people, "whatever happened to the ROO framework?" and
as such he set out about resuming the project around August 2008.
By October 2008 a large amount of research and development had been undertaken on the
new-and-improved ROO. The original productivity ideas within ROO had been augmented with
considerable feedback from real-life use of ROO and the earlier conferences. In particular a number
of projects in Australia had used the unreleased ROO technology and these projects provided a great
deal of especially useful feedback. It was recognised from this feedback that the original ROO model
suffered from two main problems. First, it did not provide a highly usable interface and as such
developers required a reasonable amount of training to fully make use of Roo. Second, it imposed
a high level of architectural purity on all applications - such as the forced use of DTOs - and many
people simply didn't want such purity. While there were valid engineering reasons to pursue such an
architecture, it was the productivity that motivated people to use ROO and they found the added burden
of issues like DTO mapping cancelled out some of the gains that ROO provided. A mission statement
was drafted that concisely reflected the vision of the project, and this was used to guide the technical
design.
1.1.3.BUILD-SNAPSHOT 163
Project Background
In early December 2008 Ben took a completely rewritten ROO with him to SpringOne Americas
2008 and showed it to a number of SpringSource colleagues and community members. The response
was overwhelming. Not only had the earlier feedback been addressed, but many new ideas had been
incorporated into the Java-only framework. Furthermore, recent improvements to AspectJ and Spring
had made the entire solution far more effective and efficient than the earlier ROO model (such as
annotation-based component scanning, considerable enhancements to AJDT etc).
Feedback following the December 2008 demonstrations led to considerable focus on bringing the ROO
technology to the open source community. The name "ROO" was preserved as a temporary codename,
given that we planned to select a final name closer to official release. The "ROO" project was then
publicly presented on 27 April 2009 during Rod Johnson's SpringOne Europe keynote, "The Future
of Java Innovation". As part of the keynote the ROO system was used to build a voting application
that would allow the community to select a final name for the new project. The "ROO" name was left
as an option, although the case was changed to "Roo" to reflect the fact it no longer represented any
acronym. The resulting votes were Spring Roo (467), Spring Boost (180), Spring Spark (179), Spring
HyperDrive (64) and Spring Dart (62). As such "Spring Roo" became the official, community-selected
name for the project.
Roo 1.0.0.A1 was released during the SpringOne Europe 2009 conference, along with initial tooling for
SpringSource Tool Suite. The Roo talk at the SpringOne Europe 2009 conference was the most highly
attended session and there was enormous enthusiasm for the solution. Roo 1.0.0.A2 was published
a few weeks later, followed by several milestones. By SpringOne/2GX North America in October
2009, Roo 1.0.0 had reached Release Candidate 2 stage, and again the Roo session was the most
highly attended session of the entire conference. SpringSource also started hosting the highly popular
Spring Discovery Days and showing people around the world what they could do with the exciting
new Roo tool. Coupled with Twitter, by this stage many members of the Java community had caught
a glimpse of Roo and it was starting to appear in a large number of conferences, user group meetings
and development projects - all before it had even reached 1.0.0 General Availability!
• "and sustainably improve": A one-off improvement in productivity isn't enough. The productivity
improvement needs to sustain beyond the initial jump-start, and continue unabated over a multi-year
period. Productivity must remain high even in the face of radically changing requirements, evolving
project team membership, and new platform versions
• "Java developer productivity": Our focus is unashamedly on developers who work with the most
popular programming language in the world, Java. We don't expect Java developers to learn new
programming languages and frameworks simply to enjoy a productivity gain. We want to harness
their existing Java knowledge, skills and experience, rather than expect them to unlearn what
they already know. The conceptual weight must be attainable and reasonable. We always favour
evolution over revolution, and provide a solution that is as fun, flexible and intuitive as possible.
1.1.3.BUILD-SNAPSHOT 164
Project Background
• "without compromising": Other tools, methodologies and frameworks claim to create solutions that
provide these benefits. However, they impose a serious cost in critical areas. We refuse to make
this compromise.
• "engineering integrity": We embrace OO and language features the way Java language designers
intended, greatly simplifying understanding, refactoring, testing and debugging. We don't force
projects with significant performance requirements to choose between developer productivity or
deployment cost. We move processing to Generation IV web clients where possible, embrace
database capabilities, and offer an optimal approach to runtime considerations.
• "or flexibility": Projects are similar, but not identical. Developers need the flexibility to use
a different technology, pattern or framework when required. While we don't lock developers
into particular approaches, we certainly provide an optimal experience when following our
recommendations. We ensure that our technology is interface agnostic, gracefully supporting both
mainstream IDEs plus the command line. Of course, we support any reasonable deployment
scenario, and particularly the emerging class of Generation IV web clients.
We believe that Spring Roo today represents a successful embodiment of this mission statement.
While we still have work to do in identified feature areas such as Generation IV web clients, these are
easily-achieved future directions upon the existing Roo foundation.
1.1.3.BUILD-SNAPSHOT 165
Appendix D. Roo Resources
As an open source project, Spring Roo offers a large number of resources to assist the community
learn, interact with one another and become more involved in the project. Below you'll find a short
summary of the official project resources.
The project home page provides a brief summary of Roo's main features and links to most of the other
project resources. Please use this URI if you are referring other people to the Spring Roo project, as
it is the main landing point for the project.
From the main Roo web site you'll also find links to our "resources index". The resources index
provides convenient, up-to-date links to all of the services shown below, as well as third-party add-ons
you are able to install.
You can always access the latest Spring Roo release ZIP by visiting the above URI. The download
site not only provides the download itself, but also provides access to all historically released versions
plus SHA1 hash codes of those files.
For fast and free end user support for all official Spring projects, the Spring Community Forum is an
excellent place to visit. Because Roo is an official top-level Spring project, of course you'll find there
is a dedicated "Spring Roo forum" for all your questions, comments and experiences.
The Roo project does not have a "mailing list" or "newsgroup" as you might be familiar with from
other open source projects, although commercial support options are available.
Extensive search facilities are provided on the community forums, and the Roo developers routinely
answer user questions. One excellent way of contributing to the Roo project is to simply keep an eye
on the forum messages and help other people. Even recommendations along the lines of, "I don't know
how to do what you're trying to do, but we usually tackle the problem this way instead...." are very
helpful to other community members.
When you ask a question on the forum, it's highly recommended you include a small Roo sample script
that can be used to reproduce your problem. If that's infeasible, using Roo's "backup" command is
another alternative and you can attach the resulting ZIP file to your post. Other tips include always
1.1.3.BUILD-SNAPSHOT 166
Roo Resources
specifying the version of Roo that you're running (as can be obtained from the "version" command),
and if you're having trouble with IDE integration, the exact version of the IDE you are using (and,
if an Eclipse-based IDE, the version of AspectJ Development Tools in use). Another good source of
advice on how to ask questions on the forum can be found in Eric Raymond's often-cited essay, "How
to Ask Smart Questions".
If you believe you have found a bug or are experiencing an issue, it is recommended you first log a
message on the forum. This allows other experienced users to comment on whether it appears there
is a problem with Roo or perhaps just needs to be used a different way. Someone will usually offer a
solution or recommend you log a bug report (usually by saying "please log this in Jira"). When you
do log a bug report, please ensure you link to the fully-qualified URI to the forum post. That way
the developer who attempts to solve your bug will have background information. Please also post the
issue tracking link back in thread you started on the forum, as it will help other people cross-reference
the two systems.
D.4. Twitter
Roo Hash Code (please include in your tweets, and also follow for low-volume announcements):
@SpringRoo
Follow the core Roo development team for interesting Roo news and progress (higher volume
than just following @SpringRoo, but only a few Tweets per week): @benalexau, @schmidtstefan,
@alankstewart, and @jimbotyrrell.
Many people who use Roo also use Twitter, including the core Roo development team. If you're a
Twitter user, you're welcome to follow the Roo development team (using the Twitter IDs above) to
receive up-to-the-minute Tweets on Roo activities, usage and events.
The Roo team also monitors Tweets that include @SpringRoo, so if you're Tweeting about Roo, please
remember to include @SpringRoo somewhere in the Tweet. If you like Roo or have found it helpful
on a project, please Tweet about it and help spread the word!
We do request that you use the Community Forums if you have a question or issue with Roo, as
140 characters doesn't allow us to provide in-depth technical support or provide a growing archive of
historical answers that people can search against.
Spring projects use Atlassian Jira for tracking bugs, improvements, feature requests and tasks. Roo
uses a public Jira instance you're welcome to use in order to log issues, watch existing issues, vote for
existing issues and review the changes made between particular versions.
As discussed in the Community Forums section, we ask that you refrain from logging bug reports until
you've first discussed them on the forum. This allows others to comment on whether a bug actually
exists. When logging an issue in Jira, there is a field explicitly provided so you can link the forum
discussion to the Jira issue.
Please note that every commit into the Roo source repository will be prefixed with a particular Jira
issue number. All Jira issue numbers for the Roo project commence with "ROO-", providing you an
easy way to determine the rationale of any change.
1.1.3.BUILD-SNAPSHOT 167
Roo Resources
Because open source projects receive numerous enhancement requests, we generally prioritise
enhancements that have patches included, are quick to complete or those which have received a large
number of votes. You can vote for a particular issue by logging into Jira (it's fast, easy and free to
create an account) and click the "vote" link against any issue. Similarly you can monitor the progress
on any issue you're interested in by clicking "watch".
Enhancement requests are easier to complete (and therefore more probable to be actioned) if they
represent fine-grained units of work that include as much detail as possible. Enhancement requests
should describe a specific use case or user story that is trying to be achieved. It is usually helpful to
provide a Roo sample script that can be used to explain the issue. You should also consider whether
a particular enhancement is likely to appeal to most Roo users, and if not, whether perhaps writing it
as an add-on would be a good alternative.
The Subversion source control system is currently used by Roo for mainline development. There are
two repository URIs, one for anonymous access and the other for people with commit access. Both
URIs contain the same source code.
Historical releases of Roo can be accessed by the "release_xxx" branches within Subversion. The
mainline development of Roo occurs on the "trunk" branch.
To detailed information about how to check out and build Roo from Subversion, please refer to the
Development Processes chapter.
To assist those who wish to simply review the current Roo code but not check it out fully onto their
own computer, Spring Roo offers a public Atlassian FishEye instance. You can use this to not only
view the current source code, but also access old releases, perform sophisticated searches and even
build graphs and reports.
If you need to link to source code from an issue report or forum post, please use the FishEye service
to provide a fully-qualified URI.
SpringSource (a division of VMware) employs the Roo development team and offers a wide
range of products and professional services around Roo and the technologies which Roo enables.
Available professional services include training, consulting, design reviews and mentoring, with
products including service level agreement (SLA) backed support subscriptions, certified builds,
indemnification and integration with various commercial products. Please visit the above URI to learn
more about SpringSource products and services and how these can add value to your build-run-manage
application lifecycle.
1.1.3.BUILD-SNAPSHOT 168
Roo Resources
D.9. Other
Please let us know if you believe it would be helpful to list any other resources in this documentation.
1.1.3.BUILD-SNAPSHOT 169