Wednesday, March 9, 2011

Part II - Generating a GWT Project Using Spring Roo

In This Post

I am going to write about using Spring Roo to generate a Google Web Toolkit (GWT) Web application that runs on Google App Engine (GAE).  I will then go over building the Roo-generated project using Maven, running it, and finally importing it into STS.


The Pizza Shop Revisited

Lets use the Pizza Shop example introduced in SpringSource's own Roo tutorial on Spring-MVC Web applications to demonstrate the creation of a GWT Web application.  The goal is to use Spring Roo to create a Web site for a Pizza Shop. The requirements for the Pizza Shop application remain the same:
  • Ability to create new Pizza types by the staff
  • A pizza will be composed of a base and one or more toppings
  • Online orders of Pizzas by customers

Here is the class diagram for the domain model:



Enter Roo

Now that the design is in place, we are ready to start generating the code for our Pizza Shop GWT Web application using Roo.

Launch Command Prompt and navigate to the directory where you would like your project files to be created.

C:\>cd springsource\project

Create project directory and cd to it.

C:\springsource\project>mkdir pizzashop
C:\springsource\project>cd pizzashop

Fire up Roo.

C:\springsource\project\pizzashop>roo
    ____  ____  ____
   / __ \/ __ \/ __ \
  / /_/ / / / / / / /
 / _, _/ /_/ / /_/ /
/_/ |_|\____/\____/    1.1.3.BUILD-SNAPSHOT [rev 6d6c5d4]


Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo>

We are inside the Roo shell now and can only use Roo commands.  You may use the help command to view the lengthy list of commands made available to us by Roo or you can try your luck with the hint command if you wish to receive some advice and direction from Roo.  Tab completion is at your disposal as well.

For our Pizza Shop project, we are going to continue by creating a top level package using the project command.  Notice how Roo displays a list of changes made to your project with each command.

roo> project --topLevelPackage com.blogspot.gwtsts.pizzashop
Created ROOT\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
Created SRC_MAIN_RESOURCES\log4j.properties
com.blogspot.gwtsts.pizzashop roo>

Next step is to setup persistence with the persistence setup command.  Information on which JPA provider we will be using and the associated database has to be supplied with this command.  Additionally, we will need to supply an applicationId for our project since we have chosen Google App Engine (GAE) as our host.

