Developing Web Applications
with Google Web Toolkit and OpenRules

Part 2 – Externalizing Business Logic

   

Part-1   Main

Steps                                                                                                                                      

In the Part 1 we have created a working GWT application that enters customer data and generates a simple greeting.  While the application uses only simple greeting rules hardcoded directly in the GWT composite Hello.java, the whole setup works. Now we are ready to add real functionality.  First we will create a remote greeting service in Java with still simple greeting rules. Secondary, we will externalize these rules into OpenRules-based Excel tables allowing them to be executed on the server side using OpenRulesEngine. Then we will make our business logic (greeting rules) much more complex without changing Java code. The final application will use OpenRules in both host and web modes.

Step 11 – Creating Remote Greeting Service  ►top

Let's copy our Part 1 Eclipse project HelloGWT to a new Eclipse project HelloGWTOpenRules that will gradually support an OpenRules-based remote greeting service. GWT Designer provides a wizard for creating remote services. Select the client package com.openrules.gwt.client and select the Designer toolbar button and select GWT > GWT Remote Service from the pull-down menu:

and type GreetingService as a name of the new remote service:

The GWT Designer will add two new classes to the package com.openrules.gwt.client:

and one new class to the package com.openrules.gwt.server:

The GWT Designer also added the remote path description

         <servlet path="/GreetingService" class="com.openrules.gwt.server.GreetingServiceImpl"/>

to the module XML file src\com\openrules\gwt\HelloGWT.gwt.xml.

The GWT Designer will keep all these files synchronized, e.g. adding a method to the remote service interface class will automatically add the appropriate method to the matching *Async and *Impl classes.

We want to pass to our remote greeting service a customer and receive back a greeting for this customer at this particular time of day.  Thus, we will add only one method "getGreeting" to the automatically created interface GreetingService.java:

 

src/com/openrules/gwt/client/GreetingService.java
package com.openrules.gwt.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

public interface GreetingService extends RemoteService {

public String getGreeting(Customer customer);

/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
   private static GreetingServiceAsync instance;
   public static GreetingServiceAsync getInstance(){
   if (instance == null) {
       instance = (GreetingServiceAsync) GWT.create(GreetingService.class);
       ServiceDefTarget target = (ServiceDefTarget) instance;
       target.setServiceEntryPoint(GWT.getModuleBaseURL() + "GreetingService");
   }
   return instance;
}

}

When we save the changes in the file GreetingService.java, this method will be automatically added to the files  GreetingServiceAsync.java and GreetingServiceImpl.java.  Before we start adding an actual greeting rules implementation  in the file GreetingServiceImpl.java we have to take care of the important GWT convention that states: Java objects passed between client and server must be marked as serializable via the GWT IsSerializable interface. Thus, we have to add the clause "implements IsSerializable" to our class Customer.java:

 

HelloGWTOpenRules/src/com/openrules/gwt/client/Customer.java
package com.openrules.gwt.client;

import com.google.gwt.user.client.rpc.IsSerializable;

public class Customer implements IsSerializable {
	String name;
	String maritalStatus;
	String gender;
	int age;
		
	.....
}

Step 12 – Moving  Business Logic from GUI to Remote Service ►top

In Part 1 we placed greeting rules into the file Hello.java that implements the GWT user interface.  Now we will move greeting rules from the client-based Hello.java to our server-based greeting service implementation GreetingServiceImpl.java:

 

HelloGWTOpenRules/src/com/openrules/gwt/server/GreetingServiceImpl.java
package com.openrules.gwt.server;
import com.openrules.gwt.client.Customer;
import com.openrules.gwt.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {

    public String getGreeting(Customer customer) {
     /*
      * Greeting generation rules
      */
      String salutation = "?";
      if (customer.getGender().equals("Male"))
          salutation = "Mr.";
      else {
          if (customer.getMaritalStatus().equals("Single"))
              salutation = "Ms.";
          else
              salutation = "Mrs.";
      }
      return "Hello " + salutation + customer.getName() + "!";
   }
}

And we have to modify the user interface Hello.java so when the user clicks on the Generate Greeting button the interface will invoke our remote service to produce the proper greeting. To do that we will add the call of the remote service instead of rules into the listener for our Generate Greeting button:

 

HelloGWTOpenRules/src/com/openrules/gwt/client/Hello.java
...
       generateGreetingButton.addClickListener(new ClickListener() {
              public void onClick(final Widget sender) {
 
                     customer.setName(textBoxName.getText());
                      customer.setAge(Integer.parseInt(textBoxAge.getText()));
                      String gender = (maleRadioButton.isChecked()) ? "Male" : "Female";
                      customer.setGender(gender);               
                      int selectedIndex = listBoxMaritalStatus.getSelectedIndex();
                      String maritalStatus = listBoxMaritalStatus.getItemText(selectedIndex);
                      customer.setMaritalStatus(maritalStatus);
                     /*
                      * execute remote GreetingService
                      */

                      AsyncCallback callback = new AsyncCallback() {
                             public
void onSuccess(Object result) {
                                    textBoxGeneratedGreeting.setText((String) result);
                             }
                             public
void onFailure(Throwable ex) {
                             }
                      };

                      GreetingService.Util.getInstance().getGreeting(customer, callback);
              }
        });
....

Now we are ready to run the application in hosted mode.

Step 13 – Run Remote Service in Hosted Mode  ►top

In the Eclipse Package explorer, right-click the HelloGWT.java and select Run As > GWT Application.
This will create a launch configuration and run the application locally. Click on the Generate Greeting button.

While now we use a remote service the results are identical to those in the Part 1.

