Implementing a continuous build system for WebSphere ILOG Business Rule Management Systems

In this article, you'll learn how to implement and deploy a continuous build system for WebSphere® ILOG Business Rule Management Systems Rule Team Server and Decision Validation Services using the JRules Java™ APIs and customization facilities.

Chabane Hamma (chabane.hamma@fr.ibm.com), Senior Software Engineer, IBM

Chabane Hamma photoChabane Hamma has been the team leader of samples and tutorials for ILOG Business Rule Management Systems since 2006. His areas of expertise include BRMS and the design and development of distributed applications that leverage web and database technologies including the JEE platform.



Antoine Melki (antoine.melki@fr.ibm.com), Senior Software Engineer, IBM

Antoine Melki photoAntoine Melki is a software architect with over a decade of experience developing and designing various parts of ILOG Business Rule Management Systems. He has been the main architect and team lead for ILOG BRMS Rule Team Server since its creation four years ago. Rule Team Server is a highly scalable rule repository exposed through a web-based rule management environment for business users.



08 April 2011

Also available in Chinese

Introduction

Rule Team Server and Decision Validation Services (DVS) are two major components of the WebSphere ILOG Business Rule Management Systems suite (BRMS). Rule Team Server allows business people to write and manage business rules in a web-based environment while DVS lets them write test suites to validate their rulesets against a set of input data, and check that the results match their expectations. Once defined, any business user having the permissions to do so can manually run the test suites using the Rule Team Server web application. However, as for any team development activity, as the number of rules and the number of Rule Team Server users on a project grows, a strong governance becomes necessary for validating the state of the repository at any point in time, as well as for making sure that Rule Team Server always provides a reasonable response time to rule authors.

Seated on top of a database, the Rule Team Server repository has been designed to handle hundreds of thousands of rules and be accessed by tens of users working collaboratively on the same project. Build operations however, which often involve processing the entire content of a rule project will take a non-negligible amount of time to be performed. A build operation can be: the deployment of an executable set of rules (namely a RuleApp) to Rule Execution Server, the execution of a test suite or the generation of an HTML report displaying the business rules contained in a project.

As an example, deploying a RuleApp containing 10,000 rules on an average PC, can take up to 3 minutes the first time it is triggered on the server, and 10 seconds the second time, a cache of the executable version of the rules being stored on the hard drive. Although those times can be acceptable for applications where rule maintenance is not a daily activity, and the number of users is relatively small, it can start causing performance issues if many users are connected at the same time, triggering reports and RuleApp deployments.

Also, with many users writing many rules, the IT needs a governance of the testing activities to ensure the validation of a rule project at any point in time, and be able to quickly warn an author if an error occurs and ask for or work on a fix so that the rule base is constantly valid and ready to be deployed to production.

In this article, we propose an architecture using Rule Team Server and DVS to implement a continuous build system for WebSphere ILOG Rules.

Solution and architecture

The overall principle of the continuous build system we would like to set up is simple: each time a business rule is created, updated or deleted in Rule Team Server, a notification is sent via JMS to a remote Message-Driven Bean (MDB), which will process the notifications and, according to some criteria (time since last build, number of commits since last build, and so on), will trigger a build on another instance of Rule Team Server, dedicated to build.

We propose to define the following tiers, as shown in Figure 1:

  • Authoring Server: An instance of Rule Team Server used by business users for their standard rule authoring and management work.
  • Build Server: A second instance of Rule Team Server dedicated to build, reading data from the same database as the one used by Authoring Server.
  • Execution Server: An instance of Rule Execution Server that will execute test suites triggered by Build Server through the DVS Scenario Service Provider (SSP).
Figure 1. Continuous build architecture
Architecture of the tiers defined for the continuous build system

Authoring Server

Authoring Server hosts an instance of Rule Team Server dedicated to collaborative rule authoring. Business users will be connected to it to create and manage their business rules. A custom session controller packaged within the Rule Team Server EAR ensures that for any business rule creation or change, a message is sent to Build Server through a JMS queue.

Authoring Server will run on a dedicated machine, or, depending on the workload (mainly number of users, number of rules, size of the vocabulary), in a clustered environment.

Build Server

Build server hosts an MDB and another instance of Rule Team Server. The MDB will read messages posted by Authoring Server to a JMS queue, and will trigger a build after a commit, if a given time has elapsed since the last build was completed. Note that the way builds are triggered is kept simple for this sample application. You may want to set up some more complex patterns, such as defining a minimum time between two consecutive builds, or only triggering a build after a certain number of changes.

The associated Rule Team Server instance will be called by the MDB to run all test suites contained in the repository. Prior to rule execution, a RuleApp is created: this consists of gathering the rules of a rule project designated to be executed by a test suite, and generating an archive file containing the executable form of the rules. Depending on the size of the repository (number of rules and decision tables, number of BOM classes and members), this build operation can be costly. This is why the WebSphere Application Server instance hosting this Rule Team Server has to run on a different machine than the one(s) used by Authoring server. This is a key point of the proposed architecture: the payload involved in building a RuleApp archive for testing is deferred to Build Server, so that business users can continue to work smoothly on Authoring Server while a build is performed.

