View source | Discuss this page | Page history | Printable version   
Toolbox
Main Page
Upload file
What links here
Recent changes
Help

PDF Books
Add page
Show collection (0 pages)
Collections help

Search

How to develop a DAL background process

Contents

Objective

A background process is a process which runs at regular intervals. For this how-to we will develop a background process for the following scenario: Say our customer wants to have sales information for the last 6 months of each product in the description field.

A background process needs to (re)calculate the sales numbers on a regular basis and save them into the Description field of each product that is marked as being sold. Our main Product window's tab should end up similar to:


Obexapp CreateBackground1.png


Consider that this is a simple exercise and that we are demonstrating how a background process is developed. The above example would probably better be implemented by first adding a new field to the M_PRODUCT database table that would hold this information. However, for the purpose of this exercise, we will just store it in the Description field.

As a side note: in this howto we will show how a java process can be implemented as a background process. A java process can however also be called directly from the user interface and have a user interface which allows entering parameters. This is described in this howto.

For a generic description of java processes see this wiki page: Processes.

Example Module

This howto is supported by an example module which shows example of the code shown and discussed in this howto.

The example module is available through the Central Repository (See 'Client Application Examples'), for more information see the Examples Client Application project page.

For your specific development you should create a new module. Please follow the How to create and package a module section to create a new module.

Definition within the application dictionary

Background processes are defined within the Application Dictionary || Report and Process window. Use the System Administrator role to create a new record as indicated below:


Obexapp CreateBackground2.png


The following fields are vital for the definition of a background process (for more information see the AD_Process table description):

Save!

Process and DalBaseProcess

Before continuing, we need to decide how our background process will perform the database operations. We have two options:

  1. Use the XSQL file that will get converted to a Java class by the SQLC core library upon runtime. If this option is used, your background Java class should implement the Process interface and implement the execute method to perform our tasks. Find this interface in src/org/openbravo/scheduling/Process.java.
  2. Use the new Data Access Layer which provides mid-tier POJOs through which we can manipulate database tables. If this method is used, your background Java class must extend the DalBaseProcess class and implement the doExecute method that performs your task. This will give it access to the correct data context provided by DAL and at the same time take care of authentication and privileges. Find the abstract class in src/org/openbravo/service/db/DalBaseProcess.java.

Since the first method will eventually become deprecated due to database dependency, the second one is the prudent option to take.

Some understanding of the Hibernate Criteria API is beneficial when using the DAL. See here for a detailed description of this API.

Still, the Data Access Layer is discussed in several other articles and howtos. In particular, the Data Access Layer reference manual should be your starting point.

Implementation

The example module implements the background process in the modules/org.openbravo.client.application.examples/src/org.openbravo.client.application.examples.ProductRevenueCalculation.java class:

// assign the background process to a package that belongs to the 
// main package of the module this custom development belongs to  
package org.openbravo.client.application.examples;
 
import java.math.BigDecimal;
import java.util.Calendar;
 
import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openbravo.dal.service.OBCriteria;
import org.openbravo.dal.service.OBDal;
import org.openbravo.model.common.order.OrderLine;
import org.openbravo.model.common.plm.Product;
import org.openbravo.scheduling.ProcessBundle;
import org.openbravo.scheduling.ProcessLogger;
import org.openbravo.service.db.DalBaseProcess;
import org.quartz.JobExecutionException;
 
// the background process needs to extend DalBaseProcess since
// we will be using DAL objects to perform database operations
public class ProductRevenueCalculation extends DalBaseProcess {
 
  static int counter = 0;
 
  private ProcessLogger logger;
 
