Practice 1. Reverse engineering an existing database

In this practice you will learn how to reverse engineer an existing database using Spring Roo. Roughly, the idea is use Spring Roo to generate the persistence layer (i.e., entity classes, configuration files, etc.) enabling a transparent access to the database. Additionally, we will use Spring Roo to generate the code of a minimal web application providing operations for listing, updating, creating and removing entries in the database. Some concepts and figures used in this practice are based on material presented in the book “Spring Roo in action” by Ken Rimple and Srini Penchikala, Ed. Manning.

Software tools

• JDK 1.7 • Spring Tools Suite • PostgreSQL

Setting up the database First of all, we will create a local copy of the working database. To that end, you will load the database from a dump file. Using your local PostgreSQL instance and the provided file, you will create the database schema and populate the tables with data.

1. Download the dump file from https://courses.cs.ut.ee/2013/esi/uploads/Main/world.zip. The following class diagram depicts the logical design of the database. Note that City and Country are not related in the beginning, we will address that problem later on.

country

code: character name: text continent: text city region: text surfacearea: real countrylanguage id: integer indepyear: smallint 1…* 1…* name: text population: integer language: text district: text lifeexpectancy: real isofficial: boolean population: integer gnp: numeric percentage: real gnpold: numeric localname: text govermentform: text headofstate: text capital: integer code2: character Figure 1. Logical design of Database

2. Start your PostgreSQL server and open a SQL shell (psql). The following figures give you a hint on how to start psql.

Figure 2. psql shell in Mac OS X and Windows XP

3. Follow the steps below for creating the database and loading the data from the dump file (Note: the commands shall be executed in psql shell). a. Create the database:

create database databaseName;

b. Select your working database

\c databaseName;

c. Load the sample database from the dump file

\i FileDirectory/world.sql;

Reverse engineering Reverse engineering is a common practice and there are several motivations for its use. For instance, for system maintenance, system reengineering, system integration, system migration, etc. In our case, Spring Roo will automatically generate the persistence layer of our application, using the JPA 2.0 framework.

1. Start Spring Tool Suite (STS).

2. Create and set up a Spring Roo Project. i. From the menu bar “File” or by right clicking on the “Project explorer” tab, select “New > Other > Spring > Spring Roo Project” ii. Fill in the text fields for Project name and Top level package name in the dialog box. Click the button “Next” and the “Finish” in the following dialog boxes.

3. Open the “Roo shell” tab. Usually, it is located at the bottom of STS. If Spring Roo shell is not shown in your application, then go to the menu “Window > Show view > Other” and select “Roo shell” under the folder “Spring”.

Figure 3. Show view > Roo shell

Hereinafter, all the commands presented shall be executed in Roo shell.

4. Configure the database connection for your application

jpa setup --database POSTGRES --provider -- databaseName databaseName --hostName hostname --userName username --password pass

where

--database Specifies the database vendor to configure. Spring Roo supports a large number of vendors, including DB2, DERBY, ORACLE and MYSQL.

2 --provider Specifies the JPA provider (persistence middleware vendor), e.g. HIBERNATE, ECLIPSELINK and OPENJPA.

--hostname Parameters required for establishing the connection to the --userName database server. --password

5. Test your database connection. a. To this end, we will execute the command database introspect to query the database schema.

database introspect --schema DatabaseSchema

b. If something goes wrong with the previous command, it is very likely that you need to install a jdbc driver for PostgreSQL. If this is your case, execute the following command:

addon search postgresql

A list of add-ons will be displayed in the shell:

01 Y Y 9.1.0.901-1_0001 Postgres #jdbcdriver driverclass:org.postgresql.Driver. This bundle wraps the standard Maven artifact:... 02 Y Y 9.1.0.901_0001 Postgres #jdbcdriver driverclass:org.postgresql.Driver. This bundle wraps the standard Maven artifact:...

03 …..

Locate the line containing the driver jdbcdriver driverclass:org.postgresql.Driver, then execute the command:

addon install id XY

where XY corresponds to the numbers in the first column in the list of add-ons.

To double check if the driver has been installed, execute the command database introspect once more