Build Server will then delegate the execution of DVS tests suites to Execution Server, sending a request to the Scenario Service Provider (SSP), which can be either colocated with Build Server, or on a different machine.

Execution Server

Execution Server hosts three components: eXecution Unit (XU), part of Rule Execution Server, which executes rules using the JRules engine, the Rule Execution Server console, which stores deployed RuleApps containig the executable version of the rules, and the Scenario Service Provider (SSP), which is the runtime part of DVS. When Build Server triggers a build, it will remotely call SSP, passing a RuleApp and the list of scenarios to test. SSP will then transfer the RuleApp to the Rule Execution Server console, and request an execution to XU, passing a classloader containing the eXecutable Object Model (XOM) classes of the rule application as a parameter. The XOM classes are packaged within the SSP WAR file.

Preparing your environment

In the Downloads section, you will find a sample implementation of a continuous build system for Rule Team Server and DVS, using the principles and pieces of code described in this article. This section explains how to set up the sample environment and how to run it. If you just want to quickly get an understanding of the architecture and coding, you may want to skip ahead to Implementing Authoring Server.

Prerequisites

We assume you are using five machines, with the following names, purposes, and products installed:

Table 1. Required machines and products installed
PurposeHost nameRequired product(s)
Development and adminadmin.example.comIBM WebSphere ILOG JRules V7.1.x
IBM WebSphere ILOG Rule Team Server 7.1.x
IBM WebSphere ILOG Decision Validation Services 7.1.x
Authoring serverauthoring.example.comIBM WebSphere Application Server V7.0
Build serverbuild.example.comIBM WebSphere Application Server V7.0
Execution serverexecution.example.comIBM WebSphere Application Server V7.0
Databasedb.example.comIBM DB2 V9.x, or any database suppported by JRules

Although we strongly recommend separating tiers on different machines, you can run the sample using a single machine, and replace each address given above with localhost.

Create a cell

First we will set up a WebSphere cell on admin.example.com to administer Authoring Server, Build Server and Execution Server, as shown in Figure 2. Each of those tiers will have a corresponding node and server.

Figure 2. Rule Team Server cell topology
Rule Team Server cell topology

Follow these steps to create the WebSphere cell from admin.example.com:

  1. Start the Profile Management Tool.
  2. Click Launch Profile Management Tool and click Create.
  3. Under Environment Selection, select Cell (deployment manager and a federated application server), then click Next.
  4. In Profile Creation Options, select Advanced profile creation and uncheck Deploy the default application, then click Next. This opens the Profile Name and Location panel.
  5. Set Deployment manager profile name to DeploymentManager, then click Next. This opens the Node, Host, and Cell Names panel.
  6. Set Deployment manager node name to RuleTeamServerCellManagerNode.
  7. Set Cell name to RuleTeamServerCell, then click Next. This opens the Administrative Security panel.
  8. Check Enable administrative security, and set the username and password to websphere (or a username and password of your choice), then click Next until the Windows Service Definition panel is displayed.
  9. Uncheck Run the deployment manager process as a Windows service, then click Next until the Profile Creation Summary panel is displayed.
  10. Click Create, then Finish.

Create nodes

You will now create the node for authoring server by completing the following steps:

  1. From authoring.example.com, start the Profile Management Tool.
  2. Click Launch Profile Management Tool and click Create..
  3. In Environment Selection, select Custom profile and click Next.
  4. In Profile Creation Options, select Advanced profile creation, then click Next. This opens the Profile Name and Location panel.
  5. Set Profile name to AuthoringServer and click Next. This opens the Node and Host Names panel.
  6. Set Node name to AuthoringServerNode and click Next. This opens the Federation panel.
  7. Set hostname to admin.example.com.
  8. Set the port to the SOAP port number of the deployment manager (to find this, open the admin console, and look at System Administration => Deployment manager => Ports => SOAP_CONNECTOR_ADDRESS).
  9. Set the username and password to log in to the deployment manager (websphere / websphere).
  10. Click Next until the Windows Service Definition panel is displayed.
  11. Uncheck Run the deployment manager process as a Windows service and click Next until the Profile Creation Summary panel is displayed.
  12. Click Create, then Finish.
  13. Open the deployment manager admin console.
  14. Select Servers => Server Types => WebSphere applications servers, and click New.
  15. Select AuthoringServerNode as the node, call the server AuthoringServer, and cllick Next, then Finish, and Save your configuration.
  16. Start the newly created server from the Application Servers panel.

Repeat the same steps to create the build server node (BuildServerNode) on build.example.com, and the execution server node (ExecutionServerNode), on execution.example.com.

Prepare the cell for use with JRules

There are a few configuration steps to perform at the cell level so that the tiers can host the JRules components (Rule Team Server, Rule Execution Server and DVS). Most of the steps described here are fully described on the ILOG JRules Information Center topic WebSphere ILOG JRules BRMS V7.1: Java EE add-ons > Installing on WebSphere Application Server.