  // abstract method doExecute needs to be implemented and carries
  // with itself the ProcessBundle object deriving from Openbravo Quartz
  // scheduler
  public void doExecute(ProcessBundle bundle) throws Exception {
 
    logger = bundle.getLogger(); // this logger logs into the LOG column of
    // the AD_PROCESS_RUN database table
    BigDecimal sumAmount = new BigDecimal(0);
 
    logger.log("Starting background product revenue calculation. Loop " + counter + "\n");
 
    // define time 6 months ago from today which is the timespan that our
    // calculation will consider
    Calendar timeSixMonthsAgo = Calendar.getInstance();
    timeSixMonthsAgo.add(Calendar.DAY_OF_MONTH, -180);
 
    try {
      // get all products that are sold (M_PRODUCT.ISSOLD = 'Y')
      final OBCriteria<Product> productList = OBDal.getInstance().createCriteria(Product.class);
      productList.add(Restrictions.eq(Product.PROPERTY_SALE, true));
 
      logger.log("No of products = " + productList.list().size() + "\n");
 
      // loop through all products that are sold and calculate revenues
      // for each
      for (Product product : productList.list()) {
 
        sumAmount = new BigDecimal(0);
 
        // select lines from C_ORDERLINE table that match the product
        final Criteria orderLineList = OBDal.getInstance().createCriteria(OrderLine.class)
            .add(Restrictions.eq(OrderLine.PROPERTY_PRODUCT, product));
 
        // filter out lines that belong to sales (as opposed to
        // purchase) and fit within the last six months
        //
        // when you want to filter on a property of an associated entity
        // then the property of that association needs an alias, see
        // here: http://www.javalobby.org/articles/hibernatequery102/
        orderLineList.createAlias(OrderLine.PROPERTY_SALESORDER, "order")
            .add(Restrictions.eq("order.salesTransaction", true))
            .add(Restrictions.gt("order.orderDate", timeSixMonthsAgo.getTime()));
 
        // Sum line amounts grouped by product
        orderLineList.setProjection(Projections.projectionList()
            .add(Projections.sum(OrderLine.PROPERTY_LINENETAMOUNT))
            .add(Projections.groupProperty(OrderLine.PROPERTY_PRODUCT)));
 
        // due to grouping and sum operation there will really only be
        // one resulting record but in theory there could be more (a
        // list)
        for (Object o : orderLineList.list()) {
          // the query returns a list of arrays (columns of the query)
          final Object[] os = (Object[]) o;
          sumAmount = (BigDecimal) os[0];
          final Product p = (Product) os[1];
          logger.log(p.getName() + " Amount " + sumAmount + "\n");
        }
        product.setDescription("6 monthRevenue = " + sumAmount);
      }
 
    } catch (Exception e) {
      // catch any possible exception and throw it as a Quartz
      // JobExecutionException
      throw new JobExecutionException(e.getMessage(), e);
    }
  }
}

Compiling the application

If using Eclipse, recompilation is not necessary if you have the "Build Automatically" option enabled. One only needs to be careful to make sure that the modules/org.openbravo.client.application.examples/src folder is added to the Java Build Path of the main openbravo project.

If using the command line compilation, use the ant smartbuild to compile the application's manual code and deploy it to Tomcat context.

Restart Tomcat.

Scheduling

In order for a background process to be executed, it first needs to be scheduled. Using the Openbravo Client Admin role (so not the System Admin role) navigate to General Setup || Process Scheduling || Process Request window and enter a new record


Obexapp CreateBackground4.png


The following fields are important (for more information see the AD_Process_Request and AD_Process_Scheduling table descriptions):

Save the record and click on the Schedule Process button in order for the process to finally get scheduled.

Bulbgraph.png   Note that you need use the Openbravo Admin role in order for the background process to have access to products of BigBazaar. The client of the role that enters the background process request is used to determine access privileges.

Monitoring

To see the process executions, the status and the log it generated, use the General Setup || Process Scheduling || Process Monitor window. After a minute or two of scheduling your process you should be able to see entries related to the executions of your new process.


Obexapp CreateBackground5.png

The Result

To be able to get meaningful results, you might need to enter and complete a Sales Order (Sales Management || Transactions || Sales Order) since the background process calculates revenues within the last 6 months and the demo database can contain records older than that. For example, enter a new Sales Order for a business partner, and enter a line for a certain product, then complete the sales order.

Then, navigate to the Master Data Management || Product window and find the product. After a minute or two when the process has recalculated the Description field, you should be able to see:


Obexapp dalbackgroundprocess result.png


Congratulations!

Retrieved from "http://wiki.openbravo.com/wiki/How_to_develop_a_DAL_background_process"

This page has been accessed 11,812 times. This page was last modified on 3 October 2011, at 13:10. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.