Getting Started with Spring Roo |
|

Update: The third installment of the "Introducing Spring Roo" blog series is now available and covers Roo's internal architecture in detail.
I have a confession to make. While many of you would know I've been busily working away on Spring Roo in recent months, I also have a separate project that hasn't made it into Subversion. The other project is planning our wedding, as next month my fiancée and I are traveling overseas to get married. So as I pondered what I could show you in this blog entry about Roo, it struck me that I should take the opportunity to build our wedding's RSVP site using Roo! So today we'll be learning how to build a wedding RSVP site using Roo, which some of my colleagues have commented is an enterprising example of pursuing work-life balance.
Progress Update
If you missed the first installment in the Spring Roo blog series on 1 May 2009, in brief I introduced the vision of SpringSource's new open source productivity tool for those wanting to rapidly build best practice Spring applications in Java. As many people discovered who played around with the alpha releases, Spring Roo offers a powerful and easy-to-use approach to productive application development, with much of the motivation behind Roo emerging in the first Jira issue, ROO-1 (logged by Rod Johnson, Father of Spring and CEO of SpringSource).
Today I am pleased to announce that we have just released Spring Roo 1.0.0.M1. This release not only features numerous fixes, enhancements and a 31% performance improvement, but also an exciting range of new capabilities including email services, JMS, Spring Web Flow, simplified installation and automatic Selenium support. That's on top of those many capabilities already present in the alpha releases, as mentioned in my earlier blog entry.
In addition to working on the first milestone release, over the last month we've also established the public project infrastructure typical of open source projects. We now have available a community support forum, Jira issue tracking, public Subversion repository, FishEye source monitoring and so on. Some of the comments reported on the #roo Twitter channel over the last month have included "I'm impressed", "liking it", "custom roo addons [are] very easy", "here comes some innovation", "the first milestone release will be cool!", "Roo looks interesting and works", "very impressive tool", "very cool" etc. We've also started seeing the first community-produced add-ons, underscoring the ease at which you can extend Roo with your own custom features.
Earlier this month we also concluded the community project naming competition, with "Spring Roo" easily emerging as the winner. A total of 952 eligible votes were received, distributed between Spring Roo (467), Spring Boost (180), Spring Spark (179), Spring HyperDrive (64) and Spring Dart (62). Thank you to everyone who voted!
Installation
Now that we've added simplified installation to Spring Roo 1.0.0.M1, installation is as simple as downloading the ZIP, extracting it, and then adding the "bin" directory to your path:
- Windows users should load Control Panel, then click System, Advanced, Environment Variables, and double-click the "Path" entry. Append to the end of the path, ";C:\spring-roo-1.0.0.M1\bin" (or wherever you installed Roo).
- *nix users should create a symbolic link to the roo.sh shell script. A command such as "sudo ln -s ~/spring-roo-1.0.0.M1/bin/roo.sh /usr/bin/roo" will generally do the trick.
While you can use Spring Roo standalone, I also recommend that you download SpringSource Tool Suite (STS) 2.3.0 or above. STS is our free, Eclipse-based IDE and offers many features to simplify Spring application development. For example, if you download STS 2.3.0 or above you will receive inbuilt Spring Roo support and don't even need to install the standalone Spring Roo shell.
This blog will be written assuming you're using the standalone Spring Roo shell. Unless otherwise specified, all commands work the same in both standard Spring Roo and also STS 2.3.0 or above. One of the main differences is when using the Roo shell you press TAB for completion options, whereas within STS the TAB key is replaced by CTRL + SPACE. We use CTRL + SPACE because it's the more traditional key combination for completions within Eclipse-based IDEs.
You should also verify you have Maven 2.0.9 or above installed. While Roo itself doesn't use Maven and can operate without it installed, projects created by Roo currently use Maven. In addition, be sure to delete the ROO_HOME variable if you installed one of the earlier Roo alpha releases.
Application Requirements
Now that you've installed Roo, let's consider the requirements of our wedding RSVP application. We'll then build the application using a combination of Roo and some manual coding. The requirement for some manual coding reflects an underlaying philosophy of Roo that you will still need to develop those parts of your application that differentiates it from the next. However, you'll see that Roo was designed to enable manual coding and customization in a completely transparent, familiar and round-trip supporting manner.
Despite having online RSVP, we've still sent out paper wedding invitations. On the back of each invitation is a small "invitation code". These are not easily guessed, but they're easy to read and type in (no UUIDs!). The wedding invitation text invites the guest to visit our wedding RSVP site in order to RSVP. When they visit the wedding RSVP site, the guest will be asked to enter their invitation code.
Once the guest enters their invitation code, any existing RSVP record will be retrieved and allow them to edit it. If they haven't previously RSVPed, they'll be presented with a new RSVP form to fill in. The form will simply ask the guest how many people are attending, and any special requests (eg dietary needs). They'll also be asked to enter their email address, and if one is provided the application will send an email-based confirmation of their RSVP. We'll also keep a record of what date and time they RSVPed, which will be useful if they change their RSVP several times.
Creating a Persistent Project
Now that we have an idea of a real-world application that we'd like to build, let's use Roo to build it. The first step is to create an empty directory and load Roo:
$ mkdir wedding $ cd wedding $ roo
If you followed the above installation instructions, you should be greeted with the Roo logo shown below. If you don't see a message like this, please go back and check your installation is correct.