First you must enable application security to enable user log in on the Rule Team Server console:

  1. Start the deployment manager and run the admin console.
  2. In Security > Global Security, check Enable Application Security.
  3. Click Apply, then Save.

Now you need to create three users: jrulesAuthor, which will be able to connect to Authoring Server only, jrulesBuilder, which will connect to Build Server programmatically in order to run test suites, as well as execute rulesets on Rule Execution Server, and finally, jrulesAdmin, which you will use for preparatory work on Rule Team Server:

  1. Select Users and Groups => Manage Users and click Create.
  2. Set jrulesAuthor as the user and jrulesAuthoras the password, then click Create.
  3. Click Create like and set jrulesBuilder as the user and jrulesBuilder as the password, then click Create..
  4. Click Create like and set jrulesAdmin as the user and jrulesAdmin as the password, then click Create.
  5. Click Close.

You need to define two datasources with the scope set to Cell=RuleTeamServerCell, with the following JNDI names:

  • jdbc/ilogDataSource, where Rule Team Server tables will be created.
  • jdbc/resdatasource, where Rule Execution Server and DVS tables will be created.

If the datasources you defined do not use an XA driver, you will have to enable server-wide Last Participant Support (LPS) for Build Server so that the global transaction initiated during the commit of an artifact in Rule Team Server does not fail, since it involves two transactional operations: connecting to the (non-XA) datasource and sending a JMS message. To do this, complete the following steps:

  1. Select Servers => Server Types => WebSphere Application Servers and select Authoring Server.
  2. Under Container Settings, expand Container Services and click Transaction Service to display the properties page for the transaction service.
  3. Check Accept heuristic hazard, then click OK and Save your changes.
  4. Restart Authoring Server.

Finally, you have to create three virtual hosts, one for Authoring Server, one for Build Server, and one for Execution server.

The steps below show how to create the host for Authoring Server:

  1. Select Environment => Virtual hosts.
  2. Click New and specify authoring_host as the name, then click OK and Save.
  3. Click authoring_host.
  4. Click Host aliases.
  5. Click New.
  6. Set * as the hostname and set the port to the HTTP port of Authoring Server (check Servers => Server Types => WebSphere Application Servers => AuthoringServer => Ports= > WC_defaulthost) for this value).

Repeat this operation to define build_host and execution_host.

Finally, restart the deployment manager and its nodes so that the settings are taken into account.

Import the sample projects

You can now start Rule Studio from admin.example.com by selecting Start => IBM WebSphere ILOG JRules V7.1.0 => JRules => Development => Rule Studio) with a fresh workspace. After having downloaded the sample Eclipse project from the Downloads section, you can import it into your workspace by selecting File => Import => Existing Projects into Workspace, then click Select archive file, choose the downloaded zip file, and click Finish.

The next step is to define the WAS7_HOME environment variable:

  • Right-click on the continuousbuild project node, then select Properties => Java Build Path => Libraries.
  • Select Add Variable, then click Configure Variables => New.
  • Set Name to WAS7_HOME and Path to the folder containing your WebSphere Application Server installation.
  • Click OK.

Finally you need to import the loanvalidation-rules and loanvalidation-xom sample projects into your workspace:

  • Select File => Import => Existing Projects into Workspace, then Select root directory and choose <JRules dir>/studio/tutorials/shared/loanvalidation-rules.
  • Check Copy projects into workspace and click OK, then Finish.
  • Select File => Import => Existing Projects into Workspace, then click Select root directory and choose <JRules dir>/studio/tutorials/shared/loanvalidation-xom.
  • Check Copy projects into workspace and click OK, then Finish.

Figure 3 shows the layout of the workspace after having switched the current perspective from Rule to Java (top right corner of your Eclipse).

Figure 3. Sample workspace layout
Sample workspace layout

Implementing the authoring server

This sections steps through the process of implementing Authoring Server.

Write a session controller class

All business rules commits done in Authoring Server must notify Build Server, so that it can decide whether a build can be triggered or not. This is done by implementing a session controller for the Rule Team Server instance which will be hosted by Authoring Server. The session controller is a Java class, which can be used to control and watch the different aspects of the governance of the repository, such as access control, or business artifacts lifecycle.

Here, you will define the elementCommitted method, as shown in Listing 1. Each new business rule version created (IlrElementHandle object passed to the elementCommitted method) will be sent to a JMS queue named ContinuousBuildQueue, which will be consumed remotely by an MDB installed on Build Server.

Listing 1. Session controller
public class BuildController extends IlrDefaultSessionController {