Step 14 – Deploy and Run Remote Service in Web Mode  ►top

Right click on HelloGWT.java and select Google Web Toolkit > Deploy module. Specify the server deployment options as follows:

Click OK to complete the deployment of our remote service on Tomcat as HelloGWTOpenRules.war.

Now you may start/restart your Tomcat server. To run the application deployed on the Tomcat, slightly modify the file run.html using the new path HelloGWTOpenRules:
 

HelloGWTOpenRules/run.html

<h2> Deployed GWT-OpenRules Application </h2>

<h3> http://localhost:8080/HelloGWTOpenRules/HelloGWT.html</h3>

<a href="http://localhost:8080/HelloGWTOpenRules/HelloGWT.html">

Run</a>

Double-click on the run.html to launch your application in the web mode. The results will be again identical to the web mode results from the Part 1.

Step 15 – Moving Business Logic to OpenRules  ►top

The greeting rules above deal only with customer's gender and marital status and produced only salutation like "Mr." or "Mrs.".  We want to create a more sophisticated greeting service that could generate a personalized greeting for any Customer based on time of the day and customer's attributes, and most importantly it should be extracted form the code to be managed by business analysts (not programmers).  To achieve this we will externalize business logic from Java to OpenRules business rules. 

We will start with the greeting rules themselves. OpenRules provides similar greeting rules with many standard examples for different environments - see for example the basic project HelloJava. For simplicity, we will place all rules inside one Excel file HelloCustomer.xls. We will place this file inside HelloGWTOpenRules/src/com/openrules/gwt/public (while any other folder could be selected).

We will create the following tables inside this file:
 

Rules void defineGreeting(int hour, Response response)
C1 C2 A1
min <= hour hour <= max response.map.put("greeting", greeting); 
int min int max String greeting
Hour From Hour To Set Greeting
0 11 Good Morning
12 17 Good Afternoon
18 22 Good Evening
23 24 Good Night

 

Rules void defineSalutation(Customer customer, Response response)
C1 C2 C3 A1
customer.gender.equals(gender) customer.maritalStatus.equals(status)  customer.age < age response.map.put("salutation",salutation); 
String gender String status int age String salutation
Gender Marital Status Age Less Than Set Salutation
Male     Mr.
Female Married   Mrs.
Female Single   Ms.
Male   <5 Little

We will use the method "helloCustomer" as the main method that will be called from the OpenRulesEngine:

 

Method String helloCustomer(Customer customer, Response response)
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
defineGreeting(hour, response);
defineSalutation(customer,response);
String result  = response.map.get("greeting") + ", " + response.map.get("salutation") + " " + customer.name + "!";
return result;

This method that will find out the current time, execute rules "defineGreeting" and "defineSalutation", and will return a ready-to-go greeting.

To make sure that our rules inside this Excel file "understand" our Java classes Customer and Response from the package "hello", we should add the following Environment table:
 

Environment
import.java com.openrules.gwt.client.Customer
com.openrules.gwt.server.Response

Our rules use two parameters "customer" and "response". The second parameter of the type Response is used to demonstrate how to pass back more information from OpenRules. Here is the code for the class Response needed only on the server side:
 

HelloGWTOpenRules/src/com/openrules/gwt/server/Response.java
package com.openrules.gwt.server;
import java.util.HashMap;

public class Response extends HashMap {
}

Now we will make our project to be dependent on OpenRules. In Eclipse we will open the properties of the project HelloGWTOpenRules and add "openrules.config" to the Java build path.

To complete the integration, we have to replace old rules inside GreetingServiceImpl.java to an execution of a preliminary created OpenRulesEngine:

 

HelloGWTOpenRules/src/com/openrules/gwt/server/GreetingServiceImpl.java
package com.openrules.gwt.server;
import com.openrules.gwt.client.Customer;
import com.openrules.gwt.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
    OpenRulesEngine ruleEngine = null;

    static String filename = "file:./webapps/HelloGWTOpenRules/HelloCustomer.xls";  // for WEB MODE
    //static
String filename = "file:./src/com/openrules/gwt/public/HelloCustomer.xls";  // for HOST MODE

    public String getGreeting(Customer customer) {
          try
{
                if
(ruleEngine == null) {
                     ruleEngine = new OpenRulesEngine(filename);
                }
                Response response = new Response();
                Object[] objects = new Object[] { customer, response };
                return
(String) ruleEngine.run("helloCustomer", objects);
          } catch (Exception e) {
                return
"Errors creating OpenRulesEngine";
          }
    }
}

The OpenRulesEngine will be created upon the first execution of the remote method getGreeting. The OpenRulesEngine has to know the location of the main Excel file "HelloCustomer.xls" that is different for different execution modes:

In the code above we use the web mode (the host mode is commented out). 

To deploy our modified service at the Tomcat follow the same steps as at the Step 14 above. Right click on HelloGWT.java and select Google Web Toolkit > Deploy module. Double-click on the run.html to launch your application in the web mode with OpenRulesEngine executing the Excel-based business rules:

To run in the host mode switch the execution mode do the following:

Thus, our OpenRules-based remote service works with our GWT greeting application. Much more complex applications with GWT-based GUI and OpenRules-based server could be developed in a similar way.

 

Summary  ►top

  1. We created a remote service for the GWT application from the Part 1

  2. We define more sophisticated greeting rules in Excel using OpenRules decision tables.

  3. We deployed and executed the GWT Greeting Application in both web and host modes with OpenRules taking care about business logic.

 

Main   Part 1   ►top

Copyright © 2008, OpenRules, Inc.