There are quite a few usability features within Roo. If you type "hint" you will be presented with step-by-step instructions. Or if you type "help" you will see all of the commands currently available (these change at different phases of your project lifecycle). Plus you can press TAB in almost all cases for completion services. If you're learning Roo, "hint" is your friend. Not only will it teach you the commands, but it will also teach you about the shell and how the keyboard features work. Get into the habit of using "hint" whenever in doubt, especially during your first few Roo projects.
Let's begin our wedding project. After you type the "create project" command into the Roo shell, you should receive the following output:
roo> project --topLevelPackage com.wedding Created /home/balex/wedding/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
As shown from the console output, Roo has created a Maven 2 project structure. Even if you quit Roo at this point and never reload it, at this moment you have a properly-configured Spring 3 web application, complete with URL rewriting, annotation-based classpath scanning and dependency injection of any class – even those created with the "new" keyword or via an ORM like Hibernate. You can even use "mvn tomcat:run" and start an embedded Tomcat container.
If you typed "hint" at this point, Roo would suggest you install a JPA provider and database. Let's do that now:
roo> persistence setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT 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
Notice that we've selected Hibernate and a persistent Hypersonic database in the command. This selection happened via the TAB button, so we didn't actually need to type those commands and arguments fully. Notice also the two "Managed" statements at the bottom. These denote a file or directory Roo is managing. Roo has inbuilt file undo services, so should something go wrong, it will automatically rollback the problematic command.
Because Roo uses JPA, we enjoy the benefits of portability across different JPA implementations. If you look at the code that Roo generates, you'll see that not a single line of it is specific to a particular persistence provider. You'll also see the Roo-provided code is extremely efficient. One of the great strengths of Java is its significant performance, and Roo does everything from avoiding reflection to optimizing string operations in your toString() methods (and everything in between) to maximise runtime performance of your applications.
As we asked for a persistent database, it is stored in ~/wedding.* by default. There is a "database properties list" command which will show you the database configuration:
roo> database properties list
database.driverClassName = org.hsqldb.jdbcDriver
database.password =
database.url = jdbc:hsqldb:${user.home}/wedding
database.username = sa
While the default location would work just fine, let's change it to somewhere else:
roo> database properties set --key database.url --value jdbc:hsqldb:/home/balex/our-wedding Managed SRC_MAIN_RESOURCES/META-INF/spring/database.properties
As shown by the console output, all Roo did was edit a stock-standard database.properties file. You could have just as validly edited your project files using a text editor or IDE. Roo doesn't mind. It was designed from the very beginning so that you could use other tools concurrently with Roo and everything would still work properly.
One reason you might like to use a "database properties set" command via Roo is because you're making a standalone script that can be replayed later. You can use the "script filename.roo" command to execute scripts, which are simply Roo commands in a standard text file format. I've included the wedding.roo script in the Roo 1.0.0 distribution for your convenience. Note that comments can also be included in the scripts using normal Java comment syntax (//, /* and */).
Creating an Entity
Let's now create a JPA entity. This entity will be stored in our database and represent the entire domain model for our application. You can create entities using your choice of IDE, text editor or the Roo shell:
roo> entity --class ~.domain.Rsvp Created SRC_MAIN_JAVA/com/wedding/domain Created SRC_MAIN_JAVA/com/wedding/domain/Rsvp.java Created SRC_MAIN_JAVA/com/wedding/domain/Rsvp_Roo_Entity.aj Created SRC_MAIN_JAVA/com/wedding/domain/Rsvp_Roo_ToString.aj Created SRC_MAIN_JAVA/com/wedding/domain/Rsvp_Roo_Configurable.aj
At this point I imagine some of you are wondering, "what are those .aj files?". In a nutshell, these are AspectJ inter-type declarations (ITDs) that very effectively deliver separation of concerns while also maintaining compatibility with future versions of the relevant Roo add-on. The .aj files are automatically created, maintained and deleted by Roo, allowing end users to safely ignore them. Indeed STS 2.1.0+ automatically hides them by default, just like Eclipse-based IDEs hide .classpath, .project and .settings resources. After all, these resources are merely internal outputs of the tool and it's pretty rare you would even open them – let alone maintain them yourself. I'm going to talk a lot more about these and other Roo internals in my next blog entry, so I'll defer further discussion until then.
You might have noticed we created the Rsvp entity within the "~.domain" package. The "~" character automatically expands to your project's top-level package, which you may recall we specified when originally creating the project. As such Roo fully understands the concept of Java packages, and allows you to structure your project packages in whatever way you find most intuitive.
Naturally an entity would normally contain some fields, so let's add them (Roo's output is omitted, as it simply manages the same files as listed above):
roo> field string code --notNull --sizeMin 1 --sizeMax 30 roo> field string email --sizeMax 30 roo> field number attending --type java.lang.Integer roo> field string specialRequests --sizeMax 100 roo> field date confirmed --type java.util.Date
In the first line you'll note we use a –notNull argument, together with a –sizeMin and –sizeMax argument. These refer to the new Bean Validation standard, which is otherwise known as JSR 303. This particular standard offers automatic web and persistence tier validation, including creating the correct DDL for the tables in your database. One of the advantages of using Roo is you gain the benefit of relevant standards like JSR 303, JPA, the Servlet Specification and REST without any extra effort. Naturally you don't need to use the JSR 303 arguments if you don't wish to do so.
Another point to note from the above field commands is we didn't specify which entity we wanted to insert the fields into. Roo automatically determines you probably want to add the fields to Rsvp, as that's the last entity you worked with. You could also specify an "–class ~.SomeEntity" argument if you wish to be explicit or target the fields at another entity (in which case that entity will become the default for subsequent entity-related commands).
Proving it Works: JUnit, Web Tier and Selenium
By now we have an application that would actually work if we deployed it. But don't take my word for it – let's add a couple of features so that you can try the application out for yourself.
Let's start with JUnit integration tests. You can obtain an integration test with one command:
roo> test integration Created SRC_TEST_JAVA/com/wedding/domain Created SRC_TEST_JAVA/com/wedding/domain/RsvpDataOnDemand.java Created SRC_TEST_JAVA/com/wedding/domain/RsvpIntegrationTest.java Created SRC_TEST_JAVA/com/wedding/domain/RsvpDataOnDemand_Roo_Configurable.aj Created SRC_TEST_JAVA/com/wedding/domain/RsvpDataOnDemand_Roo_DataOnDemand.aj Created SRC_TEST_JAVA/com/wedding/domain/RsvpIntegrationTest_Roo_Configurable.aj Created SRC_TEST_JAVA/com/wedding/domain/RsvpIntegrationTest_Roo_IntegrationTest.aj
This integration test will verify the common JPA operations like persist, remove, find, merge etc all work. A total of eight tests are performed per entity, and all build on Spring Framework's extensive integration test infrastructure. While we could run the integration tests at this stage, it's trivial to add a web tier as well:
roo> controller scaffold ~.web.RsvpController Created SRC_MAIN_JAVA/com/wedding/web Created SRC_MAIN_JAVA/com/wedding/web/RsvpController.java Created SRC_MAIN_WEBAPP/WEB-INF/config Created SRC_MAIN_WEBAPP/WEB-INF/config/webmvc-config.xml Created SRC_MAIN_JAVA/com/wedding/web/RsvpController_Roo_Controller.aj Created SRC_MAIN_WEBAPP/images Created SRC_MAIN_WEBAPP/images/banner-graphic.png Created SRC_MAIN_WEBAPP/images/springsource-logo.png Created SRC_MAIN_WEBAPP/images/resultset_first.png Created SRC_MAIN_WEBAPP/images/resultset_next.png Created SRC_MAIN_WEBAPP/images/resultset_previous.png Created SRC_MAIN_WEBAPP/images/resultset_last.png Created SRC_MAIN_WEBAPP/images/us.png Created SRC_MAIN_WEBAPP/images/de.png Created SRC_MAIN_WEBAPP/images/list.png Created SRC_MAIN_WEBAPP/images/add.png Created SRC_MAIN_WEBAPP/styles Created SRC_MAIN_WEBAPP/styles/roo-menu-left.css Created SRC_MAIN_WEBAPP/styles/roo-menu-right.css Created SRC_MAIN_WEBAPP/WEB-INF/classes Created SRC_MAIN_WEBAPP/WEB-INF/classes/left.properties Created SRC_MAIN_WEBAPP/WEB-INF/classes/right.properties Created SRC_MAIN_WEBAPP/WEB-INF/layouts Created SRC_MAIN_WEBAPP/WEB-INF/layouts/layouts.xml Created SRC_MAIN_WEBAPP/WEB-INF/layouts/default.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views Created SRC_MAIN_WEBAPP/WEB-INF/views/dataAccessFailure.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/resourceNotFound.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/uncaughtException.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/index.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/views.xml Created SRC_MAIN_WEBAPP/WEB-INF/tags Created SRC_MAIN_WEBAPP/WEB-INF/tags/pagination.tagx Created SRC_MAIN_WEBAPP/WEB-INF/tags/language.tagx Created SRC_MAIN_WEBAPP/WEB-INF/tags/theme.tagx Created SRC_MAIN_WEBAPP/WEB-INF/i18n Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages.properties Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/messages.properties Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_de.properties Managed SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_de.properties Created SRC_MAIN_WEBAPP/images/show.png Created SRC_MAIN_WEBAPP/images/update.png Created SRC_MAIN_WEBAPP/images/delete.png Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp Managed SRC_MAIN_WEBAPP/WEB-INF/config/webmvc-config.xml Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/list.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/show.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/create.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/update.jspx Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/views.xml Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml Created SRC_MAIN_WEBAPP/WEB-INF/web.xml Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml Managed ROOT/pom.xml
The automatic web tier provided by Roo builds on Spring Framework 3's excellent REST support. All endpoints are completely RESTful and use clean, properly-formed URLs. Roo's automatic web tiers are useful in a number of situations, in particular:
- Programmatic access via REST clients
- Administrative section of an application
- To serve as a template for your manually-created controllers and JSPs
Let's wrap up with a Selenium test, which will actually verify our new RsvpController works:
roo> selenium test --controller ~.web.RsvpController Created SRC_MAIN_WEBAPP/selenium Created SRC_MAIN_WEBAPP/selenium/test-rsvp.xhtml Created SRC_MAIN_WEBAPP/selenium/test-suite.xhtml Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx Managed ROOT/pom.xml
Okay, let's see the application in action by running the following commands:
roo> perform test (Maven console output condensed) ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.wedding.domain.RsvpIntegrationTest Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.726 sec roo> quit $ mvn tomcat:run
You can now use your browser to visit http://localhost:8080/wedding. When you're ready to test the web tier, leave the Tomcat server running and then execute the following command:
$ mvn selenium:selenese
During execution of the Selenium tests, you should see an image similar to:

Security and Logging
So far we've created our wedding application, ran some integration tests, played around with it in a web browser, and verified correct operation of the web tier using automated Selenium testing. The next step is to fine-tune the Log4J-based logging:
roo> logging setup --package WEB --level DEBUG Created SRC_MAIN_RESOURCES/META-INF/spring/log4j.properties Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml
Let's now turn our attention to security. At present anyone can access our web site and use the existing RESTful administrative backend to create, update and delete RSVPs. Recall from the application requirements that we wanted to use invitations codes (printed on the back of the cards) to ensure only invited guests can RSVP. Fortunately, Spring Security offers us a very fast way of satisfying this requirement, and Roo can install Spring Security in one line:
roo> security setup Managed ROOT/pom.xml Created SRC_MAIN_RESOURCES/META-INF/spring/applicationContext-security.xml Created SRC_MAIN_WEBAPP/WEB-INF/views/login.jspx Managed SRC_MAIN_WEBAPP/WEB-INF/views/views.xml Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml
There are also similar commands like "web flow" and "jms setup", but we're not going to explore them in this blog entry. You can expect to see many more "install" commands in future versions of Roo (and you're welcome to add installer requests to the Roo issue tracker).
Manual Controllers, Dynamic Finders and Email Support
As mentioned above, our automatic web tier is perfectly suitable for the administrative backend of our application. But we also need a portion of the application this is suitable for prospective guests to use. This portion of the application must understand the relationship between invitation codes, managing RSVPs and sending emails. Because these requirements will require some programming, let's build a new controller:
roo> controller class --class ~.web.PublicRsvpController Created SRC_MAIN_JAVA/com/wedding/web/PublicRsvpController.java Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml Managed ROOT/pom.xml
The PublicRsvpController will respond to HTTP GET and POST requests. Two stubbed methods for these operations have automatically been provided in the PublicRsvpController.java source file.
If we consider the GET use case, our objective is to retrieve the correct RSVP for a particular invitation code. The way this will work is Spring Security will require people to login to use the application, and we'll treat each invitation code as a unique login name. As such, the GET method needs to obtain the currently logged on user's name from Spring Security and then retrieve the corresponding RSVP from the database. Normally you'd go and write a JPA QL query at this point to obtain the specific Rsvp instance that has the matching code, but because you're using Roo you can save yourself the trouble and instead use a dynamic finder.
Dynamic finders provide you with an almost unlimited range of pre-canned queries. These queries all internally use JPA QL, delivering maximum standards-based compatibility and portability. All dynamic finders (and other Roo methods) are implemented as properly-formed, type-safe Java methods – bringing all the normal advantages of familiarity, IDE code assist, debugger integration and significant runtime performance. You can list the available dynamic finders using a command such as this:
roo> finder list --class ~.domain.Rsvp --filter code,equ findRsvpsByCodeEquals(String code) findRsvpsByCodeNotEquals(String code)
Note the "–filter" argument is limiting the output to only those proposed method signatures that contain the "code" and "equ" strings. You can instruct Roo you'd like to see more combinations by omitting the "-filter" argument, or specifying "-depth 2" (or 3, 4 etc if you'd like more properties involved in your query).
Once you find the dynamic finder you'd like to use, simply add it:
roo> finder add --finderName findRsvpsByCodeEquals Managed SRC_MAIN_JAVA/com/wedding/domain/Rsvp.java Created SRC_MAIN_JAVA/com/wedding/domain/Rsvp_Roo_Finder.aj Managed SRC_MAIN_JAVA/com/wedding/web/RsvpController_Roo_Controller.aj Created SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/findRsvpsByCodeEquals.jspx Managed SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx Managed SRC_MAIN_WEBAPP/WEB-INF/views/rsvp/views.xml
If we consider the POST use case for our PublicRsvpController, our requirements specified that we should send our guests an email to confirm their RSVP. Normally we'd pull out the Spring reference guide and locate the section on configuring email support, but instead we'll just ask Roo to deal with it for us:
roo> email sender setup --hostServer 127.0.0.1 Created SRC_MAIN_RESOURCES/META-INF/spring/email.properties Managed SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml Managed ROOT/pom.xml roo> field email template --class ~.web.PublicRsvpController Managed SRC_MAIN_JAVA/com/wedding/web/PublicRsvpController.java Managed SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml Managed SRC_MAIN_JAVA/com/wedding/web/PublicRsvpController.java
The final command added a Spring MailSender field to PublicRsvpController, plus provided a method that shows us how to use it.
While on the topic of email integration, my colleague Stefan Schmidt has just published a separate blog entry showing how to use the Roo email and JMS add-ons together. The article shows you more advanced configuration options, such as how to use Gmail to send your email messages.
IDE Integration
We've now reached the point where you can use Eclipse/STS to finish the application off. Let's import the application into Eclipse/STS:
roo> perform eclipse (Maven console output condensed)
Finally, let's import the project into Eclipse/STS. You do this by loading Eclipse/STS, then selecting File > Import > Existing Projects into Workspace, and selecting the project's directory. If you're not using STS 2.3.0 or above, ensure you have separately installed AJDT 1.6.5 or above. When prompted by AJDT whether you'd like to enable JDT weaving, select to enable weaving. This will result in a better Roo experience when using Eclipse's Java editor.
Final Steps
We're now going to change several files using Eclipse/STS. The following screen shot shows the project structure we'll ultimately end up with, and I've highlighted those files we'll be changing:

Start by editing applicationContext-security.xml. Make some minor changes so that it resembles the following file:
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
<logout logout-url="/static/j_spring_security_logout"/>
<intercept-url pattern="/rsvp/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/static/**" access="permitAll" />
<intercept-url pattern="/login**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="admin1234" password="ignored" authorities="ROLE_ADMIN"/>
<user name="user12345" password="ignored" authorities="ROLE_USER"/>
<user name="user67890" password="ignored" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
The file above shows that the invitation codes are actually usernames, and we're ignoring passwords. Spring Security doesn't realize we're ignoring passwords, so we need to edit the src/main/webapp/WEB-INF/views/login.jspx and add an <input name="j_password" type="hidden" value="ignored"/> line within the form. Of course, the existing <div> containing the "j_password" label and input element should be deleted. Some appropriate text within the login.jsp explaining to guests where on the card they can find their invitation code should also be added to this file.
Security is now setup. Let's now open the PublicRsvpController.java file. As shown, Roo has already stubbed the email features, and provided you empty Spring MVC methods to complete. This is the only actual Java programming required in the entire application, and because these use the normal features of Spring MVC and Spring's MailSender class, I won't discuss them further here:
@RequestMapping("/publicrsvp/**")
@Controller
@SessionAttributes("rsvp")
public class PublicRsvpController {
@Autowired
private transient MailSender mailTemplate;
@RequestMapping
public String get(ModelMap modelMap) {
modelMap.put("rsvp", getRsvp());
return "publicrsvp";
}
@RequestMapping(method = RequestMethod.POST)
public String post(@ModelAttribute("rsvp") Rsvp rsvp, ModelMap modelMap) {
rsvp.setConfirmed(new Date());
if (rsvp.getId() == null) {
rsvp.persist();
} else {
rsvp.merge();
}
if (rsvp.getEmail().length() > 0) {
sendMessage("Ben Alex <ben.alex@springsource.com>", "RSVP to our wedding", rsvp.getEmail(), "Your RSVP has been saved: " + rsvp.toString());
}
modelMap.put("rsvp", rsvp);
return "thanks";
}
private Rsvp getRsvp() {
Rsvp rsvp = new Rsvp();
try {
String code = SecurityContextHolder.getContext().getAuthentication().getName();
rsvp.setCode(code);
// Cast due to http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#getSingleResult()
rsvp = (Rsvp) Rsvp.findRsvpsByCodeEquals(code).getSingleResult();
} catch (DataAccessException ignored) { /* no Rsvp for this code was found, so start a new Rsvp */ }
return rsvp;
}
private void sendMessage(String mailFrom, String subject, String mailTo, String message) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(mailFrom);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setTo(mailTo);
simpleMailMessage.setText(message);
mailTemplate.send(simpleMailMessage);
}
}
Note in the "get" and "post" methods we return a string, which should correlate with the JSP view name we would like rendered. As such our next step is to provide those two JSPs. Fortunately Roo built some JSP files that will serve as useful templates.
First rename src/main/webapp/WEB-INF/index.jsp to thanks.jsp. This will be the page displayed when the "post" method returns. You probably want to add something like, "Your RSVP has been confirmed: ${rsvp}".
Next copy src/main/webapp/WEB-INF/views/rsvp/create.jspx to src/main/webapp/WEB-INF/views/publicrsvp.jspx. This page should then be edited. You can safely delete the "code" and "confirmed" sections, as both are taken care of by the PublicRsvpController. You should also change the "form_url" variable assignment to <c:url value="/publicrsvp" var="form_url"/>.
Because Spring Roo uses Tiles to allow easy branding of each web view, you need to edit the src/main/webapp/WEB-INF/views/views.xml file. You need to rename the "index" definition to "thanks", and also add a new definition for "publicrsvp" to the new publicrsvp.jspx. The final file should resemble:
<tiles-definitions>
<definition extends="public" name="thanks">
<put-attribute name="body" value="/WEB-INF/views/thanks.jspx"/>
</definition>
<definition extends="public" name="dataAccessFailure">
<put-attribute name="body" value="/WEB-INF/views/dataAccessFailure.jspx"/>
</definition>
<definition extends="public" name="resourceNotFound">
<put-attribute name="body" value="/WEB-INF/views/resourceNotFound.jspx"/>
</definition>
<definition extends="public" name="uncaughtException">
<put-attribute name="body" value="/WEB-INF/views/uncaughtException.jspx"/>
</definition>
<definition extends="public" name="login">
<put-attribute name="body" value="/WEB-INF/views/login.jspx"/>
</definition>
<definition extends="public" name="publicrsvp">
<put-attribute name="body" value="/WEB-INF/views/publicrsvp.jspx"/>
</definition>
</tiles-definitions>
The very last step is to edit src/main/webapp/WEB-INF/urlrewrite.xml and change the URL rewrite rule for /. The /app/index should be modified to /app/publicrsvp/, which indicates to perform a GET of the new PublicRsvpController by default.
You should now be ready to test deployment. You have several options:
- Use "mvn tomcat:run" from the command line
- Right-click the project within Eclipse/STS and select Run As > Run on Server
- Right-click the project within STS and select Spring Tools > Open Roo Shell, then type "deploy –server someServer"
When you now visit http://localhost:8080/wedding, you will be prompted for your invitation code. Use one of the usernames listed in the applicationContext-security.xml file above. RSVP a few times, and you'll see the application correctly retrieves your previous RSVP record. You'll also see that it sends you an email, assuming you type an email address and have a properly configured SMTP server (edit mail.properties if you wish to change the SMTP server details). Login as the administrative user and you will see that you can access all RSVP records, change them and so on.
Naturally at this stage we'd normally tidy up the look and feel of publicly-visible parts of the application. Then we'd run "perform package" to provide a WAR that is ready to deploy to a production server environment such as SpringSource tc Server or SpringSource dm Server.
Conclusion
In this blog entry we covered the steps required to install Roo, use its shell, and rapidly build a realistic application that features:
- A best practice Spring Framework 3-based application architecture
- Maven 2-based project structure
- JPA-based persistence, in this case using Hibernate
- Database storage to a custom Hypersonic file location
- Bean Validation (JSR 303) support, including propagation of the constraints down to database DDL
- Automated JUnit integration tests that build on Spring Framework's integration test features
- An automated RESTful application backend
- Automated Selenium tests of your web tier
- Dynamic finders that serve a practical use case in our application
- Spring Security integration, including web URL security and a customised login page
- Email transmission (read more about emailing via Roo in Stefan's blog entry)
- Log4J configuration support
- URL rewriting that keeps the URLs clean and RESTful
- A manual web controller
- Embedded Tomcat server container usage
- Eclipse and STS integration
We'll be adding a lot of additional capabilities to Roo over the coming weeks and months, and my next blog posting will cover Roo's internals and architecture. In the meantime we very much welcome your Roo comments, experiences and feedback. The community forum is a great place to ask questions, and you can also follow us on Twitter. We hope that you enjoy using Spring Roo.
Similar Posts
- Using Postgres on Cloud Foundry
- Using Cloud Foundry Services with Spring: Part 4 – Spring Profiles
- Spring MVC: from JSP and Tiles to Thymeleaf
- GORM Gotchas (Part 1)
- Spring Roo 1.1.0.M1 Released





Neale says:
Added on May 27th, 2009 at 7:50 amBen,
Congrats on this, and thanks for holding the vision since your early work. Roo is rather an exciting development (that's in addition to using it to test the latest AspectJ Refactoring support in AJDT
You may want to revise the reference to STS 2.1.0, or get someone to clarfy the pre-registration pages of the STS site.
It's a *big pain* to read your article, and mistakenly think that STS 2.1.0 has been released (when actually it's still M1).
It wouldn't be such a pain if the STS pages actually reflected the state of play, but otherwise, it might just be worth saying "2.1.0M1 is the current release at date of writing" or something similar.
Hossam Karim says:
Added on May 27th, 2009 at 3:55 pmWOW!!
Any plans to move to the modeling next step?
Colin Sampaleanu (blog author) says:
Added on May 27th, 2009 at 4:16 pmJust a heads-up to anybody reading Ben's original post, that only the upcoming STS 2.1.0M2 (tentatively due end of week) will allow you to point to whatever external version of Roo you wish. The current STS 2.1.0M1 has an embedded older version (1.0 alpha 2) of Roo.
Colin
Don says:
Added on May 27th, 2009 at 6:31 pmThis looks a bit like Grails app development, or maybe a lot like Grails app dev. Does it make sense for Spring to have both Grails and Roo in their portfolio. Could you discuss the differences between the two?
hantsy says:
Added on May 27th, 2009 at 10:58 pmI think this is an alternative to AppFuse.
It is more productive.
Grzegorz Borkowski says:
Added on May 28th, 2009 at 8:15 amI have some mixed feelings about Roo.
Firstly, the "automatic controller" generated by Roo – why this class is empty, and all methods are in the aspect? I don't see any point in generating special aspect per class for keeping the core methods of this class. It looks awkward, besides some IDEs will not recognize the .aj file and you won't see syntax highlighting, code completion etc in such file. Also all the toString, getters and setters etc for entity classes are put into aspect class. What for? I have getters and setters in java, but I don't see any advantage of moving it into separate files: it's even worse, more places to see, harder refactoring…
Secondly, as Don mentioned earlier, Roo looks like a variation of Grails, using aspects instead of Groovy. Does it make sense to have two so similar products? What's the relationship between those two? What if you want to use both of them?
And last thing: why such strange name? What does ROO stands for? An animal from Winnie-the-Pooh? How do pronounce it? Like Foo? What this name is supposed to mean?
Petera says:
Added on May 28th, 2009 at 4:56 pmI suspect Roo is short for the marsupial that inherits the land from where the framework author is from.
I also have the same wonderment about using aspects. Why not just use Groovy as the DSL to short-cut code generation?
Ben Alex (blog author) says:
Added on May 28th, 2009 at 8:57 pmGrzegorz, as I mentioned in my post I am going to explore Roo architecture in the third installment in the series. We now have access to – courtesy of AJDT – a feature called "push in refactoring". What this does is move all the introduced members from the *.aj files to the correct *.java file. I have a lot of reasons I don't encourage people to do this, but the key point is that it's available for people who don't like the use of *.aj ITD files and simply want to use Roo to stub a project and then get rid of it. This underscores the flexibility of Roo. You can get rid of it easily, and still gain the initial jump-start benefits. But you can also keep using it and continue to enjoy long-term productivity gains.
I think you'll find the support for ITDs is extremely good, particularly within STS and Eclipse. I don't comment on other IDEs, but given both STS and Eclipse are free I don't think people are really that constrained by Roo's choice to use ITDs. In relation to your controller having no methods, in practical terms there are several ways of dealing with this. You can use the aforementioned "push in refactoring" to move the Roo method directly into the controller and then take ownership of it (ie edit it). Or you can simply write a method in the controller and it will automatically take priority over the ITD and the ITD will have the corresponding method removed. Or you can edit the @Roo annotation in the controller to switch off controller methods you don't want. There's other ways too, but I think those three are a good enough start.
Regarding the name "Roo", we brainstormed about 20 names before SpringOne Europe. We then eliminated those subject to existing trademarks and similar considerations. You'd be surprised how many great names you just can't use due such factors! Anyhow, those names that remained were put to the community to vote and "Roo" was the hands-down winner (as mentioned in my entry above). The name Roo originally came from "Real Object Oriented", but we dropped that given the focus shifted to sustainable productivity when I resumed work on the project. Because I still called the code "Roo" when talking to colleagues, it became the de facto project name. When we saw the names that survived trademark review, we thought it would be nice to at least throw Roo in there – and that's the story of the name! You're also right in that you pronounce it like "Foo".
Grzegorz Borkowski says:
Added on May 29th, 2009 at 2:14 amAlex, thanks for response. Things are getting clearer now. I'm waiting for your post about "push in refactoring". For example I'm curious how do you synchronize the class and aspects: if I have a class with field "foo" – or roo
– and there are getters and setters for it in attached aspect file, and it is used in toString() in other aspect file; and when you change the name of this field in your class, will the aspects be updated automatically? And what about visibility of getter/setter methods in other classes, will code completion and compiler be able to spot them?
And still the relation of Roo to Groovy remains unclear. Hope to hear some comments on it soon.
Ben Alex (blog author) says:
Added on May 29th, 2009 at 8:20 pmGrzegorz, you don't need to do anything special to synchronize the classes and aspects. Thanks to improvements in AJDT you will see all the introduced members if you press CTRL SPACE. The Java editor will also treat the ITD-sourced members as if they were normal members, providing instant visual feedback if there is an error, missing argument etc. So when you're writing the PublicRsvpController above, it's actually extremely easy and you don't have to guess, "um, what was the dynamic finder method name again?" or, "is the persist method static and does it need any arguments?". All of this "just works" – give it a try! Also, if you rename a class or add/rename/remove a field, you'll see that the Roo running in the background automatically detects you've done this and immediately creates/updates/deletes affected files accordingly. I demonstrated this during the keynote with the pre-1.0.0.A1 release. In the keynote I moved one field to higher in the entity (using the normal Java editor in Eclipse), and showed that Roo automatically trickled this change through the toString(), getters/setters and even JSP content.
xeno says:
Added on June 2nd, 2009 at 12:51 pmBen,
Can you give us an example with Spring JDBC, any of MySQL || PostgreSQL || Oracle, and that magic "push-in". Yes, I know that will create an POSP (plain ol' spring project), which won't be as cool as AJDT & ITD but that's OK. Thanks a lot.
Riven Hong says:
Added on June 2nd, 2009 at 10:21 pmGreat job! I like it more than grails. Still I have four question:
1. Can I use other web framework in Roo, such as Struts2 ?
2. How to separate projects , for example: one project focus on web UI and controllers , another project focus on backend services,such as get information from DB or use RMI to access other Service.
3. How to extend Roo's function by Plug-in?
4. Which dojo version is used currently and can I use Grid dojo dijit in Roo?
Ben Alex (blog author) says:
Added on June 2nd, 2009 at 10:41 pmRiven, answers to your questions:
1. You can use other web frameworks with Roo. You have the normal Spring Framework under Roo, so all the normal Spring Framework features are fully available. I discussed use of alternate web frameworks at http://forum.springsource.org/showpost.php?p=242290&postcount=3
2. You can use the normal Maven 2 multi-project techniques and separate your application tiers. One current limitation is Roo cannot create a web tier for an entity tier in a separate project. I did design the project model abstraction to support multi-project approaches, though, so we'll undoubtedly address this in a future version.
3. I'll talk some more about add-ons in my next Roo blog, but in the meantime I can suggest taking a look in Subversion. Most existing add-ons are quite small and easy to follow. The security add-on, for example, is only 165 lines of Java plus 27 lines of XML.
4. We're using the Dojo version contained within Spring JavaScript 2.0.7.RELEASE.
Andrew Eisenberg says:
Added on June 3rd, 2009 at 11:18 amFor those of you asking about the Push-In refactoring, here's a blog post about how it works:
http://contraptionsforprogramming.blogspot.com/2009/05/push-in-refactoring-for-ajdt.html
I don't think that it made it into the most recent milestone release of STS because of a compatibility issue we were having with m2eclipse (solved now).
Andrew Eisenberg says:
Added on June 3rd, 2009 at 11:19 amThe push in refactoring is currently only available from AJDT in the dev update site:
http://download.eclipse.org/tools/ajdt/34/dev/update
Bruno Unna says:
Added on June 3rd, 2009 at 12:36 pmGreat tool!
I've been following the procedure described in this post with interest, and I must say it is very clear and illustrative. However, its first half is much more detailed and easy to follow than the second one; perhaps I would have appreciated the opposite effect, since the second part is the one which requires more attention from the user.
A little comment on STS (perhaps this is no the right place, if it isn't, pleas let me know): as of now, the "New Roo Simple" template doesn't allow the creation of a Roo project with a base package as short as the one used in the example. The regex demands a three-part package. Besides, the project name doesn't admit dots in it.
At any rate, I believe this is a very promising tool. I'm looking forward to use intensively in the next months.
Regards.
Ben Alex (blog author) says:
Added on June 3rd, 2009 at 5:49 pmAndrew, thanks for creating a blog entry on the push-in refactoring. I look forward to talking a lot about this very cool feature in part 3 of the Introducing Roo series. After all, it proves how easy it is to get rid of Roo out of your projects at any time. I think that's a very compelling benefit of Roo.
Bruno, thanks for your comments. I have logged an issue at https://issuetracker.springsource.com/browse/STS-121 regarding the 3-part package name in STS. Would you also please let me know which specific section(s) of the blog weren't detailed enough?
Paul Bernet says:
Added on June 4th, 2009 at 9:53 amI tried the example above with EclipseLink:
>install jpa -provider ECLIPSELINK -database HYPERSONIC_PERSISTENT
While running the tests I got this Exception:
Caused by: Exception [EclipseLink-7211] (Eclipse Persistence Services – 1.0.1 (B
uild 20080905)): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Mapping metadata cannot be applied to fields or propertie
s that are transient, static or abstract. The attribute [public transient javax.
persistence.EntityManager com.wedding.domain.Rsvp.ajc$interField$com_wedding_dom
ain$entityManager] from class [class com.wedding.domain.Rsvp] is in violation of
this restriction. Ensure there are no mapping annotations defined on this attri
bute and ensure this attribute has not be defined as a persistence mapping withi
n an XML file.
Regards.
Ben Alex (blog author) says:
Added on June 4th, 2009 at 5:09 pmPaul, we too noticed this when testing with EclipseLink, which erroneously regards the @PersistenceContext annotation as mapping metadata. This in turn conflicts with the transient access modifier on the EntityManager field. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=277550. We also found an issue in OpenJPA concerning the remove use case. All other OpenJPA operations work, but OpenJPA's usage is more complex due to the instrumentation strategies it uses.
Maodo DIOP says:
Added on June 8th, 2009 at 10:30 amWhat is the equvalent for MySql when writing
install jpa -provider HIBERNATE -database HYPERSONIC_PERSISTENT ?
Or how to install MySql provider
Bruno Unna says:
Added on June 8th, 2009 at 10:57 amMaodo DIOP, I use this:
install jpa -provider HIBERNATE -database MYSQL
Which will, of course, leave a file named "src/main/resources/database.properties". This is editable by hand or, as explained above, using the database set of commands in Roo.
Regards.
Carlos Adolfo Ortiz Q says:
Added on June 8th, 2009 at 3:48 pmWell
I am new to Roo, but I would like to ask. Why is this different from Grails, or it is a Grails environment (I am new to Grails as well)
My question is. Are Roo and Grails following the same principles?
Maodo DIOP says:
Added on June 9th, 2009 at 3:54 amI have use it but an error:
roo> install jpa -provider HIBERNATE -database MYSQL
Command 'install jpa -provider HIBERNATE -database MYSQL' not found (for assista
nce press TAB or type "hint" then hit ENTER)
For informations my Spring ROO version is 1.0.0.M1 [rev 64]
flye12 says:
Added on June 12th, 2009 at 10:42 amDoes Roo has support for JDO upfront, so instead of using JPA implementatioin use JDO?
And where can I access the latest milestone release?
Aries McRae says:
Added on June 18th, 2009 at 2:27 amLOL!!! How appropriate for the wedding
/wedding/src/main/webapp/WEB-INF/jsp/uncaughtException.jsp
ServletException sex = (ServletException) exception;
rootCause = sex;
Ram Kumar says:
Added on June 29th, 2009 at 10:19 pmRoo is way cool.
Just a question though, is it possible to set the primary key using the "add field" function i.e. rather than using the default primary key that is auto generated by roo?
Tejas says:
Added on June 30th, 2009 at 9:59 amHi,
I followed this step-by-step and at mvn test I got following –
[INFO] [surefire:test]
[INFO] Surefire report directory: D:\w20space\wedding\target\surefire-reports
org.apache.maven.surefire.booter.SurefireExecutionException: Bad version number
in .class file; nested exception is java.lang.UnsupportedClassVersionError: Bad
version number in .class file
java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12
4)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.locateTest
Sets(AbstractDirectoryTestSuite.java:87)
at org.apache.maven.surefire.Surefire.createSuiteFromDefinition(Surefire
.java:209)
at org.apache.maven.surefire.Surefire.run(Surefire.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(Su
refireBooter.java:345)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.j
ava:1009)
[INFO] ————————————————————————
[ERROR] BUILD FAILURE
[INFO] ————————————————————————
[INFO] There are test failures.
Andrew Eisenberg says:
Added on June 30th, 2009 at 10:23 am@Tejas,
It looks like you are trying to run your maven with an unsupported JDK. Make sure that you are using Java 5 or later.
Tejas says:
Added on June 30th, 2009 at 4:22 pmHere is the version what MVN uses:
>mvn -v
Apache Maven 2.1.0 (r755702; 2009-03-18 15:10:27-0400)
Java version: 1.5.0_06
Java home: c:\java\jdk\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"
Andrew Eisenberg says:
Added on June 30th, 2009 at 5:57 pmUse Java 6 instead. I think Roo has some Java 6 dependencies.
RobertGloverJr says:
Added on July 4th, 2009 at 10:37 am(Using Ubuntu 9.04 and spring-roo-1.0.0.M2.zip). In roo I type "create project -topLevelPackage com.wedding" and the output I get is:
Created /home/rdg1/rdg/roo/wedding/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/applicationContext.xml
But in your example it indicates the output I should get is that plus the following in addition:
Created SRC_MAIN_WEBAPP/WEB-INF
Created SRC_MAIN_WEBAPP/WEB-INF/wedding-servlet.xml
Created SRC_MAIN_WEBAPP/WEB-INF/web.xml
Created SRC_MAIN_WEBAPP/WEB-INF/jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/index.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml
When I look at the contents of wedding/src/main/webapp/ there is nothing in it. The generated pom.xml added a dependency for javax.servlet, but that's the only thing I see anywhere related to a web application having been generated.
Did something change between roo m1 and roo m2 perhaps?
RobertGloverJr says:
Added on July 5th, 2009 at 8:20 amSuspecting the problem is with M2 only, I just now downloaded M1 (spring-roo-1.0.0.M1.zip), deleted and then recreated the the symbolic link (sudo ln -s /home/rdg1/java/roo1m1/spring-roo-1.0.0.M1/bin/roo.sh /usr/bin/roo) and then tried this command (the one that did not work correctly in m2) : create project -topLevelPackage com.wedding
This time (in m1 as opposed to m2) it worked perfectly. Below shows the correct output. I think it's safe to venture that something broke in the m2 version when running on ubuntu 9.04. Below shows the correct output I got using m1 (instead of m2):
Created /home/rdg1/rdg/roo/wedding/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/applicationContext.xml
Created SRC_MAIN_WEBAPP/WEB-INF
Created SRC_MAIN_WEBAPP/WEB-INF/wedding-servlet.xml
Created SRC_MAIN_WEBAPP/WEB-INF/web.xml
Created SRC_MAIN_WEBAPP/WEB-INF/jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/index.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml
I'll now happily continue with the tutorial (using m1). So far I am very impressed with Roo. It strikes me as a killer app. Not to tread on any toes, but until I tried Roo for myself I was devoting a lot of my spare time to keeping up with Groovy/Grails. I hope it's okay to say this here– I think it's a better use of my time to instead learn Spring 3, Roo and core java better.
Tejas says:
Added on July 10th, 2009 at 2:55 pm@Andrew, Thanks, You were correct – It works with JDK 6 with no issues..
Tejas says:
Added on July 10th, 2009 at 3:27 pmDoes anybody know where to set these variable for selenium-maven-plugin ?
>mvn -e selenium:selenese
Error stacktraces are turned on.
[INFO] Scanning for projects…
[INFO] Searching repository for plugin with prefix: 'selenium'.
[INFO] ————————————————————————
[INFO] Building wedding
[INFO] task-segment: [selenium:selenese]
[INFO] ————————————————————————
[INFO] ————————————————————————
[ERROR] BUILD ERROR
[INFO] ————————————————————————
[INFO] One or more required plugin parameters are invalid/missing for 'selenium:
selenese'
[0] Inside the definition for plugin 'selenium-maven-plugin' specify the followi
ng:
…
VALUE
.
[1] Inside the definition for plugin 'selenium-maven-plugin' specify the followi
ng:
…
VALUE
.
[2] Inside the definition for plugin 'selenium-maven-plugin' specify the followi
ng:
…
VALUE
.
[INFO] ————————————————————————
[INFO] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: Error configuring: org.c
odehaus.mojo:selenium-maven-plugin. Reason: Invalid or missing parameters: [Mojo
parameter [name: 'browser'; alias: 'null'], Mojo parameter [name: 'startURL'; a
lias: 'null'], Mojo parameter [name: 'suite'; alias: 'null']] for mojo: org.code
haus.mojo:selenium-maven-plugin:1.0:selenese
Thanks