  /**
   * For each commit, applies the default behavior, and if the committed object is a 
   * project element, sends a message containing the committed handle to a JMS queue.
   */
  public void elementCommitted(IlrCommitableObject cobject, IlrElementHandle newHandle)
    throws IlrObjectNotFoundException {
    super.elementCommitted(cobject, newHandle);
    if (session.getBrmPackage().getBusinessRule().isSuperTypeOf(newHandle.eClass())) {
      QueueConnection connection = null;
      try {
        InitialContext context = new InitialContext();
        QueueConnectionFactory qcf = (QueueConnectionFactory) context
          .lookup("jms/ContinuousBuildQueueConnectionFactory");
        Queue queue = (Queue) context.lookup("jms/ContinuousBuildQueue");
        connection = qcf.createQueueConnection();
        QueueSession queueSession
                = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
        QueueSender sender = queueSession.createSender(queue);
        ObjectMessage message = queueSession.createObjectMessage();
        CommitInfo info = new CommitInfo(session, newHandle); 
        message.setObject(info);
        sender.send(message);
      } catch (NamingException e) {
        Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
      } catch (JMSException e) {
        Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
      } finally {
        if (connection != null) {
          try {
            connection.close();
          } catch (JMSException e) {
            Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
          }
        }
      }
    }
  }
  
}

As shown in Listing 2, you need to declare the new controller as the default controller for Rule Team Server. This is done by defining the teamserver.controller.class configuration parameter in a new preferences.properties file, which will be bundled in the root directoy of the JAR file containing the controller class.

Listing 2. preferences.properties file setting the session controller
ilog.rules.teamserver.controller.class=continuousbuild.BuildController

Package and deploy

You will now repackage the Rule Team Server EAR file with the new controller class and preferences file, using an Ant task provided in the sample:

  1. In Rule Studio, open the file build/build.xml.
  2. Set the value of the ILOG_RULES_HOME property to the root directory of your JRules installation.
  3. From the outline, right-click package-authoring-server-ear and select Run As > 1 Ant Build, as shown in Figure 4.
    Figure 4. Packaging authoring server
    Packaging authoring server

    The authoring server EAR is now ready to be deployed to the Authoring Server node:

  4. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  5. Click Install and choose the file build/out/authoring-server.ear from your hard drive.
  6. Click Next, select Detailed installation, and click Next.
  7. Click Continue.
  8. Go to Step 2: Map modules to servers and select the AuthoringServer node in the clusters and servers list, check the checkbox below, and click Apply.
  9. Go to Step 6: Map virtual hosts for Web modules and select the teamserver web module. Select authoring_host as the virtual host.
  10. Go to Step 8: Map security roles to users or groups.
  11. Select the rtsUser, rtsConfigManager, rtsAdministrator and rtsInstaller roles and click Map Users. On the Search and Select Users page, select jrulesAdmin from the Available list and click the right arrow to move it to the Selected list, then click OK.
  12. Select the rtsUser role and click Map Users. On the Search and Select Users page, select jrulesAuthor from the Available list and click the right arrow to move it to the Selected list, then click OK.
  13. Click Next, then Finish.

Now you need to set the classloader policy of Rule Team Server to parent last so that classes contained in the EAR are loaded before the ones in the application server.

  1. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  2. Click the Authoring Server row.
  3. Click Manage Modules and select the teamserver module.
  4. Change class loader order to Classes loaded with local class loader first (parent last).
  5. Click OK and save your changes.
  6. Start the application.

Implementing the build server

Build Server is implemented using an MDB, which will receive commit notifications from Authoring Server, as explained in the previous section. If the latest build was run more than three minutes before the current time, a new build is triggered on the Rule Team Server instance hosted by Build Server. Our build operation consists of taking all tests suites of all rule projects in the repository and executing them, one after the other. Before executing tests suites, a RuleApp executable is generated and the ruleset execution takes place. If an error occurs, an email is sent to the build administrator with some details about the failure. The email body will provide a hyperlink to each failing test suite report, allowing the administrator to easily see the details of the failure within Rule Team Server, as shown in Figure 5.

Figure 5. Failing test suite report
Failing test suite report

Write the message driven bean

We define the Java class BuildMessageBean as an MDB, using EJB 3.0 annotations. Listing 3 shows the implementation of the onMessage method: each message processed contains a reference to the project element that was committed from Authoring Server. After connecting to Rule Team Server through an IlrSession, we look at the status of the continuousbuild.ongoing custom configuration parameter in the repository. If set to true, it means that another build is ongoing, triggered by a previous message. Otherwise, we check the value of the continuousbuild.buildDate custom configuration parameter in the Rule Team Server database. When such notification is received, if the latest build was run more than three minutes before the current time, a new build is triggered on the Rule Team Server instance hosted by Build Server. If the build fails, an email is sent containing the error output produced by the build.

Listing 3. Receive commit notifications via JMS and trigger a build if needed
public class BuildMessageBean implements MessageDrivenBean, MessageListener, Constants {

  . . .