database introspect --schema DatabaseSchema

When things go wrong:

Sometimes there are some issues with the command and it does not display any result, instead addon search it shows a message “No add-ons known. Are you online? Try the 'download status' command”. If this is the case, then execute the following commands for the installation of the jdbc driver: - obr url add --url http://spring-roo-repository.springsource.org/repository.xml - osgi obr deploy --bundleSymbolicName org.springframework.roo.wrapping.postgresql-jdbc3

6. To reverse engineer the database use the following command

database reverse engineer --schema DatabaseSchema --package

3 ~.domain

where

--schema Specifies the name of the database schema you will reverse engineer

--package Specifies the package that will contain the set of java classes implementing the persistence layer, and that will be generated by Spring Roo

--includeTables Specifies the subset of tables to be reverse engineered. If this "table1 table2 …" parameter is omitted Spring Roo will reverse engineer all the tables.

--excludeTables This is a symmetric operation to the previous one. "table1 table2 …"

In this lab session, we are going to include all the tables. Therefore, we can omit both --includeTables and --excludeTables.

Up to now we have considered only the steps regarding to the persistence layer and, in fact, we have already completed the basic configurations. In the following steps we will generate the controllers and simple views (user interfaces) for our application.

7. Configure the application with a web presentation layer

web mvc setup

8. Generate the controllers for all the entities created

web mvc all --package ~.web

The previous command implements the controllers and view artifacts for all the data access operations (i.e., create, show, list, update and delete), and for all the entities in the persistence layer. However, you can also add controllers and view artifacts for one entity at a time using the following command

web mvc scaffold --class ~.web.ClassController --backingType

~.domain.Class --disallowedOperations operation1, operation2

where

--backingType Defines the name of the backing type for which the controllers will be generated

--class Specifies the name of the new controller for the entity given in

4 --backingType.

--disallowedOperations Specifies the set of operations that will not be supported by the controller code. You can disable the operations delete, update and create.

9. Run your web application. a. Drag and drop your project into the VMware vFabric tc Server in the tab Servers and start the server. b. Open an external browser (e.g., Google Chrome, Safari or any other) and go to the following URL: htt://localhost:8080/nameOfYourProject c. Look at the generated views and test the different functionalities.

10. In the browser, open the form for creating a new Country. Some of the fields are set as not null, for instance, code, name and continent. Therefore, if one of such fields is left empty when filling in the form, then a warning message appears notifying that it is an invalid input. Nevertheless, the field continent is a regular string and one can put any string value different from Asia, Europe, North America, Africa, Oceania, Antarctica or South America. Therefore, we will add a validator to this text field, such that only the listed words are allowed. a. Focus on the class Country (in Roo shell, execute the command focus --class ~.domain.Country) and add a validation to the String field continent executing the following command:

field string --fieldName continent --notNull --regexp

^(Asia|Europe|North\sAmerica|Africa|Oceania|Antarctica|South\sAmerica)$

If you are not familiarized with regular expressions, the following link can be useful: http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/. The command field has different options besides string and, depending on the type, there are different restrictions that you can set. For instance, you can specify the minimum and maximum possible values for an integer, etc. Deploy your application once more and try to introduce invalid values for the field continent when inserting new Country (if the definition of the validator was correct then you will see a warning message).

A first look at JPA inter-object references In your browser, select “Create new Country” from the side menu bar. Note that when you add a new country to the database, you will need to enter the id of the capital city. In the application as-is the user might enter wrong values. If you look at the logical design of the database depicted in Figure 1, we could actually relate the table City and Country (as shown in the logical design in Figure 3). In order to avoid this kind of mistakes, JPA provides inter- object references. In the following, you will learn how to setup JPA references.

country

code: character name: text continent: text region: text city surfacearea: real countrylanguage indepyear: smallint id: integer 1 1 1…* 1…* population: integer language: text name: text lifeexpectancy: real isofficial: boolean district: text gnp: numeric percentage: real population: integer gnpold: numeric localname: text govermentform: text headofstate: text capital: integer code2: character Figure 4. Logical design of database 2

1. Ensure that you are working with the class “Country”. To this end, use the following command:

5

focus --class ~.domain.Country

2. To setup the JPA reference, use the following command:

field reference --fieldName capital --type ~.domain.City --

cardinality ONE_TO_ONE

where

--fieldName Specifies the field in the working class that refers to an object of the class specified by the parameter --type

--type It defines the Java type of the field

--cardinality It is used to set the type of JPA relationship between the involved entities

Therefore, the command above specifies that the value in “Country.capital” refers to an instance of the class “City”. Roughly, JPA will emulate inter-object reference by means of foreign keys.

Deploy your application once again and observe how your form for inserting new Country has been automatically modified.

Structure of your Roo project 1. Structure a. src/main/java contains Java source code and, generally, starts in the specified top-level package name (parameter set when creating the project).

b. src/main/resources holds all the data related to the application-level configuration, such as Spring configuration files, database properties and persistence configuration.

c. src/main/webapp. If your project is configured with Spring MVC, then it contains the web application code. It holds Spring MVC configuration files, views in JSPX format, style sheets, JavaScript files, among other files.

d. src/test/(java or resources). The folder src/test/java contains all the Java tests source code. Whereas, src/test/resources holds any test-specific Spring configuration file, test property files or anything else needed during testing to support the test classes.

2. Dig into the generated classes a. For instance, src/main/java/your_source_folder/domain contains the entity classes corresponding to the tables in the used database schema. The files nameOfTable_Roo_Jpa_Entity.aj and nameOfTable _Roo_DbManaged.aj have the setters and getters for the fields of the entity, which correspond to the columns in the table. Finally, the file nameOfTable_Roo_Jpa_ActiveRecord.aj contains all JPA methods to find, persist, update, list, and remove entity instances. b. src/main/java/your_source_folder/web contains the controllers needed for the views of the entities. c. In src/main/resources you can find, among other files managed by Roo framework, the file

6 databases.properties that holds the data for the database connection.

If the files *.aj are not visible, a. In the tab Project Explorer select the “View menu/Customize View” (triangle at the upper right corner of the tab)

b. Uncheck the option “Hide generated Spring Roo ITDs”

3. Look at the components related to the web layer of your application:

§ src/main/webapp. The root directory of the web application. Any home page named index.jsp will be served from here by default as the home page of the application. § WEB-INF. The root configuration directory of the web application. As with all web applications, this directory is not visible for browsing. The web.xml web application descriptor file, generated by Roo, lives here and manages the Spring Web application context. § classes. Contains all compiled Java class files, with the AspectJ ITDs woven into them. § i18n. Contains localized property files for the application framework and user- defined form elements. § layouts. Contains the Apache Tiles layouts. § spring. Contains the Spring Web MVC configuration files. § tags. Contains Roo’s generated JSPX tags, which aid in building menus, scaffolding‚ and configuring form fields and display elements. § views. Contains all application view files and Apache Tiles view definitions. § images. Contains all predefined Roo image files such as icons for country flags, add, update, delete, and list buttons, and so on. § styles. Contains all CSS style files.

7 An important element in our user interface is default.jspx. It defines the content that will be showed to the user depending on the selected option. Open the file default.jspx that is located in WEB-INF/layouts. default.jspx file describes the following layout:

In default.jspx, tiles define the content that will be placed in the div elements, and the actual content is in the files referenced in layouts.xml. Note that the elements header, menu and footer are set by default. Thus, the only element that changes is body, and the different contents are defined in WEB-INF/views.

Two themes are automatically generated for your web application, standard and alt. The theme helps you to define different elements, such as layout, colors and fonts. The option for changing the theme is in the footer of your webpage. The only difference between the predefined themes is the position of the menu in the screen. Every time a page is rendered, the name of the used theme is passed in a cookie to Spring, and the loaded CSS corresponds to the file pointed out in WEB-INF/classes/theme.properties.

• As part of the practice, modify the CSS style file alt.css, e.g. you can change the colors of the background and menu.

Recommended links o http://www.springsource.org/spring-roo o http://static.springsource.org/spring-roo/reference/html/base-dbre.html o http://static.springsource.org/spring-roo/reference/html/base-web.html

8