View source | Discuss this page | Page history | Printable version   

ERP 2.50:Developers Guide/How to develop a DAL background process/it

Contents

Obiettivo

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:


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.

Modulo

All new developments must belong to a module that is not the core module. Please follow the How to create and package a module section to create a new module.

Bulbgraph.png   Note: This article will assume you have created such a new module according to the article just mentioned.

Definizione nel Dizionario Applicazione

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:


CreateBackground2.png


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

Save!

Processo e 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.

Implementazione

The solution to our problem must lie within modules/org.openbravo.howtos/src/org/openbravo/howtos/background/ProductRevenueCalculation.java inline with our definition inside the application dictionary shown above. See commented solution below:

 
 // assign the background process to a package that belongs to the 
 // main package of the module this custom development belongs to  
 package org.openbravo.howtos.background;
 
 import java.math.BigDecimal;
 import java.util.Calendar;
 
 import org.hibernate.Criteria;
 import org.hibernate.criterion.Expression;
 import org.hibernate.criterion.Projections;
 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(Expression.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(
                                Expression.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(
                        Expression.eq("order.salesTransaction", true)).add(
                        Expression.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);
        }
    }
 }

Compilare l'applicazione

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.howtos/src folder is added to the Java Build Path of the main openbravo project.

If using the command line compilation, use the ant compile.development -Dtab=xxx to compile the application's manual code.

Restart Tomcat.

Schedulare

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


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.

Monitorare

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.


CreateBackground5.png

Il Risultato

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 BigBazaar contains records older than that. For example, enter a new Sales Order for McGiver business partner, entering 200 Cookies in the Lines tab, not forgetting to Complete the Sales Order.

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


CreateBackground1.png


Congratulations!

Retrieved from "http://wiki.openbravo.com/wiki/ERP_2.50:Developers_Guide/How_to_develop_a_DAL_background_process/it"

This page has been accessed 3,421 times. This page was last modified on 14 June 2011, at 11:04. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.