  public void onMessage(Message message) {
	try {
	  CommitInfo commitInfo = (CommitInfo) ((ObjectMessage) message).getObject();
      IlrElementHandle element = commitInfo.getElement();
      IlrBaseline workingBaseline = commitInfo.getWorkingBaseline();
      String buildServerURL = commitInfo.getBuildServerURL();
      // Connects to Build Server
      IlrRemoteSessionFactory factory = new IlrRemoteSessionFactory();
      factory.connect("jrulesBuilder", "jrulesBuilder", 
                      buildServerURL, "jdbc/ilogDataSource");
      IlrSession session = factory.getSession();
      if (!"true".equals(IlrSettings.getGlobalSetting(session,
                                                      "continuousbuild.ongoing"))) {
        String lastBuildDateStr
                = IlrSettings.getGlobalSetting(session, "continuousbuild.buildDate");
        SimpleDateFormat sdf = new SimpleDateFormat();
        Date lastBuildDate
          = (lastBuildDateStr == null) ? null : sdf.parse(lastBuildDateStr);
        if (lastBuildDate == null 
            || (System.currentTimeMillis() - lastBuildDate.getTime() > 1000 * 60 * 3)) {
          IlrSettings.saveGlobalSetting(session, "continuousbuild.ongoing", "true");
          try {
            StringWriter sw = new StringWriter();
            PrintWriter out = new PrintWriter(sw);
            boolean result = build(session, element, workingBaseline, out);
            if (!result) {
              String text = sw.toString();
              sendEmail(session, text);
            }
          } catch (MessagingException e) {
            Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
          } finally {
            IlrSettings.saveGlobalSetting(session,
                                          "continuousbuild.buildDate",
                                          sdf.format(new Date()));
            IlrSettings.removeGlobalSetting(session, "continuousbuild.ongoing");
          }
        }
      }
    } catch (Exception e) {
      Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
    }
  }

  . . .

}

As shown in Listing 4, the actual build operation lies in the build method, which will run all test suites and, if any error is encountered, will print the details of the error in the given PrintWriter. If the error is encountered during the execution of a test suite, a link to the test suite report is printed. Otherwise we simply print the exception stack trace.

In any case, if the build fails, the reference of the commit that triggered the build is printed, including: version, type and name of the committed element, as well as a hyperlink to its details page in Authoring Server.

Listing 4. Build and print errors if any
  private boolean build(IlrSession session, 
                        IlrElementHandle handle, 
                        IlrBaseline workingBaseline, 
                        PrintWriter out) {
    boolean result = true;
    IlrPermanentLinkHelper helper = new IlrPermanentLinkHelper(session);
    try {
      List<IlrScenarioSuiteReport> errorReports = runAllTestSuites(session);
      if (errorReports != null) {
        result = false;
        out.println("<h1>Build failed</h1>");
        out.println("<p>Some errors were found while executing the "
                    +"test suites of the Rule Team Server repository.");
        out.println("You will find detailed information in the report(s) below:");
        for (IlrScenarioSuiteReport report : errorReports) {
          out.println("<li>");
          String permalink = helper.getElementURL(report, null);
          out.println("<a href=" + permalink + ">" + report.getName() + "</a>");
          out.println("</li>");
        }
      }
    } catch (Exception e) {
      result = false;
      out.println("Exceptions raised while executing test suites:");
      out.println("<pre>");
      e.printStackTrace(out);
      out.println("</pre>");
    }
    if (!result) {
      try {
    	session.setWorkingBaseline(workingBaseline);
        IlrProjectElement element 
          = (IlrProjectElement) session.getElementDetails(handle);
        IlrElementVersion version = session.getElementVersion(element);
        out.println("<p>Last change in repository:");
        String projectName = element.getProject().getName();
        out.println("<li>Artifact: <a href=\""
        		+ helper.getElementDetailsURL(projectName, element)
        		+ "\">"
        		+ element.getName() 
        		+ "</a>");
        out.println("<li>Version: " + version.getMajor() + "." + version.getMinor());
        out.println("<li>Author: " + version.getCreator());
        out.println("<li>Comment: " 
                    + ((version.getComment() == null) ? "" : version.getComment()));
      } catch (Exception e) {
        Logger.getLogger("continuousbuild").log(Level.SEVERE, e.getMessage(), e);
      }
    }
    return result;
  }

The actual execution of the tests is done through the runAllTestSuites method. All the test suites found in the repository are executed one after the other. In case of a failure, failing reports are returned so that they can be referenced in the report email.

Listing 5. Run all test suites and get a list of failing reports
  private List<IlrScenarioSuiteReport> runAllTestSuites(IlrSession session)
          throws IlrApplicationException {
    EClass serverClass = session.getBrmPackage().getServer();
    List servers
      = session.findElements(new IlrDefaultSearchCriteria(serverClass));
    IlrServer server = (IlrServer)servers.get(0);
    List<IlrRuleProject> projects = IlrSessionHelper.getProjects(session);
    List<IlrScenarioSuiteReport> errorReports = null;
    for (IlrRuleProject project : projects) {
      IlrBaseline current = project.getCurrentBaseline();
      session.setWorkingBaseline(current);
      EClass testSuiteClass = session.getBrmPackage().getTestSuite();
      List<IlrTestSuite> testSuites
              = session.findElements(new IlrDefaultSearchCriteria(testSuiteClass));
      for (IlrTestSuite testSuite : testSuites) {
        IlrElementHandle reportHandle 
          = session.executeScenarioSuite(testSuite, server, null);
        IlrScenarioSuiteReport report
                = (IlrScenarioSuiteReport) session.getElementDetails(reportHandle);
        if (report.isArchiveErrors() 
            || report.getNbErrors() > 0 
            || report.getNbFailures() > 0) {
          if (errorReports == null) {
            errorReports = new ArrayList<IlrScenarioSuiteReport>();
          }
          errorReports.add(report);
        }
      }
    }
    return errorReports;
  }

