Recently I got opportunity to implement some change
requests (CR) in the application built using Spring Roo, when I searched about
it I didn't find complete tutorial, which made me to write below post, hope by
reading this tutorial one will get complete idea of tool along with the
example.
What is Spring Roo?
Spring Roo is a development tool, not a
framework, by reading the name spring many people think it is a framework,
it is one type of code generation tool.
How to Install?
There are three ways via which one can install spring
roo. First one is download spring roo latest release for example
spring-roo-1.3.0.RELEASE and decompress it. Second way is download Spring Tool Suite
(STS) it has support for roo project, no need to download separately. Last way
is install spring roo plugin in eclipse from eclipse market place. In addition
to that we will need Apache Maven for build process.
Step 1: Creating New
Project
After installing a Spring Roo and Maven, we will create a
new directory for our project:
>
mkdir pizza
>
cd pizza
pizza>
Now we will start roo shell by executing /bin/roo.bat
file.
pizza>
roo.bat
____
____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/
|_|\____/\____/ 1.2.1.RELEASE [rev
6eae723]
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.
Enter
a --topLevelPackage like 'com.mycompany.projectname' (no quotes).
When
you've finished completing your --topLevelPackage, press ENTER.
Your
new project will then be created in the current working directory.
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.
roo>
Like help in DOS, here we have hint command. After typing hint you may noticed that this
command guides you in a step-by-step style towards the completion of your first
project. If you type help it will
give you list of supported command. To create new project we will use project
command:
roo>
project --topLevelPackage com.abc.roo.pizzashop
Created
ROOT/pom.xml
Created
SRC_MAIN_RESOURCES
Created
SRC_MAIN_RESOURCES/log4j.properties
Created
SPRING_CONFIG_ROOT
Created
SPRING_CONFIG_ROOT/applicationContext.xml
com.abc.roo.pizzashop
roo>
After issuing project
command as we can see, roo shell created maven style project structure along
with pom.xml. The top level package will become groupId in pom.xml. After that you can use tild(~) to refer to top
level package. The following folder structure now exists in your file system:
As we can see directory structure, it is a typical maven
style spring project, is will create log4j.properties, applicationContext.xml
with default configuration and pom.xml having required dependencies and bare
minimal configuration.
Next step is to add persistence support. Roo support Java Persistence API (JPA) for ORM. ORM will take care of mappings between our persistent domain objects called entities and their corresponding database tables. To add persistence configuration support in your project we can use the jpa setup command. We can always use hint command to show help at the configuration level.
com.abc.roo.pizzashop
roo> hint
Roo
requires the installation of a persistence configuration,
for
example, JPA or MongoDB.
For
JPA, type 'jpa setup' and then hit TAB three times.
We
suggest you type 'H' then TAB to complete "HIBERNATE".
After
the --provider, press TAB twice for database choices.
For
testing purposes, type (or TAB) HYPERSONIC_IN_MEMORY.
If
you press TAB again, you'll see there are no more options.
As
such, you're ready to press ENTER to execute the command.
Once
JPA is installed, type 'hint' and ENTER for the next suggestion.
Similarly,
for MongoDB persistence, type 'mongo setup' and ENTER.
Now we will issue jpa
setup command to add persistence support through hibernate in our project.
com.abc.roo.pizzashop
roo>
com.abc.roo.pizzashop
roo> jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY
Created
SPRING_CONFIG_ROOT/database.properties
Updated
SPRING_CONFIG_ROOT/applicationContext.xml
Created
SRC_MAIN_RESOURCES/META-INF/persistence.xml
Updated
ROOT/pom.xml [added dependencies org.hsqldb:hsqldb:1.8.0.10,
org.hibernate:hibernate-core:3.6.9.Final,
org.hibernate:hibernate-entitymanager:3.6.9.Final,
org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final,
org.hibernate:hibernate-validator:4.2.0.Final,
javax.validation:validation-api:1.0.0.GA, cglib:cglib-nodep:2.2.2,
javax.transaction:jta:1.1,
org.springframework:spring-jdbc:${spring.version},
org.springframework:spring-orm:${spring.version},
commons-pool:commons-pool:1.5.6, commons-dbcp:commons-dbcp:1.3]
com.abc.roo.pizzashop
roo>
As we can see we have added provider as hibernate and
database as hypersonic_in_memory which will avoid extra work for database
server, setup etc. Spring Roo also offer EclipseLink, OpenJPA, and DataNucleus as
a alternative choice for ORM. We can edit the SRC_MAIN_RESOURCES/META-INF/persistence.xml
file to modify your JPA provider's
configuration setting.
Step 2: Adding Entities
and Fields
Now we will create domain objects and their fields. We
can use the entity jpa command to create actual domain object. The –class
is mandatory attribute. We use the --testAutomatically attribute which will creates integration
tests for a domain object.
com.abc.roo.pizzashop
roo> hint
You
can create entities either via Roo or your IDE.
Using
the Roo shell is fast and easy, especially thanks to the TAB completion.
Start
by typing 'ent' and then hitting TAB twice.
Enter
the --class in the form '~.domain.MyEntityClassName'
In
Roo, '~' means the --topLevelPackage you specified via 'create project'.
After
specify a --class 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.
After creating an entity, use 'hint' for
the next suggestion.
com.abc.roo.pizzashop
roo>
com.abc.roo.pizzashop
roo> entity jpa --class ~.domain.Topping --testAutomatically
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping.java
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingDataOnDemand.java
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingIntegrationTest.java
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping_Roo_Configurable.aj
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping_Roo_ToString.aj
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping_Roo_Jpa_Entity.aj
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping_Roo_Jpa_ActiveRecord.aj
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingDataOnDemand_Roo_Configurable.aj
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingDataOnDemand_Roo_DataOnDemand.aj
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingIntegrationTest_Roo_Configurable.aj
Created
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingIntegrationTest_Roo_IntegrationTest.aj
As we can see along with java it will create AspectJ
source, also it will create appropriate folder structure for our project.
Next step we need to add the 'name' field to our Topping class. This can be done by using the field command as follows:
~.domain.Topping
roo> hint
You
can add fields to your entities using either Roo or your IDE.
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.
After
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.
If
creating multiple fields, use the UP arrow to access command history.
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
Updated
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping.java
Updated
SRC_TEST_JAVA/com/abc/roo/pizzashop/domain/ToppingDataOnDemand_Roo_DataOnDemand.aj
Created
SRC_MAIN_JAVA/com/abc/roo/pizzashop/domain/Topping_Roo_JavaBean.aj
After every successful command we issue hint command to
display information about next available steps. Along with field we have added
–notNull and –size
attribute this will result in annotation based validation.
Similarly we will
Base and Pizza entity and we will add fields in it using below commands.
entity jpa --class
~.domain.Base --testAutomatically
field string --fieldName
name --notNull --sizeMin 2
entity jpa --class
~.domain.Pizza --testAutomatically
field string --fieldName
name --notNull --sizeMin 2
field number --fieldName
price --type java.lang.Float
Now we need to add mapping of Pizza with Base and Topping entity. Pizza and Topping class have m:m relationship. To create relationship Roo
provides field set command.
~.domain.Pizza
roo> field set --fieldName toppings --type ~.domain.Topping
This will automatically annotate bean properties with
appropriate annotation, similarly we can define the m:1 relationship between
the Pizza
and Base
domain class by using the field reference command:
~.domain.Pizza
roo> field reference --fieldName base --type ~.domain.Base
Now we will create the PizzaOrder domain
object and add required fields using below commands:
entity jpa --class
~.domain.PizzaOrder --testAutomatically
field string --fieldName
name --notNull --sizeMin 2
field string --fieldName
address --sizeMax 30
field number --fieldName
total --type java.lang.Float
field date --fieldName
deliveryDate --type java.util.Date
field set --fieldName pizzas
--type ~.domain.Pizza
This will complete our creation of domain model.
Step 3: Performing Integration
Test
To perform integration test on our domain entities will
use perform tests command, note Roo
will by default create test, if not we can use test integration command.
~.domain.PizzaOrder
roo> perform tests
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Tests
run: 36, Failures: 0, Errors: 0, Skipped: 0
[INFO]
----------------------------------------------------------------------
[INFO]
BUILD SUCCESS
[INFO]
----------------------------------------------------------------------
[INFO]
Total time: 3.860s
[INFO]
Finished at: Tue Feb 12 18:01:45 EST 2015
[INFO]
Final Memory: 6M/81M
[INFO]
----------------------------------------------------------------------
As you can see Roo has issued a Maven command internally to
execute the integration tests.
Step 4: Import In Our
IDE
Now it’s time to import our project in favorite IDE, we
will use eclipse.
By default Roo projects does not contain any IDE-specific workspace configuration artifacts. If our eclipse has Maven plugin no need to issue peform eclipse command, we can directly import as maven project, maven will do rest of things.
By default Roo projects does not contain any IDE-specific workspace configuration artifacts. If our eclipse has Maven plugin no need to issue peform eclipse command, we can directly import as maven project, maven will do rest of things.
~.domain.PizzaOrder
roo> perform eclipse
[INFO]
Adding support for WTP version 2.0.
[INFO]
Using Eclipse Workspace: null
[INFO]
Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO]
Wrote settings to /Users/nishant/projects/roo-test/pizzashop/.settings/org.eclipse.jdt.core.prefs
[INFO]
Wrote Eclipse project for "pizzashop" to /Users/nishant /projects/roo-test/pizzashop.
[INFO]
n.PizzaOrder roo>
Javadoc for some artifacts is not
available.
Please run the same goal with the
-DdownloadJavadocs=true parameter in order to check remote repositories for javadoc.
List of artifacts without a javadoc
archive:
org.springframework.roo:org.springframework.roo.annotations:1.2.1.RELEASE
[INFO]
----------------------------------------------------------------------
[INFO]
BUILD SUCCESS
[INFO]
----------------------------------------------------------------------
[INFO]
Total time: 1.685s
[INFO]
Finished at: Tue Feb 12 18:04:20 EST 2015
[INFO]
Final Memory: 7M/81M
[INFO]
----------------------------------------------------------------------
Step 5: Creating A Web Layer
Next step we need to add to web tier for the Pizza
application. This is achieved by the web mvc setup commands. Then to genrate controllers and all relevant web related
artifacts we will issue web mvc setup
command followed by the web mvc all
command:
~.domain.PizzaOrder
roo> web mvc setup
~.domain.PizzaOrder
roo> web mvc all --package ~.web
This command will scan the our project for any domain
entities and it will add Spring MVC controller for each entity found. The --package
attribute is needed to specify in which package the controllers should be
installed. This will also add required dependencies. All newly added web
artifacts which can be found under the src/main/webapp
folder. This folder contains all css, js, jsp and tiles related configurations.
Step 6: Loading App In
App Server
To deploy our application in a web container we can use mvn tomcat:run target or in STS select
Run as—run on server.
If deployment is successful check the server console our
application will be available at http://localhost:8080/pizzashop
Step 7: Adding Security
to Our Application
To provide authentication and authorization support we with
the help of Spring Security addon we will issue security setup command:
~.web
roo> security setup
Created
SPRING_CONFIG_ROOT/applicationContext-security.xml
Created
SRC_MAIN_WEBAPP/WEB-INF/views/login.jspx
Updated
SRC_MAIN_WEBAPP/WEB-INF/views/views.xml
Updated
ROOT/pom.xml [added property 'spring-security.version' = '3.1.0.RELEASE'; added
dependencies
org.springframework.security:spring-security-core:${spring-security.version},
org.springframework.security:spring-security-config:${spring-security.version},
org.springframework.security:spring-security-web:${spring-security.version},
org.springframework.security:spring-security-taglibs:${spring-security.version}]
Updated
SRC_MAIN_WEBAPP/WEB-INF/web.xml
Updated
SRC_MAIN_WEBAPP/WEB-INF/spring/webmvc-config.xml
Open applicationContext-security.xml file in the src/main/resources/META-INF/spring folder and and namespaces as shown below.
<!--
HTTP security configurations -->
<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"/>
<!-- Configure these elements to secure
URIs in your application -->
<intercept-url pattern="/pizzas/**"
access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/toppings/**"
access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/bases/**"
access="hasRole('ROLE_ADMIN')"/>
<intercept-url
pattern="/resources/**" access="permitAll" />
<intercept-url
pattern="/static/**" access="permitAll" />
<intercept-url pattern="/**"
access="permitAll" />
</http>
Next we can can use the Spring Security JSP tag library
to restrict access to the menu items in the menu.jspx file:
<div
xmlns:jsp="..." xmlns:sec="http://www.springframework.org/security/tags"
id="menu" version="2.0">
<jsp:directive.page
contentType="text/html;charset=UTF-8"/>
<jsp:output
omit-xml-declaration="yes"/>
<menu:menu id="_menu"
z="nZaf43BjUg1iM0v70HJVEsXDopc=">
<sec:authorize
ifAllGranted="ROLE_ADMIN">
<menu:category
id="c_topping" z="Xm13w68rCIyzL6WIzqBtcpfiNQU=">
<menu:item
id="i_topping_new" .../>
<menu:item
id="i_topping_list" .../>
</menu:category>
<menu:category
id="c_base" z="yTpmmNMm/hWoy3yf+aPcdUX2At8=">
<menu:item
id="i_base_new" .../>
<menu:item
id="i_base_list" .../>
</menu:category>
<menu:category
id="c_pizza" z="mXqKC1ELexS039/pkkCrZVcSry0=">
<menu:item
id="i_pizza_new" .../>
<menu:item
id="i_pizza_list" .../>
</menu:category>
</sec:authorize>
<menu:category
id="c_pizzaorder" z="gBYiBODEJrzQe3q+el5ktXISc4U=">
<menu:item
id="i_pizzaorder_new" .../>
<menu:item
id="i_pizzaorder_list" .../>
</menu:category>
</menu:menu>
</div>
Step 8: Take Backup And
Create Deployable
backup command
is useful to take back of our workspace.
~.web
roo> backup
Created
ROOT/pizzashop_2015-02-12_18:10:19.zip
Backup
completed in 35 ms
~.web
roo>
Finally, to create web archive war file we will use maven
perform package command:
~.web
roo> perform package
[INFO]
Scanning for projects...
[INFO]
----------------------------------------------------------------------
[INFO]
Building pizzashop
[INFO] task-segment: [package]
[INFO]
----------------------------------------------------------------------
[INFO]
[war:war {execution: default-war}]
[INFO]
Exploding webapp...
[INFO]
Assembling webapp pizzashop in /Users/nishant/projects/roo-test/pizzashop/target/pizzashop-0.1.0-SNAPSHOT
[INFO]
Copy webapp webResources to /Users/nishant/projects/roo-test/pizzashop/target/pizzashop-0.1.0-SNAPSHOT
[INFO]
Generating war /Users/nishant/projects/roo-test/pizza/target/pizzashop-0.1.0-SNAPSHOT.war
[INFO]
Building war: /Users/nishant/projects/roo-test/pizza/target/pizzashop-0.1.0-SNAPSHOT.war
[INFO]
----------------------------------------------------------------------
[INFO]
BUILD SUCCESS
[INFO]
----------------------------------------------------------------------
[INFO]
Total time: 5.881s
[INFO]
Finished at: Tue Feb 12 18:15:54 EST 2015
[INFO]
Final Memory: 8M/81M
[INFO]
----------------------------------------------------------------------
~.web
roo>
This will provide war file under target directory.
Download a copy of source code of the tutorial https://github.com/nishantraut/SpringRoo
Finally we are done. If you have any queries feel free to
leave a comment. Happy Coding...Have fun.