In Roo-generated applications, you can change JPA entities and let Roo take care of making necessary changes to the controllers and views. In this recipe, we look at an example scenario, which demonstrates how changes to a JPA entity are propagated to corresponding controllers and views.
Delete the contents of the ch04-recipe
sub-directory inside the C:
oo-cookbook
directory.
Copy the ch04_web-app.roo
script into the ch04-recipe
directory.
Execute the ch04_web-app.roo
script that creates the flight-app
Roo project, sets up Hibernate as the persistence provider, configures MySQL as the database for the application, creates Flight
and FlightDescription
JPA entities, and defines a many-to-one relationship between the Flight
and FlightDescription
entities. If you are using a different database than MySQL or your connection settings are different than what is specified in the script, then modify the script accordingly.
Start the Roo shell from the C:
oo-cookbookch04-recipe
directory.
Execute the controller
all
command to create controllers and views corresponding to JPA entities in the flight-app
project, as shown here:
.. roo> controller all --package ~.web
Execute the perform
eclipse
command to update the project's classpath settings, as shown here:
.. roo> perform eclipse
Now, import the project into your Eclipse IDE.
The following code from the FlightDescription.java
file shows the FlightDescription
entity, which we will modify in this recipe to get a feel of Roo's round-tripping capabilities:
@RooJavaBean @RooToString @RooEntity(identifierField = "flightDescId", identifierColumn = "FLIGHT_DESC_ID", table = "FLIGHT_DESC_TBL", finders = {"findFlightDescriptionsByDestinationAndOrigin" }) public class FlightDescription { @NotNull @Column(name = "ORIGIN_CITY") private String origin; @NotNull @Column(name = "DESTINATION_CITY") private String destination; @NotNull @Column(name = "PRICE") private Float price; }
To see round-tripping support for web controllers and views, follow the steps given here:
FlightDescription.java
file in your editor.finders
attribute and its value from the @RooEntity
annotation, and save the FlightDescription.java
file. The Roo shell shows the actions taken by Roo in response to the deletion of the finders
attribute, as shown here:Updated SRC_MAIN_WEBAPPWEB-INFviewsmenu.jspx Deleted SRC_MAIN_JAVA...webFlightDescriptionController_Roo_Controller_Finder.aj Deleted SRC_MAIN_JAVA...domainFlightDescription_Roo_Finder.aj
origin
field to originCity
, destination
field name to destinationCity
and save the FlightDescription.java
file. The Roo shell shows the following actions taken by Roo in response to our changes:Updated ...WEB-INFviewsflightdescriptionslist.jspx Updated ...WEB-INFviewsflightdescriptionsshow.jspx Updated ...WEB-INFviewsflightdescriptionscreate.jspx Updated ...WEB-INFviewsflightdescriptionsupdate.jspx Updated ...WEB-INFi18napplication.properties Updated ...domainFlightDescription_Roo_JavaBean.aj Updated SRC_MAIN_JAVA...webApplicationConversionServiceFactoryBean_Roo_ConversionService.aj Updated SRC_MAIN_JAVA...domainFlightDescription_Roo_ToString.aj
@NotNull
JSR 303 annotation from the price
field and save the FlightDescription.java
file. Now, Roo shell shows the following output in response to the change:Updated...WEB-INFviewsflightdescriptionscreate.jspx Updated...WEB-INFviewsflightdescriptionsupdate.jspx
Let's now look at what Spring Roo did when we made modifications to FlightDescription.java
. The following adjustments were made by Spring Roo in the flight-app
project when the finders
element was removed:
FlightDescription_Roo_Finder.aj
ITD, which contained the implementation of the finder method.FlightDescriptionController_Roo_Controller_Finder.aj
ITD was created initially, it contained a method for showing the form (refer to /WEB-INF/views/flightdescriptions/findFlightDescriptionsByDestinationAndOrigin.jspx
), which allows searching for a FlightDescription
based on origin and destination cities. It also contained a method to search the FlightDescription
instances and display returned results (refer to /WEB-INF/views/flightdescriptions/list.jspx
). Now, as the finder method has been removed, the controller methods to show the search form and search results are removed. It is important to note that in Spring Roo 1.1.3, the method responsible for searching entity instances is not created in FlightDescriptionController_Roo_Controller_Finder.aj
. This bug is resolved in Spring Roo 1.1.4 and above.It is important to note that even though the findFlightDescriptionsByDestinationAndOrigin.jspx
file is no longer required in the flight-app
application, Spring Roo doesn't remove it. You will need to manually remove the JSPX file from your Roo project. This is because Spring Roo doesn't automatically delete JSPX files that are no longer required in the application.
menu.jspx
file.When the origin
and the destination
field names are modified, then the following modifications are performed by Roo:
FlightDescription_Roo_JavaBean.aj
ITD, the getter and setter methods for the origin
and the destination
fields are replaced with the getter and setter methods for originCity
and destinationCity
, respectively.FlightDescription_Roo_ToString.aj
ITD, the toString
method is modified to include the value of the destinationCity
and originCity
fields, instead of the origin
and the destination
fields.ApplicationConversionServiceFactoryBean
is configured by the <mvc:annotation-driven>
element defined in the web application context XML. We saw earlier that the *_Roo_ConversionService.aj
file of the flight-app
project introduces static classes into the ApplicationConversionServiceFactoryBean
class that represent converters for the Flight
and the FlightDescription
JPA entities.FlightDescriptionConverter
static class defined in ApplicationConversionServiceFactoryBean_Roo_ConversionService.aj
, which returns the converter for the FlightDescription
entity:import org.springframework.core.convert.converter.Converter; privileged aspect ApplicationConversionServiceFactoryBean_Roo_ConversionService { ... static class ApplicationConversionServiceFactoryBean. FlightDescriptionConverter implements Converter<FlightDescription, java.lang.String> { public String convert(FlightDescription flightDescription){ return new StringBuilder(). append(flightDescription.getOrigin()). append(""). append(flightDescription.getDestination()). append(" "). append(flightDescription.getPrice()).toString(); } } ... }
In the given code, the FlightDescriptionConverter
static class implements Spring's Converter
. It converts the FlightDescription
JPA entity into a String
representation. The String
representation of FlightDescription
is created by simply concatenating the values of each of its fields.
As we modified the names of the origin
and the destination
fields to originCity
and destinationCity
, Roo modifies the FlightDescriptionConverter
class to use the modified getter methods for the fields. The changes that occurred due to these modifications can be outlined as follows:
application.properties
file is modified to add new properties, which act as labels, for the originCity
and the destinationCity
fields, as shown here:label_sample_roo_flightapp_domain_flightdescription_destinationcity=Destination City label_sample_roo_flightapp_domain_flightdescription_origincity=Origin City
As you may have guessed, the property names are derived from the package in which the JPA entity resides, that is the JPA entity name and the name of the field. It is also important to note that once a property is added to the application.properties
file, it is never removed or modified by Roo. Roo always creates new properties in the application.properties
file. So, if you frequently modify your JPA entity fields, it will result in unwanted proliferation of properties in the application.properties
file, which you will need to remove manually.
create.jspx
, update.jspx
, show.jspx
, and the list.jspx
files in /WEB-INF/views/flightdescriptions/
are modified to reflect the change in name of the fields of the FlightDescription
JPA entity. It is important to note that if a field defined in the JSPX view is not Roo-managed, that is, the value of the z
attribute is 'user-managed' then Roo will not make any modification to the field in response to changes in JPA entities.When the @NotNull
JSR 303 annotation is removed from the price
field of FlightDescription
, then Roo cascades this change to the /WEB-INF/views/flightdescriptions/create.jspx
and the /WEB-INF/views/flightdescriptions/update.jspx
views. The only change that Roo makes to these views is to remove the required
attribute from the <input>
custom tag element that shows the price
field on the web user interface.
The round-tripping support for JSPX views in Roo is quite sophisticated and takes care of the following changes in the Roo-managed JPA entity:
If you want a particular element of a JSPX to remain unmodified even if the corresponding field in the Roo-managed JPA entity is modified, then you can manually set the z
attribute value to user-managed
. The sideeffect of this change is that Roo will create a new element in the JSPX views if you add or modify the corresponding JPA entity field.
13.58.51.36