Finally the sendMail method will send an email with the failing report, using the JavaMail API.

Listing 6. Send email with error details
  private void sendEmail(IlrSession session, String text) throws MessagingException {
    Properties props = new Properties();
    props.put("mail.smtp.host",
              IlrSettings.getGlobalSetting(session, "continuousbuild.email.smtphost"));
    props.put("mail.from", 
              IlrSettings.getGlobalSetting(session, "continuousbuild.email.from"));
    MimeMessage mimeMessage = new MimeMessage(Session.getInstance(props));
    mimeMessage.setRecipients(javax.mail.Message.RecipientType.TO,
    		IlrSettings.getGlobalSetting(session, "continuousbuild.email.to"));
    mimeMessage.setSubject("Errors while building rule projects");
    mimeMessage.setSentDate(new Date());
    mimeMessage.setContent(text, "text/html");
    Transport.send(mimeMessage);
  }

Figure 6 gives an example of what the email will look like.

Figure 6. Failing report email
Failing report email

Declare the JMS queue

Before deploying the build server application, you need to create the JMS queue that will enable communication between authoring server and build server. The steps below describe how to create a bus, then a queue connection factory, the actual queue as well as activation specification of the queue.

Create a bus

  1. From the WebSphere console, go to Service Integration => Buses.
  2. Click New, set the bus name to ContinuousBuildBus and uncheck Bus security.
  3. Click Next and Finish, then save your changes.
  4. Click ContinuousBuildBus, then click Bus members.
  5. Click Add and select BuildServerNode:BuildServer.
  6. Click Next until the Finish panel appears.
  7. Click Finish and save your changes.

Create a queue connection factory

  1. Go to Resources => JMS => Queue connection factories.
  2. Change the scope to Cell=RuleTeamServerCell.
  3. Click New, select Default Messaging provider, then click OK.
  4. Set the name to ContinuousBuildQueueConnectionFactory and the JNDI name to jms/ContinuousBuildQueueConnectionFactory.
  5. Select ContinuousBuildBus as the Bus name.
  6. Click OK, then save your changes.

Create a queue

  1. Go to Resources => JMS => Queues.
  2. Change scope to Cell=RuleTeamServerCell.
  3. Click New, select Default Messaging provider, then click OK.
  4. Set the name to ContinuousBuildQueue and the JNDI name to jms/ContinuousBuildQueue.
  5. Select ContinuousBuildBus as the bus name.
  6. Under Queue Name, select Create Service Integration Bus Destination.
  7. Set the Identifier field to ContinuousBuildQueueSpace.
  8. Click Next twice and Finish, then save your changes.

Create an activation specification

  1. Go to Resources => JMS => Activation specifications.
  2. Change scope to Cell=RuleTeamServerCell.
  3. Click New, select Default Messaging provider, then click OK.
  4. Set the name to ContinuousBuildActivationSpec and the JNDI name to eis/ContinuousBuildActivationSpec.
  5. Set jms/ContinuousBuildQueue as the Destination JNDI name.
  6. Select ContinuousBuildBus as the bus name.
  7. Click OK, then save your changes.

Package and deploy

You can now package Build Server:

  1. Open build/build.xml.
  2. Run the target package-build-server-ear. This will package the MDB defined above, as well as an instance of Rule Team Server.

The build server EAR is now ready to be deployed to the Build Server node:

  1. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  2. Click Install and choose the file build/out/build-server.ear from your hard drive.
  3. Click Next, select Detailed installation, and click Next again.
  4. Go to Step 2: Map modules to servers and select the BuildServer node in the clusters and servers list. Check both the buildserver.jar and teamserver modules, and click Apply.
  5. Go to Step 6: Bind listeners for message-driven beans. In the Listener Bindings column, select Activation Specification, set the Target resource JNDI name to eis/ContinuousBuildActivationSpec. Depending on your WebSphere install, you may get a warning when going to the next step. If so, you can safely ignore it.
  6. Go to Step 7: Map virtual hosts for Web modules. Select the teamserver module, and set the virtual host to build_host.
  7. Go to Step 9: Map security roles to users or groups.
  8. Select the rtsUser and rtsConfigManager roles and click Map Users. On the Search and Select Users page, select jrulesBuilder from the Available list and click the right arrow to move it to the Selected list. Click OK.
  9. Go to Step 11: Summary. You should see a screen similar to the one in Figure 7.
  10. Click Finish and save your changes.