com.blogspot.gwtsts.pizzashop roo> persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE --applicationId pizzashopexample
Updated ROOT\pom.xml [Removed redundant artifacts]
Updated SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml
Created SRC_MAIN_RESOURCES\META-INF\persistence.xml
Created SRC_MAIN_WEBAPP\WEB-INF
Created SRC_MAIN_WEBAPP\WEB-INF\appengine-web.xml
Created SRC_MAIN_WEBAPP\WEB-INF\logging.properties
Updated SRC_MAIN_RESOURCES\log4j.properties
Updated ROOT\pom.xml [Added property 'gae.version' with value '1.4.0']
Updated ROOT\pom.xml [Added property 'gae-test.version' with value '1.4.0']
Updated ROOT\pom.xml [Added property 'gae.home' with value '${user.home}/.m2/rep
ository/com/google/appengine/appengine-java-sdk/${gae.version}/appengine-java-sdk-${gae.version}']
Updated ROOT\pom.xml [Added property 'datanucleus.version' with value '1.1.5']
Updated ROOT\pom.xml [Added dependencies com.google.appengine.orm:datanucleus-appengine:1.0.7.final, com.google.appengine:appengine-api-1.0-sdk:${gae.version},
com.google.appengine:appengine-testing:${gae-test.version}, com.google.appengine:appengine-api-stubs:${gae-test.version}, com.google.appengine:appengine-api-labs:${gae-test.version}, javax.persistence:persistence-api:1.0, org.datanucleus:da
tanucleus-core:${datanucleus.version}, org.datanucleus:datanucleus-jpa:1.1.5, org.datanucleus:datanucleus-rdbms:${datanucleus.version}, org.datanucleus:datanucleus-enhancer:1.1.4, javax.jdo:jdo2-api:2.3-ec, org.hibernate:hibernate-validator:4.1.0.Final, javax.validation:validation-api:1.0.0.GA, cglib:cglib-nodep: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.4,commons-dbcp:commons-dbcp:1.3]
Updated ROOT\pom.xml [Added repositories http://maven-gae-plugin.googlecode.com/svn/repository, http://www.datanucleus.org/downloads/maven2/, https://repository.jboss.org/nexus/content/repositories/releases]
Updated ROOT\pom.xml [Added pluginRepositories http://maven-gae-plugin.googlecode.com/svn/repository, http://www.datanucleus.org/downloads/maven2/]
Updated ROOT\pom.xml [Added plugin maven-gae-plugin]
Updated ROOT\pom.xml [Added plugin maven-datanucleus-plugin]
Updated ROOT\pom.xml [Updated maven-eclipse-plugin]
Please enter your database details in src/main/resources/META-INF/persistence.xml.
com.blogspot.gwtsts.pizzashop roo>

Lets diverge from the original design to show how enums can be generated with Roo.  We will create a new enum type to track the type of payment selected for the pizza order.  We will provide the customers with three payment options:
  • Credit card payment online
  • Cash payment on delivery
  • Credit card payment on delivery
Note that enum classes are used by both the client and the server and thus should be placed inside the shared package.  The enum type command creates our enum class and the enum constant command inserts the constants as shown below.  Another issue to make a note about is the use of tilde character (~), which stands for the project's home package (com.blogspot.gwtsts.pizzashop) and saves us from having to repeat the entire package name for each command.

com.blogspot.gwtsts.pizzashop roo> enum type --class ~.shared.PaymentType
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\shared\PaymentType.java
~.shared.PaymentType roo> enum constant --name CC_ONLINE
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\shared\PaymentType.java
~.shared.PaymentType roo> enum constant --name CASH_ON_DELIVERY
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\shared\PaymentType.java
~.shared.PaymentType roo> enum constant --name CC_ON_DELIVERY
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\shared\PaymentType.java
~.shared.PaymentType roo>

The time has come to start creating our domain objects.  We will need to create Topping and Base prior to Pizza as they are contained or used by Pizza and we'll need to create Pizza before PizzaOrder for the same reason.  We will use the --testAutomatically option on all our domain objects, because it will generate integration tests for us and allow us to run them automatically.  Note that the generated domain object classes will only be used on the server-side and thus should be placed in the server package.  Classes placed under the server package will not be converted to JavaScript by the GWT compiler.

Create the Topping domain object using the entity command and notice that Roo generates various Java and AspectJ files in our project's src/main/java and src/test/java directories.

~.shared.PaymentType roo>entity --class ~.server.domain.Topping --testAutomatically
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingDataOnDemand.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingIntegrationTest.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_Configurable.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_Entity.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingIntegrationTest_Roo_IntegrationTest.aj
Deleted SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_ToString.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingDataOnDemand_Roo_Configurable.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingDataOnDemand_Roo_DataOnDemand.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingIntegrationTest_Roo_Configurable.aj
~.server.domain.Topping roo>

Notice that the context (blue-colored text) has been changed to our new Topping entity.  We can now use the field command to add its name field, which is of string type and should contain at least 2 characters.

~.server.domain.Topping roo> field string --fieldName name --notNull --sizeMin 2
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_JavaBean.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Topping_Roo_ToString.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\ToppingDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.Topping roo>

Lets create the Base domain object in the same manner along with its name field.

~.server.domain.Topping roo> entity --class ~.server.domain.Base --testAutomatically
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseDataOnDemand.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseIntegrationTest.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_Configurable.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_Entity.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseIntegrationTest_Roo_Configurable.aj
Deleted SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_ToString.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseIntegrationTest_Roo_IntegrationTest.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseDataOnDemand_Roo_DataOnDemand.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseDataOnDemand_Roo_Configurable.aj
~.server.domain.Base roo> field string --fieldName name --notNull --sizeMin 2
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_JavaBean.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Base_Roo_ToString.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\BaseDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.Base roo>

Notice that the context has changed to the Base domain object.  If we wanted to add a field to the Topping domain object at this point, then we would have to execute the field command and pass the fully-qualified class name for our Topping class via a --class option.

Lets create the Pizza domain object along with all its fields in the same fashion.  Remember that two of the fields for our Pizza domain object will be references to the Topping and Base domain objects.  In order to specify this relationship, we will use reference field and specify the fully-qualified class name through the use of a --type option.

~.server.domain.Base roo> entity --class ~.server.domain.Pizza --testAutomatically
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaIntegrationTest.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_Entity.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_Configurable.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand_Roo_DataOnDemand.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaIntegrationTest_Roo_IntegrationTest.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaIntegrationTest_Roo_Configurable.aj
Deleted SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand_Roo_Configurable.aj
~.server.domain.Pizza roo> field string --fieldName name --notNull --sizeMin 2
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza.java
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand_Roo_DataOnDemand.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_JavaBean.aj
~.server.domain.Pizza roo> field number --fieldName price --type java.lang.Float
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza.java
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand_Roo_DataOnDemand.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_JavaBean.aj
~.server.domain.Pizza roo> field set --fieldName toppings --type ~.server.domain.Topping
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_JavaBean.aj
~.server.domain.Pizza roo> field reference --fieldName base --type ~.server.domain.Base
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza.java
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaDataOnDemand_Roo_DataOnDemand.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\Pizza_Roo_JavaBean.aj
~.server.domain.Pizza roo>

Notice that since our pizza can have zero, one, or many toppings, the toppings field is a set.

Finally, lets create the PizzaOrder domain object, which will include the PaymentType enum that was generated earlier.

~.server.domain.Pizza roo> entity --class ~.server.domain.PizzaOrder --testAutomatically
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand.java
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderIntegrationTest.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_Entity.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_Configurable.aj
Deleted SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderIntegrationTest_Roo_IntegrationTest.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderIntegrationTest_Roo_Configurable.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_Configurable.aj
Created SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field string --fieldName name --notNull --sizeMin 2
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field string --fieldName address --sizeMax 30
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field number --fieldName total --type java.lang.Float
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field enum --fieldName paymentType --type ~.shared.PaymentType
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field date --fieldName deliveryDate --type java.util.Date
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
Updated SRC_TEST_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrderDataOnDemand_Roo_DataOnDemand.aj
~.server.domain.PizzaOrder roo> field set --fieldName pizzas --type ~.server.domain.Pizza
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder.java
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_ToString.aj
Updated SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\domain\PizzaOrder_Roo_JavaBean.aj
~.server.domain.PizzaOrder roo>

The gwt setup command creates all client-side GWT source files with the MVP pattern, RequestFactory, UiBinder, and GIN in place.  Since we have selected to work with GAE in this project, this command also creates and updates the required source files and configuration to enable support for GAE authentication.  The gwt setup command generates 254 lines of output, only some of which are shown below.

~.server.domain.PizzaOrder roo> gwt setup
Created SRC_MAIN_WEBAPP\WEB-INF\spring
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\ApplicationScaffold.gwt.xml
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\Scaffold.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\ScaffoldApp.java
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\gae\UserServiceLocator.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\server\gae\GaeAuthFilter.java
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\ioc\ScaffoldModule.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\ioc\MobileInjector.java
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\gae\GaeLoginWidgetDriver.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\scaffold\gae\GaeAuthRequestTransport.java
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\managed\request\ToppingProxy.java
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\managed\request\ToppingRequest.java
...
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\managed\ui\BaseListEditor.ui.xml
Created SRC_MAIN_JAVA\com\blogspot\gwtsts\pizzashop\client\managed\ui\BaseSetEditor.ui.xml
UPDATE: The gwt setup command does not work in Roo 1.1.4 due to the problem described in ROO-2445.

The following logging setup command updates the log4j.properties file to enable logging in our project at the INFO level.  Alternatively, we could have chosen to log at DEBUG, ERROR, FATAL, TRACE, or WARN levels.

~.server.domain.PizzaOrder roo> logging setup --level INFO
Updated SRC_MAIN_RESOURCES\log4j.properties

All of our project files have been generated after entering a total of 24 commands in the Roo shell.  Alternatively, we could have placed these 24 commands in a .roo file and generated our project using the script command as shown below.

roo> script --file pizzashop.roo

Contents of pizzashop.roo file:
project --topLevelPackage com.blogspot.gwtsts.pizzashop

persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE --applicationId pizzashopexample

enum type --class ~.shared.PaymentType
enum constant --name CC_ONLINE
enum constant --name CASH_ON_DELIVERY
enum constant --name CC_ON_DELIVERY

entity --class ~.server.domain.Topping --testAutomatically
field string --fieldName name --notNull --sizeMin 2

entity --class ~.server.domain.Base
--testAutomatically
field string --fieldName name --notNull --sizeMin 2

entity --class ~.server.domain.Pizza --testAutomatically
field string --fieldName name --notNull --sizeMin 2
field number --fieldName price --type java.lang.Float
field set --fieldName toppings --type ~.server.domain.Topping
field reference --fieldName base --type ~.server.domain.Base

entity --class ~.server.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 enum --fieldName paymentType --type ~.shared.PaymentType
field date --fieldName deliveryDate --type java.util.Date
field set --fieldName pizzas --type ~.server.domain.Pizza

gwt setup

logging setup --level INFO

Since we have used the entity command's --testAutomatically option to generate integration tests for all our domain objects, we can automatically execute integration tests by running the perform tests command.  Roo launches these integration tests by issuing a Maven command and produces over a thousand lines of ouput.

roo> perform tests
[Thread-8] [INFO] Scanning for projects...
[Thread-8] [INFO] ------------------------------------------------------------------------
[Thread-8] [INFO] Building pizzashop
[Thread-8] [INFO]    task-segment: [test]
[Thread-8] [INFO] ------------------------------------------------------------------------
[Thread-8] [INFO] [gae:unpack {execution: default}]
...
------------------------------------------------------------------------
[Thread-8] [INFO] BUILD SUCCESSFUL
[Thread-8] [INFO] ------------------------------------------------------------------------
[Thread-8] [INFO] Total time: 1 minute 10 seconds
[Thread-8] [INFO] Finished at: Wed Mar 09 01:02:59 EET 2011
[Thread-8] [INFO] Final Memory: 62M/357M
[Thread-8] [INFO] ------------------------------------------------------------------------

The backup command is useful to quickly backup all your project files in ZIP file format.  The archive file will be created in your project's root directory.

roo> backup
Created ROOT\pizzashop_2011-03-05_11.10.06.zip
Backup completed in 305 ms

Exit Roo shell with the exit command (quit also works).

roo> exit


Maven

From your project's root directory enter and execute mvn gwt:run command to build and run the Pizza Shop application via Maven.  Maven will download all dependencies that have been declared in your project's pom.xml file, the first time you run this command.

C:\springsource\project\pizzashop>mvn gwt:run

After successfully loading dependencies and building our project, Maven will launch our Web application in GWT development mode.

Click the "Launch Default Browser" button to launch the Pizza Shop Web application with the default browser on your system.  Alternatively, you can click the "Copy to Clipboard" button and paste the address to another browser you wish to use.

You will be greeted with a mock login screen.  Click login to enter the Roo-generated scaffold application.  Play around.



STS

Finally, lets import our Pizza Shop project into STS and make the neccessary configuration within STS to allow us to build and run our Web application.

Select the "Import..." menu item in STS's File menu to launch the Import wizard.










Select the "Existing Maven Projects" item under Maven and click Next to continue to the next step.








Browse to Pizza Shop root directory and click the Finish button to load the project into STS.  STS will automatically load project files and attempt to build the project, but we'll have to make some changes to the configuration before we can successfully build the project.







Right-click on your project in the Project Explorer and select Properties from the project context menu to open the project properties window.










Select Google-->App Engine-->ORM in the window titled "Properties for pizzashop."  This is where we configure project files that will be subjected to Object/Relational Mapping.  By default, STS directs DataNucleus to enhance every file under our src directory.  We want to change this to only include our entity classes.  Therefore, we will start by removing all directories added by default.  Then, we will add a pattern, which will include only our entity classes such as "src/main/**/server/domain/*.java".  After we click the OK button, STS will try to run DataNucleus enhancer and build the project again.

Our project is now loaded into STS.  Notice that you can access the Roo shell from within STS and further modify the project with Roo commands.  To run our Pizza Shop application from within STS, select Debug As --> Web Application from the project's context menu and click the OK button on the HTML Page Selection window, leaving ApplicationScaffold.html selected.  Click the Proceed button if a warning dialog pops up and follow progress on the Console window.  Once the server is running, you can start your application by double-clicking the URL displayed on the Development Mode window ...and we are back to where we left off in our Pizza Shop application.


In The Next Post

We will be going through the Roo-generated GWT code for our Pizza Shop project.



IntroPart IPart IIPart IIIPart IVPart V



11 comments:

  1. Nice stuff, Cengiz.
    Thanks for doing this.

    ReplyDelete
  2. You're welcome. I'm glad you liked it.

    ReplyDelete
  3. Thanks alot for these super tutos, well explain.
    It's me or that some pictures are missing ?

    ReplyDelete
  4. There should be seven images in this post. Are you not able to see all of them?

    ReplyDelete
  5. Hello

    It's a very complete tuturial! Thank you for your effort

    I have a problem. When I try to create the Topping entity appears this error

    roo> entity --class ~.server.domain.Topping --testAutomatically

    Command 'entity --class ~.server.domain.Topping --testAutomatically' was found but is not currently available (type 'help' then ENTER to learn about this command)

    Where is the problem? I am using roo 1.1.3 as you comment in your Post I
    Thanks

    ReplyDelete
  6. Ok, solved using the last Roo 1.1.3 snapshot

    ReplyDelete
  7. I have required to change the POM to change the roo.annotations library.

    I used 1.1.2.RELEASE

    I hope this will be usefull

    ReplyDelete
  8. If you are not using App Engine, then ROO-2204 could be your problem. See https://jira.springsource.org/browse/ROO-2204

    ReplyDelete
  9. Hei,

    thanks for your posts! They really helped me.

    However i have another problem with the latest 1.1.3. Snaphot:
    Missing artifact org.springframework.roo:org.springframework.roo.annotations:jar:1.1.3.BUILD-SNAPSHOT:provided

    I have no clue how to solve this. Can you give me some advice?

    ReplyDelete
  10. Ok I got it.
    Xavi already explained it.
    For those who maybe have the same problem - Change the version field in your pom.xml from {roo.version} to 1.1.2.RELEASE.

    ReplyDelete
  11. Xavi, Alex,

    The contents of the snapshot change with every build and some builds can be unstable.

    I have uploaded the snapshot version that I have used in my posts. You can click the link provided at the following address to access it:
    http://gwtsts.blogspot.com/2011/03/part-i-installation-and-setup-of-sts.html#snapshot

    ReplyDelete