<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.infinite-erp.co.id/index.php?action=history&amp;feed=atom&amp;title=How_to_develop_a_DAL_background_process</id>
	<title>How to develop a DAL background process - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.infinite-erp.co.id/index.php?action=history&amp;feed=atom&amp;title=How_to_develop_a_DAL_background_process"/>
	<link rel="alternate" type="text/html" href="https://wiki.infinite-erp.co.id/index.php?title=How_to_develop_a_DAL_background_process&amp;action=history"/>
	<updated>2026-04-06T21:43:58Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.31.1</generator>
	<entry>
		<id>https://wiki.infinite-erp.co.id/index.php?title=How_to_develop_a_DAL_background_process&amp;diff=258&amp;oldid=prev</id>
		<title>Wikiadmin: Created page with &quot;== 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''': ''Sa...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.infinite-erp.co.id/index.php?title=How_to_develop_a_DAL_background_process&amp;diff=258&amp;oldid=prev"/>
		<updated>2018-10-15T13:39:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;== Objective ==  A background process is a process which runs at regular intervals. For this how-to we will develop a background process for the &amp;#039;&amp;#039;&amp;#039;following scenario&amp;#039;&amp;#039;&amp;#039;: &amp;#039;&amp;#039;Sa...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Objective ==&lt;br /&gt;
&lt;br /&gt;
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.''&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:obexapp_CreateBackground1.png|center|700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 [[How_to_create_a_Java_Based_Process|howto]].&lt;br /&gt;
&lt;br /&gt;
For a generic description of java processes see this wiki page: [[Processes]].&lt;br /&gt;
&lt;br /&gt;
== Example Module ==&lt;br /&gt;
&lt;br /&gt;
This howto is supported by an example module which shows example of the code shown and discussed in this howto. &lt;br /&gt;
&lt;br /&gt;
The example module is available through the Central Repository (See 'Client Application Examples'), for more information see the [[Projects/ExamplesClientApplication|Examples Client Application]] project page.&lt;br /&gt;
&lt;br /&gt;
For your specific development you should create a new module. Please follow the [[How_To_Create_and_Package_a_Module | How to create and package a module]] section to create a new module.&lt;br /&gt;
&lt;br /&gt;
== Definition within the application dictionary ==&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:obexapp_CreateBackground2.png|center|700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following fields are vital for the definition of a background process (for more information see the [[ERP/3.0/Developers_Guide/Database_Model/org.openbravo.model.ad.ui/AD_Process |AD_Process]] table description):&lt;br /&gt;
* '''Module''' - your custom module that this new background process will belong too; note that this will consequently indicate the location on the hard drive and the package it must belong to&lt;br /&gt;
* '''Search Key''' - unique identifier of the process; a good practice is to use the class name&lt;br /&gt;
* '''Name''' - a user friendly name of the process&lt;br /&gt;
* '''UI Pattern''' - should be set to Manual since Openbravo ERP does not need to generate any UI windows&lt;br /&gt;
* '''Background''' - indicates that this process is a background process which consequently also displays the '''Java Class Name''' field&lt;br /&gt;
* '''Java Class Name''' - the full specification of the class name including the package (this package must follow the package structure of your module specified above)&lt;br /&gt;
&lt;br /&gt;
Save!&lt;br /&gt;
&lt;br /&gt;
== Process and DalBaseProcess ==&lt;br /&gt;
&lt;br /&gt;
Before continuing, we need to decide how our background process will perform the database operations. We have two options:&lt;br /&gt;
# 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''.&lt;br /&gt;
# 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''. &lt;br /&gt;
&lt;br /&gt;
Since the first method will eventually become deprecated due to database dependency, the second one is the prudent option to take.&lt;br /&gt;
&lt;br /&gt;
Some understanding of the Hibernate Criteria API is beneficial when using the DAL. See [http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querycriteria.html here] for a detailed description of this API. &lt;br /&gt;
&lt;br /&gt;
Still, the Data Access Layer is discussed in several other articles and howtos. In particular, the [[Data_Access_Layer | Data Access Layer reference manual]] should be your starting point.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
The example module implements the background process in the ''modules/org.openbravo.client.application.examples/src/org.openbravo.client.application.examples.ProductRevenueCalculation.java'' class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;// assign the background process to a package that belongs to the &lt;br /&gt;
// main package of the module this custom development belongs to  &lt;br /&gt;
package org.openbravo.client.application.examples;&lt;br /&gt;
 &lt;br /&gt;
import java.math.BigDecimal;&lt;br /&gt;
import java.util.Calendar;&lt;br /&gt;
&lt;br /&gt;
import org.hibernate.Criteria;&lt;br /&gt;
import org.hibernate.criterion.Projections;&lt;br /&gt;
import org.hibernate.criterion.Restrictions;&lt;br /&gt;
import org.openbravo.dal.service.OBCriteria;&lt;br /&gt;
import org.openbravo.dal.service.OBDal;&lt;br /&gt;
import org.openbravo.model.common.order.OrderLine;&lt;br /&gt;
import org.openbravo.model.common.plm.Product;&lt;br /&gt;
import org.openbravo.scheduling.ProcessBundle;&lt;br /&gt;
import org.openbravo.scheduling.ProcessLogger;&lt;br /&gt;
import org.openbravo.service.db.DalBaseProcess;&lt;br /&gt;
import org.quartz.JobExecutionException;&lt;br /&gt;
&lt;br /&gt;
// the background process needs to extend DalBaseProcess since&lt;br /&gt;
// we will be using DAL objects to perform database operations&lt;br /&gt;
public class ProductRevenueCalculation extends DalBaseProcess {&lt;br /&gt;
&lt;br /&gt;
  static int counter = 0;&lt;br /&gt;
&lt;br /&gt;
  private ProcessLogger logger;&lt;br /&gt;
&lt;br /&gt;
  // abstract method doExecute needs to be implemented and carries&lt;br /&gt;
  // with itself the ProcessBundle object deriving from Openbravo Quartz&lt;br /&gt;
  // scheduler&lt;br /&gt;
  public void doExecute(ProcessBundle bundle) throws Exception {&lt;br /&gt;
&lt;br /&gt;
    logger = bundle.getLogger(); // this logger logs into the LOG column of&lt;br /&gt;
    // the AD_PROCESS_RUN database table&lt;br /&gt;
    BigDecimal sumAmount = new BigDecimal(0);&lt;br /&gt;
&lt;br /&gt;
    logger.log(&amp;quot;Starting background product revenue calculation. Loop &amp;quot; + counter + &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // define time 6 months ago from today which is the timespan that our&lt;br /&gt;
    // calculation will consider&lt;br /&gt;
    Calendar timeSixMonthsAgo = Calendar.getInstance();&lt;br /&gt;
    timeSixMonthsAgo.add(Calendar.DAY_OF_MONTH, -180);&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
      // get all products that are sold (M_PRODUCT.ISSOLD = 'Y')&lt;br /&gt;
      final OBCriteria&amp;lt;Product&amp;gt; productList = OBDal.getInstance().createCriteria(Product.class);&lt;br /&gt;
      productList.add(Restrictions.eq(Product.PROPERTY_SALE, true));&lt;br /&gt;
&lt;br /&gt;
      logger.log(&amp;quot;No of products = &amp;quot; + productList.list().size() + &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      // loop through all products that are sold and calculate revenues&lt;br /&gt;
      // for each&lt;br /&gt;
      for (Product product : productList.list()) {&lt;br /&gt;
&lt;br /&gt;
        sumAmount = new BigDecimal(0);&lt;br /&gt;
&lt;br /&gt;
        // select lines from C_ORDERLINE table that match the product&lt;br /&gt;
        final Criteria orderLineList = OBDal.getInstance().createCriteria(OrderLine.class)&lt;br /&gt;
            .add(Restrictions.eq(OrderLine.PROPERTY_PRODUCT, product));&lt;br /&gt;
&lt;br /&gt;
        // filter out lines that belong to sales (as opposed to&lt;br /&gt;
        // purchase) and fit within the last six months&lt;br /&gt;
        //&lt;br /&gt;
        // when you want to filter on a property of an associated entity&lt;br /&gt;
        // then the property of that association needs an alias, see&lt;br /&gt;
        // here: http://www.javalobby.org/articles/hibernatequery102/&lt;br /&gt;
        orderLineList.createAlias(OrderLine.PROPERTY_SALESORDER, &amp;quot;order&amp;quot;)&lt;br /&gt;
            .add(Restrictions.eq(&amp;quot;order.salesTransaction&amp;quot;, true))&lt;br /&gt;
            .add(Restrictions.gt(&amp;quot;order.orderDate&amp;quot;, timeSixMonthsAgo.getTime()));&lt;br /&gt;
&lt;br /&gt;
        // Sum line amounts grouped by product&lt;br /&gt;
        orderLineList.setProjection(Projections.projectionList()&lt;br /&gt;
            .add(Projections.sum(OrderLine.PROPERTY_LINENETAMOUNT))&lt;br /&gt;
            .add(Projections.groupProperty(OrderLine.PROPERTY_PRODUCT)));&lt;br /&gt;
&lt;br /&gt;
        // due to grouping and sum operation there will really only be&lt;br /&gt;
        // one resulting record but in theory there could be more (a&lt;br /&gt;
        // list)&lt;br /&gt;
        for (Object o : orderLineList.list()) {&lt;br /&gt;
          // the query returns a list of arrays (columns of the query)&lt;br /&gt;
          final Object[] os = (Object[]) o;&lt;br /&gt;
          sumAmount = (BigDecimal) os[0];&lt;br /&gt;
          final Product p = (Product) os[1];&lt;br /&gt;
          logger.log(p.getName() + &amp;quot; Amount &amp;quot; + sumAmount + &amp;quot;\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        product.setDescription(&amp;quot;6 monthRevenue = &amp;quot; + sumAmount);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    } catch (Exception e) {&lt;br /&gt;
      // catch any possible exception and throw it as a Quartz&lt;br /&gt;
      // JobExecutionException&lt;br /&gt;
      throw new JobExecutionException(e.getMessage(), e);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compiling the application ==&lt;br /&gt;
&lt;br /&gt;
If using Eclipse, recompilation is not necessary if you have the &amp;quot;Build Automatically&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
If using the command line compilation, use the '''''ant smartbuild''''' to compile the application's manual code and deploy it to Tomcat context.&lt;br /&gt;
&lt;br /&gt;
Restart Tomcat.&lt;br /&gt;
&lt;br /&gt;
== Scheduling ==&lt;br /&gt;
&lt;br /&gt;
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 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:obexapp_CreateBackground4.png|center|700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following fields are important (for more information see the [[ERP/3.0/Developers_Guide/Database_Model/org.openbravo.model.ad.ui/AD_Process_Request |AD_Process_Request]] and [[ERP/3.0/Developers_Guide/Database_Model/org.openbravo.model.ad.ui/AD_Process_Scheduling |AD_Process_Scheduling]] table descriptions):&lt;br /&gt;
* '''Process''' - determines which background process to schedule. Only background processes are available in the dropdown&lt;br /&gt;
* '''Timing''' - there are several ways of scheduling a process based on the requirement if the process needs to be run once or repetitively. Use the ''Scheduled'' option for our purpose&lt;br /&gt;
* '''Frequency''' - how often does the process need to run. Based on your selection the fields below will change accordingly for you to be able to enter appropriate interval. Select ''02 - Every n minutes'' for us to be able to see the results immediately.&lt;br /&gt;
* '''Interval in Minutes''' - How many minutes apart should the process be run in case ''02 - Every n minutes'' was selected above. Enter ''1''.&lt;br /&gt;
&lt;br /&gt;
Save the record and click on the '''Schedule Process''' button in order for the process to finally get scheduled. &lt;br /&gt;
&lt;br /&gt;
{{(!) | 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.}}&lt;br /&gt;
&lt;br /&gt;
== Monitoring ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:obexapp_CreateBackground5.png|center|700px]]&lt;br /&gt;
&lt;br /&gt;
== The Result ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:obexapp_dalbackgroundprocess_result.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HowTo]]&lt;/div&gt;</summary>
		<author><name>Wikiadmin</name></author>
		
	</entry>
</feed>