Next you must set the classloader policy of Rule Team Server to parent last so that classes contained in the EAR are loaded before the ones in the application server:

  1. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  2. Click the Build Server row.
  3. Click Manage Modules.
  4. Click the teamserver module.
  5. Change class loader order to Classes loaded with local class loader first (parent last).
  6. Click OK and save your changes.
  7. Start the application.
Figure 7. Build Server deployment summary
Build Server deployment summary

Implementing the execution server

Execution Server is an enterprise application gathering three JRules components: the Rule Execution Server console and the XU (eXecution Unit), both part of Rule Execution Server, and the SSP (Scenario Service Provider), part of DVS. The SSP is repackaged with the XOM of the rule application we want to execute (classes of the loanvalidation-xom project in our sample case).

Register Rule Execution Server MBean descriptors

Prior to using Rule Execution Server, you must register the MBean descriptors in the server classpath, in order declare all of the attributes, operations, and notifications for a Rule Execution Server MBean:

  1. In the left navigation, open Servers => Server Types => WebSphere application servers. In the Application servers pane, click Execution Server.
  2. Under Server Infrastructure, expand Java and Process Management and click Process definition.
  3. Under Additional Properties, click Java Virtual Machine.
  4. In the Classpath field, add <JRules dir>/executionserver/lib/jrules-mbean-descriptors.jar.
  5. Click OK and save your changes.

Package and deploy

Now you need to package Execution Server by opening build/build.xml, and running the target called package-execution-server-ear. This will package the Rule Execution Server console, the XU and the SSP along with the loanvalidation-xom classes in a single EAR file.

You can then perform the deployment, as described below:

  1. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  2. Click Install and choose the file <continuous build workspace>/continuousbuild/build/out/ execution-server.ear from your hard drive.
  3. Click Next, select Detailed installation, and click Continue.

    Note: Some warnings may appear when deploying the Rule Execution Server application, that you can safely ignore.

  4. Go to Step 2: Map modules to servers and select the ExecutionServer node in the clusters and servers list, check the three checkboxes below (for the Rule Execution Server, SSP, XU modules), and click Apply.
  5. Go to Step 6: Provide JNDI names for JCA objects and set the Name field to xu_cf and the JNDI name to eis/XUConnectionFactory. Click Next. A warning should appear, that you can ignore. Click Continue.
  6. Go to Step 7: Map resource references to resources. In the javax.resource.cci.ConnectionFactory section, set the Target Resource JNDI Name to eis/XUConnectionFactory, and in the javax.sql.DataSource section, set it to jdbc/resdatasource.
  7. Go to Step 8: Map virtual hosts for Web modules and set execution_host as the virtual host for both ILOG Rule Execution Server Console and ILOG Rule Execution Server Console web modules.
  8. Go to Step 10: Map security roles to users or groups and select the resAdministrators, resDeployers and resMonitors roles, then click Map Users.
  9. On the Search and Select Users page, select jrulesBuilder from the Available list and click the right arrow to move it to the selected list. Click OK.
  10. Click Next, then Finish.

Now set the classloader policy of the Rule Execution Server console and SSP to parent last so that classes contained in the EAR are loaded before the ones in the application server

  1. From the WebSphere admin console, go to Applications => Application Types => WebSphere enterprise application.
  2. Click the Execution Server row.
  3. Click Manage Modules.
  4. Click the ILOG Rule Execution Server Console module.
  5. Change class loader order to Classes loaded with local class loader first (parent last).
  6. Click OK.
  7. Click Manage Modules.
  8. Click the ILOG Scenario Service Provider module.
  9. Change class loader order to Classes loaded with local class loader first (parent last).
  10. Click OK and save your changes.
  11. Start the application.

Running the sample application

In this section, we'll step through running the sample applicaiton.

Preparing Rule Execution Server

You first need to determine the port on which the Rule Execution Server console is running:

  1. Open the deployment manager admin console.
  2. Open Environment => Virtual hosts.
  3. Click execution_host.
  4. In the Additional Properties section, click Host Aliases.
  5. The port is the one displayed in the first row.

You can then run Installation Manager wizard, which will open the first time you launch the Rule Execution Server console:

  1. Open a web browser to http://execution.example.com:<PORT>/res, where <PORT> is the value you found in the previous step.
  2. Enter jrulesBuilder as the username and password.
  3. Click Sign In, then click Next, then Next again.
  4. Click Execute.
  5. Click Finish, then Sign Out.

Preparing Rule Team Server

You first need to determine the port on which the Rule Team Server console is running:

  1. Open the deployment manager admin console.
  2. Open Environment => Virtual hosts.
  3. Click authoring_host.
  4. In the Additional Properties section, click Host Aliases.
  5. The port is the one displayed in the first row.

