Professional Documents
Culture Documents
Tutorial: Spring Roo and JPA: Prof. Dr. Joachim Hering Ulm University of Applied Sciences Germany
Tutorial: Spring Roo and JPA: Prof. Dr. Joachim Hering Ulm University of Applied Sciences Germany
Tutorial: Spring Roo and JPA: Prof. Dr. Joachim Hering Ulm University of Applied Sciences Germany
Page 1 of 16
In this tutorial you will get some hands-on experience with the Spring Tool Suite (STS) and
Spring Roo to rapidly develop a database-based (Web-)Application by following a step-by-
step guide.
Note that in this tutorial a Linux-based operating system is assumed. However, on other
platforms (e.g., Windows), this tutorial should work as well - different file paths may have
to be used, though (e.g., "C:\" instead of "home").
Pre-Requisite: Java SE
Please ensure that the JDK 1.7 has been installed on your machine. The current version of
Spring Roo requires JDK 1.6 or JDK 1.7 to be installed.
Page 2 of 16
Domain Object Model
In this tutorial, you will develop the Web Application "MyJobOffers" allowing to maintain
and view job offers. The corresponding Domain Object Model is shown in the following
figure.
Close the "Welcome" page, "Dashboard" page and "Tool tips", if displayed.
Within STS, we will mainly work with the Roo Shell. If it is not shown, you may open it via
"Window->Show View->Other...", expand the folder "Spring", and select "Roo Shell". After
clicking "OK", you should see the Roo Shell in a tab at the bottom of STS. If you see the
Roo Shell at a different place, you may drag the corresponding tab to the bottom of STS.
Page 3 of 16
A new Roo project may now be created by clicking on the "Create new Roo Project" button
( ) on the right upper side of the Roo Shell.
Observe in the "Package Explorer" of STS, that a new project "MyJobOffers" has been
created.
In the following, we will mainly be using the Roo Shell to enter Roo commands.
A few notes about the Roo Shell in STS (please feel free to try them out):
• Entering "help" provides you with some further information on the Roo Shell
• Entering "help RooCommand" will provide you with information on a specific Roo
command. E. g., "help jpa setup"
• Entering "hint" will provide you with a generic step-by-step guidance
NOTE: If time left after the tutorial, you may experiment with that, in this tutorial,
however, you will already be provided with a specific step-by-step guidance.
• While entering Roo commands, you may at any time press CTRL+SPACE. Roo will
then provide you with a list of possible Roo commands/options.
E.g., pressing CTRL+SPACE in the empty Roo Shell will present you with a list of
all possible Roo commands to choose from.
Page 4 of 16
Setting up the Java Persistence API (JPA) in Roo
In Roo, JPA is set up by entering the following Roo command:
roo1> jpa setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE
Note that for this tutorial, we are using the HYPERSONIC IN MEMORY database which
relieves us from the need to have a separate database engine installed.
In real world (Web-)Applications, another database engine should be used. The "jpa setup"
command does of course allow to set up jpa for other database engines like for instance
Oracle, MySQL, MSSQL, ...
Since JPA is a standard API, the "jpa setup" command may be re-run at any time with
different options (e.g., for the database or for the JPA provider) without affecting any of the
existing Java code.
After entering this command, Roo automatically modifies your project such that JPA may
be used in the following.
Please feel free at any time of the tutorial to explore the current structure of your project
via the "Package Explorer".
1 Please do not enter "roo>". This is only to highlight, that a command is to be entered into the Roo Shell.
Page 5 of 16
Also note that the following fields (shown in the Domain Object Model) will be created later,
i.e., when creating relationships between those Domain Objects:
• city
• cities
• companies
• jobOffers
• company
• jobCategories
City:
roo> entity jpa --class ~.domain.City --testAutomatically
roo> field string --fieldName name --sizeMax 20 --notNull
In the "Package Explorer", have a look at "City", the just generated JPA Entity.
This class looks quite simple, it only contains the field we specified (i.e., "name").
However, note that "City" has a number of Roo annotations (e.g., @RooJavaBean,
@RooToString, @RooJpaActiveRecord). Those annotations indicate that Roo has
automatically generated Java code for us to help us speed up development time.
Spring Roo puts all generated code in separate AspectJ (*.aj) files that will be
automatically merged into the corresponding java-Files at build time - all transparent to the
developer.
However, those AspectJ files are very similar to Java code and may be viewed by the
developer. This way, developers can concentrate on the key details (e.g., the Domain
Object fields), while all the boilerplate code is put in separate files.
We will now have a brief look at the AspectJ files generated for our Domain Object "City".
By default, AspectJ files are not visible. Hence, we first have to make them visible as
follows:
From the Package Explorer menu ( ) on the right upper side, choose "Filters". Deselect
the option "Hide generated Spring Roo ITDs" and click "OK".
By convention, all AspectJ files belonging to "City" are named "City_*.aj". Have a look at
those files and the functionality they add to our "City" class.
Of particular interest is "City_Roo_Jpa_ActiveRecord.aj", which enables "City" to not only
contain its data but also to load and persist its data from/to the underlying relational
database.
Now create the other Domain Objects accordingly (maybe you can already do that
yourself):
Page 6 of 16
Country:
roo> entity jpa --class ~.domain.Country --testAutomatically
roo> field string --fieldName name --sizeMax 20 --notNull
Company:
roo> entity jpa --class ~.domain.Company --testAutomatically
roo> field string --fieldName name --sizeMax 20 --notNull
roo> field string --fieldName streetName --sizeMax 20 --notNull
roo> field number --fieldName streetNo --type java.lang.Integer --min 0 --max 9999 --notNull
roo> field string --fieldName postCode --sizeMax 10 --notNull
JobCategory:
roo> entity jpa --class ~.domain.JobCategory --testAutomatically
roo> field string --fieldName name --sizeMax 20 --notNull
JobOffer:
roo> entity jpa --class ~.domain.JobOffer --testAutomatically
roo> field string --fieldName subject --sizeMax 20 --notNull
roo> field string --fieldName contactEmail --sizeMax 20 --notNull
roo> field string --fieldName description --sizeMax 200 --notNull
Page 7 of 16
Creating the relationships between Domain Objects
Now that the Domain objects are created, we use Spring Roo to define their relationships.
We will start defining the one-to-many relationships and finally the many-to-many
relationship between "JobOffer" and "JobCategory".
We will generally create bidirectional relationships where navigation is possible from both
sides (e.g., from companies to their city and from cities to companies). Hence, creating a
relationship between two Domain Objects is a two-step-process where each direction of
the relationship is created separately.
Note: Again, as soon as you get the idea, please try to enter the commands yourself
(without looking at the solution) based on the Domain Object Model shown above.
Remember: Using CTRL-SPACE will help you entering the Roo commands.
City-Company:
Each city may have a number of company headquarters (one-to-many).
roo> focus --class ~.domain.City
roo> field set --fieldName companies --type ~.domain.Company --cardinality
ONE_TO_MANY --mappedBy city
Note that Spring Roo has added the following field to the "City" class:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "city")
private Set<Company> companies = new HashSet<Company>();
Via the "@OneToMany" annotation, JPA knows about the relationship between "City" and
"Company" and will be able to generate the correct SQL when queries are issued. This will
be done transparent to the developer - the developer only needs to know about the
Domain Object Model.
The "mappedBy" option refers to the name of the field in "Company" that represents the
related "City". This instructs JPA to manage the relatioship at the "many" end 2, which we
will define in the following:
2 One-to-many relationships are typically managed at the "many" end. This makes sense, since the foreign
key (here: Company.city) lives in the "many" side.
Page 8 of 16
Every company has its headquarter in a particular city (many-to-one).
Note that Spring Roo has added the following field to the "Company" class:
@NotNull
@ManyToOne
private City city;
This is the field that is referred to by the "mappedBy" option when the one-to-many
relationship between "City" and "Company" was defined.
The bidirectional one-to-many relationship between "City" and "Company" is now complete
where the following rules have been established:
• Cities contain sets of Companies in a collection named companies
• Companies reference their City in the reference variable "city"
• Removing/saving a City will also remove/save its assigned Companies (cascading)
• If JPA is used to load a City, JPA will automatically fetch assigned Companies when
the "getCompanies" method is called (defined in City_Roo_JavaBean.aj)
Page 9 of 16
Country-City:
Each country has a number of cities (one-to-many).
Company-JobOffer:
Each company may have a number of job offers (one-to-many).
Page 10 of 16
JobOffer-JobCategory:
Note that option 1 allows us to specify fields for the intersecting object (i.e., fields that
belong to the relationship between "JobOffer" and "JobCategory" like for instance
"categoryAssignedByUser".
However, in this tutorial, we will be using the simpler option 2:
Each job offer may belong to one or more job categories (many-to-many).
Note that the "mappedBy" option defines the name of the set within the "JobOffer" and
indicates that "JobCategory" is not in charge of persisting relationships to "JobOffers".
In a bidirectional many-to-many relationship, we have to define one side as the primary,
i.e., active side, and the other side as the inverse side (via the mappedBy option). When
using JPA, we need to know, which is the active side, since only updates on this side will
actually trigger JPA persistence for relationships.
There can only be one active side of the many-to-many relationship to be watched by JPA,
since otherwise the same rows may be inserted twice in the underlying relational
database.
For most bidirectional one-to-many relationships, the appropriate active side is the "many"
side, as the foreign key lives in the child (i.e., the "many" side).
For many-to-many relationships, the choice is arbitrary and may be decided on a case-by-
case basis. In our case it seems more natural for "JobOffer" to be the active side.
Page 11 of 16
The underlying relational data model
We have now finished creating our Domain Object Model in Spring Roo.
Before testing some of the persistence functionality that Spring Roo has generated for us,
let us take a brief look at the automatically generated corresponding underlying relational
data model.
Page 12 of 16
Note the following about the relational data model:
• Entities are related to each other traditionally using primary and foreign keys.
• The many-to-many relationship between "JobOffer" and "JobCategory" results in
three tables where an intermediate table (job_offer_job_categories) is used to
implement the many-to-many relationship between job offers and job categories.
Now you may specify your own simple JUnit test by adding the following test method to
"CityIntegrationTest.java".
@Test
public void testWriteReadCity() {
CityDataOnDemand cityDod = new CityDataOnDemand();
City city = cityDod.getNewTransientCity(0);
city.persist();
city.flush();
city.clear();
Re-run the tests with the now newly added test method.
Page 13 of 16
Using the Roo-generated Business Objects in your own code
The Roo-generated Business Objects are of course ready to be used in your own code as
well. However, before you can do that, you will need to bootstrap Spring's container to be
able to have access to all functionality offered.
For a stand-alone Java application, that needs to be done manually in the main() method.
Suppose, we want to create a new City ("Ulm") and persist it. The following Class
"MyOwnCode", which you may create in the package " com.springroo.myjoboffers"
shows, how that can be done:
package com.springroo.myjoboffers;
import org.springframework.context.support.GenericXmlApplicationContext;
import com.springroo.myjoboffers.domain.Country;
After having created this class, you may run it by right-clicking on "MyOwnCode.java" and
selecting "Run As->Java Application".
After that you may also experiment with the other Domain Objects available (e.g., City,
Company, ...).
Page 14 of 16
Create a CRUD-based Spring MVC Web Application based on
our Domain Object Model
You may finally turn your Spring project into a CRUD-based Spring MVC Web Application
by entering the following Roo commands:
roo> web mvc setup
roo> web mvc all --package com.springroo.myjoboffers.web
Please wait until STS has finished building the newly generated code.
Run the Web Application by right-clicking on the "MyJobOffers" project folder in the
"Package Explorer" and selecting "Run As-> Run on Server" and clicking on Finish.
You may now use that Web Application to maintain your Job Offers.
Please note that in our set-up, the persisted data will be re-created each time you run your
Spring-based (Web-)Application. Hence, the just created city "Ulm" will not be listed via the
Web-Application.
This will sequentially execute all Roo commands contained in the file specified. This way,
you may easily re-create the project you have just been working on.
You may try this out by copying log.roo to your home directory, deleting your MyJobOffers
project and trying to re-create your project from scratch using the re-play feature.
Note: All manual additions (i.e., not via Roo commands) like for instance the manual
addition of JUnit tests will get lost - so it may be useful to make a copy of your project
first...
Page 15 of 16
If there is some time left
In case there is still some time left, you may do the following:
• Add further tests
• Add finders and expose them to the web interface (see presentation)
• Create your own Spring Roo project in the Spring Tool Suite
References
K. Rimple et al., „Spring Roo in Action“, Manning Publications, 2012
Page 16 of 16