You can then run Installation Manager wizard which will open the first time you will launch the Rule Team Server console:

  1. Open a web browser and navigate to the link http://authoring.example.com:<PORT>/authoringserver where <PORT> is the value you found in the previous step.
  2. Enter jrulesAdmin as the username and password.
  3. Click Next, then click Generate SQL.
  4. Click Next on the next four pages, then click New and select Custom Name in the list box.
  5. Set the name to continuousbuild.buildserver.url and set the value to the Rule Team Server URL running on BuildServer (http://build.example.com:<PORT>/buildserver), and click Apply.
  6. Click New and select Custom Name in the list box.
  7. Set the name to continuousbuild.email.smtphost and set the value to the SMTP host you want to use for sending build failure emails, and click Apply.
  8. Click New and select Custom Name in the list box.
  9. Set name to continuousbuild.email.to and set the value to the email address you want to use to send build notifications and click Apply.
  10. Click New and select Custom Name in the list box.
  11. Set name to continuousbuild.email.from and set the value to the reply email address you want to set for build server notifications and click Apply.
  12. Click Finish.
  13. Click OK.

Publish sample project and test suite

  1. Open Rule Studio with the continuousbuild workspace.
  2. Select the project loanvalidation-rules.
  3. Right-click and select Rule Team Server => Connect.
  4. Set both the username and password to jrulesAdmin.
  5. Set the URL to http://authoring.example.com:<authoringserver_port>/authoringserver.
  6. Click Connect.
  7. In the Project configuration section, select Create a new project on Rule Team Server.
  8. Click Finish.

Next you will create a test suite and a server to execute it:

  1. Log in to Rule Team Server (http://authoring.example.com:<authoringserver_port>/authoringserver) as jrulesAdmin/jrulesAdmin.
  2. On the Home page, select loanvalidation-rules as the current project.
  3. Click the Compose tab.
  4. Select Test suite and click OK.
  5. Set Loanvalidation Tests as the name of the test suite.
  6. Go to Steps 3: Scenarios, and upload the sample Excel file containing scenarios: <continuousbuild workspace>/continuousbuild/resources/loanvalidation-scenarios.xls.
  7. Click Finish and Run.
  8. Since no server has been created, click Configure a new one.
  9. Call the server My Test Server.
  10. Set http://execution.example.com:<executionserver_port>/res as the URL.
  11. Set jrulesBuilder/jrulesBuilder as the user name and password and click OK.
  12. Click Run.
  13. After a few seconds, Rule Team Server should display an execution report, which means that your install is valid.

You can now give the whole system a try:

  1. Log in to Rule Team Server (http://authoring.example.com:<authoringserver_port>/authoringserver) as jrulesAuthor/jrulesAuthor.
  2. Open the loanvalidation-rules project.
  3. Click the Explore tab and open the validation/loan directory.
  4. Selet the checkAmount rule in the right table.
  5. Click the Quick Edit icon and change the maxAmount variable to 1200000.
  6. Click Save.
  7. After a few seconds, you should receive an email reporting a build failure!.

Taking it a step further

In this section, we'll look at some additional enhancements you may want to make.

Add criteria to trigger a build

In our sample, we trigger a build each time a business rule is created or modified, and if no previous build is still running. You may want to consider some other criteria, in order to limit the load on build server. For example, you may:

  • Trigger a build after a certain number of commits.
  • Define a minimal duration between two builds.
  • Run only the test suites impacted by the modified rule. Note that this may be a difficult exercise depending on the structure of your rule projects (test suites using ruleset extractors, ruleflow using a dynamic select to execute rules, and so on).

Add a tab to view the status of the builds

You may want to add a custom tab in the Rule Team Server console in order to display information about the builds: current status, start date, duration, links on test suite reports, and so on. For more information, refer to the Customizing Rule Team Server topic in the Information Center.

Extend the concept of build to other functionalities of Rule Team Server

In this article, we define a build operation as the execution of the tests suites of the repository. You may want to extend that concept to HTML report generation (see IlrReportEngine) or RuleApp deployment to Rule Execution Server (see IlrSession.deployRuleAppArchive).

Disable some functions in Authoring Server

Since test suite executions are handled by Build Server, you may want to prevent the Authoring Server user from launching the test suites by themselves. You can do this by securing your rule projects and defining permissions for test suites.

Conclusion

In this article, you learned how to implement a continuous build system for Rule Team Server and Decision Validation Services, using some of the customization capabilities of Rule Team Server. You also learned how to configure and deploy such a system on three machines, using a sample application. Finally, you learned how to extend the sample to become production-ready to match the requirements and constraints of your business rules repository with respect to build.

Acknowledgments

Thanks to Thierry Kormann for his early thoughts on the emerging need for a continuous build for BRMS, and thanks to Albin Carpentier for his tips and tricks for JMS and Rule Execution Server set-up.


Download

DescriptionNameSize
Code samplecontinuousbuild.zip48KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Business process management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Business process management, WebSphere
ArticleID=645753
ArticleTitle=Implementing a continuous build system for WebSphere ILOG Business Rule Management Systems
publish-date=04082011