<?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=Processes</id>
	<title>Processes - 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=Processes"/>
	<link rel="alternate" type="text/html" href="https://wiki.infinite-erp.co.id/index.php?title=Processes&amp;action=history"/>
	<updated>2026-04-06T21:45:35Z</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=Processes&amp;diff=218&amp;oldid=prev</id>
		<title>Wikiadmin: Created page with &quot;== Processes ==  A process is a systematic series of actions directed to some end. Typically a process receives some parameters and taking them into account performs some acti...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.infinite-erp.co.id/index.php?title=Processes&amp;diff=218&amp;oldid=prev"/>
		<updated>2018-10-15T12:59:43Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;== Processes ==  A process is a systematic series of actions directed to some end. Typically a process receives some parameters and taking them into account performs some acti...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Processes ==&lt;br /&gt;
&lt;br /&gt;
A process is a systematic series of actions directed to some end. Typically a process receives some parameters and taking them into account performs some actions to obtain a result. Openbravo defines two main kinds of processes ''PL/SQL Processes'' and ''Java Processes''.&lt;br /&gt;
&lt;br /&gt;
All processes (as well as [[Reports|Reports]]) are managed from the same window: '''Application Dictionary || Report and Process'''.&lt;br /&gt;
&lt;br /&gt;
Once a process is defined it can be added to the menu to be called directly from there, it can be invoked through a button or it can be scheduled to be executed in the background.&lt;br /&gt;
&lt;br /&gt;
Background processes can be set as ''Prevent Concurrent Executions''. Before a process with this attribute is about to be executed, it is checked there are no other instances of the same process in execution at the same time, in this case another execution is aborted. &lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
When a process (PL/SQL or Java) or a Jasper Report is set as ''Standard'' a pop-up message is automatically generated  and displayed when invoking it, this message looks like this:&lt;br /&gt;
&lt;br /&gt;
[[Image:Ref-dialog-params.png]]&lt;br /&gt;
&lt;br /&gt;
This pop-up has a section with information about the process, this information is obtained from the ''Help'' field in the ''Report and Process'' tab.&lt;br /&gt;
&lt;br /&gt;
It also prompts for a number of parameters, and finally there are two buttons, ''OK'' to start the process and ''Cancel'' to close the pop-up and not to do anything else. In case the process did not require any parameter that section would be empty.&lt;br /&gt;
&lt;br /&gt;
When this kind of process requires parameters they must be defined in the'''Application Dictionary || Report and Process &amp;gt;&amp;gt;  Parameter''' tab.&lt;br /&gt;
&lt;br /&gt;
[[Image:Ref-dialog-params-def.png]]&lt;br /&gt;
&lt;br /&gt;
Parameters are defined in a very similar way than columns are, depending on the ''Reference'' field, the parameter is assigned the generated UI for it will be different.&lt;br /&gt;
&lt;br /&gt;
Let's overview some of the most important fields in this tab:&lt;br /&gt;
*'''DB Column name''': This is the name the parameter will be passed with to the process. When the process is going to use this parameter it will have to use this name. Please notice that Postgresql is case-sensitive. In case the parameter references an existing column in database (for example, it is a parameter of type search), then the ''DB Column name'' field must be cased the same way as the column in the Application Dictionary.&lt;br /&gt;
*'''Sequence''': It is a numeric value to order the parameter in the pop-up.&lt;br /&gt;
*'''Application Element''': It is the [[Element_and_Synchronize_Terminology|Element]] that will be used to get the label from, in this way parameters are translatable. Note that it is also possible to set or not this element as '''Centrally Maintained'''.&lt;br /&gt;
*'''Reference''', '''Reference Search Key''' and '''Validation''': These three fields works exactly like the same ones when defining references for columns.&lt;br /&gt;
*'''Range''': If it is checked, the pop-up will display two parameters in order to define a range, the first parameter will be named as specified in ''DB Column name'' field and the second one will have the same name with a ''_TO'' suffix.&lt;br /&gt;
&lt;br /&gt;
=== Defining Processes ===&lt;br /&gt;
&lt;br /&gt;
Processes can be of two different types: ''PL/SQL Processes'' and ''Java Processes''. PL/SQL processes are implemented in the PL/SQL language and are executed by the database engine. Java proceses are implemented in the Java language and are executed by the application server.&lt;br /&gt;
&lt;br /&gt;
==== PL/SQL Processes ====&lt;br /&gt;
&lt;br /&gt;
''PL/SQL Processes'' are implemented by database stored procedures. For more information read the documentation on [[How to create a Stored Procedure]].&lt;br /&gt;
&lt;br /&gt;
PL/SQL processes are defined in '''Application Dictionary || Report and Process'''. The only field to take into account for this kind of processes is '''Procedure''': It is the procedure name in the database. Note that as PL/SQL procedures are assigned to modules, they must be named according to following the naming rules: the name of the procedure must start with the module's DBPrefix.&lt;br /&gt;
&lt;br /&gt;
As the pop-up for PL/SQL processes is always automatically generated, the '''UI Pattern''' field must be set as ''Standard''.&lt;br /&gt;
&lt;br /&gt;
In case the process requires any parameter, it is possible to define them. To learn more about how to do it read the section [[#Parameters|above]].&lt;br /&gt;
&lt;br /&gt;
==== Java Processes ====&lt;br /&gt;
&lt;br /&gt;
Java processes are implemented by java classes. For more information read the documentation [[How to create a Java Process]].&lt;br /&gt;
&lt;br /&gt;
Java processes are also defined in the '''Application Dictionary || Report and Process''' window. Depending on the ''UI pattern'' they use, they can be split into ''Standard'' and ''Manual''. Additionally, if the ''UI Pattern'' is set to ''Manual'' is necessary to include an entry in the '''Process Mapping''' to make it accessible in the web.xml.&lt;br /&gt;
&lt;br /&gt;
The pop-up used to invoke Java processes defined with ''Standard'' ''UI pattern'' is automatically generated in the same way the interface for PL/SQL processes is done.&lt;br /&gt;
&lt;br /&gt;
To set a Java process to be have Standard UI just set the ''UI Pattern'' field to ''Standard'' in the '''Application Dictionary || Report and Process''' header. It is also necessary to indicate the Java class that is going to implement the process, this is done adding a new record in the '''Process Class''' tab. At least, one record in this tab must be checked as default.&lt;br /&gt;
&lt;br /&gt;
If the process requires parameters they can be defined in the '''Parameter''' tab as explained in the [[#Parameters|Parameters]] section of this document.&lt;br /&gt;
&lt;br /&gt;
=== Executing processes ===&lt;br /&gt;
&lt;br /&gt;
{{(!)|Note after defining the process compilation is required in order to be able to execute it. This step can be performed executing &amp;lt;code&amp;gt;'''ant smartbuild'''&amp;lt;/code&amp;gt; and restarting Tomcat afterwards.}}&lt;br /&gt;
&lt;br /&gt;
Processes can be executed from the user interface from a menu or in with button. It can also be scheduled to be executed in the background without any user interaction.&lt;br /&gt;
&lt;br /&gt;
==== Executing a process from a menu option ====&lt;br /&gt;
&lt;br /&gt;
To execute a process from a menu option you need to define a new menu option that executes the process. Menus are defined in '''General Setup || Application || Menu'''. In the '''Action''' field the '''Process''' entry must be selected, then in the '''Process''' field select the process. it will be executed imediately and then saved.&lt;br /&gt;
&lt;br /&gt;
Finally press the '''Tree''' button to organize the new menu option in the menu tree, and now the process defined can be executed selecting this new menu created.&lt;br /&gt;
&lt;br /&gt;
==== Executing a process from a button ====&lt;br /&gt;
&lt;br /&gt;
To execute a process with a button you need to define a column that references a button. In '''Application Dictionary || Tables and Columns''', go to the column you want to use to execute the process and in the field '''Reference''' select the '''Button''' entry, then in the '''Process''' field select the process you want to execute and save.&lt;br /&gt;
&lt;br /&gt;
When executing a process with a button, record ID the of the current record selected of the table will be passed to the process. This allows to execute functions for specific records.&lt;br /&gt;
&lt;br /&gt;
==== Executing a process in the background ====&lt;br /&gt;
&lt;br /&gt;
Backgroung processes are defined in '''General Setup || Process Scheduling || Process Request'''. For more information read the documentation [[How to create a Background Process]].&lt;br /&gt;
&lt;br /&gt;
In this window you can define a background process. The process to be executed can be selected in the '''Process''' field. Then you define the scheduling for the background process and it is then ready for use.&lt;br /&gt;
&lt;br /&gt;
There is no user interaction necessary to execute the process, thus no pop-up will appear prompting for additional parameters.&lt;br /&gt;
&lt;br /&gt;
===== Kill a background Process =====&lt;br /&gt;
&lt;br /&gt;
{{(!)|This capability will be available starting from '''PR15Q3'''}}&lt;br /&gt;
&lt;br /&gt;
A button &amp;quot;Kill Process&amp;quot; is shown in the Process Monitor window on that processes that implements the KillableProcess interface while a process is being executed (Status = Processing). The interface KillableProcess will let you kill your process using a kill mechanism.&lt;br /&gt;
&lt;br /&gt;
'''Mechanism to Kill'''&lt;br /&gt;
&lt;br /&gt;
The mechanism that your background process use to kill itself might vary between implementations. However the principle idea in any implementation should be to have the body of the job's execute(..) periodically check some flag to see if a kill has been requested, and if the flag is set, somehow abort the performance of the rest of the job's work.&lt;br /&gt;
&lt;br /&gt;
'''Example'''&lt;br /&gt;
&lt;br /&gt;
Let's see an example that you can find in this test module: [http://centralrepository.openbravo.com/heartbeat-server/org.openbravo.forge.ui/sso/ForgeModuleDetail/Example-Module-For-Kill-Process Example Module for Kill Process]&lt;br /&gt;
&lt;br /&gt;
Here we have a dummy process that the only thing it does is print in the log the identifier for all the business partners:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;public class DummyProcess extends DalBaseProcess {&lt;br /&gt;
&lt;br /&gt;
  private static final Logger log4j = Logger.getLogger(DummyProcess.class);&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void doExecute(ProcessBundle bundle) throws Exception {&lt;br /&gt;
    try {&lt;br /&gt;
&lt;br /&gt;
      // Get all business partners&lt;br /&gt;
      final OBCriteria&amp;lt;BusinessPartner&amp;gt; bpCri = OBDal.getInstance().createCriteria(&lt;br /&gt;
          BusinessPartner.class);&lt;br /&gt;
      bpCri.setFetchSize(1000);&lt;br /&gt;
      final ScrollableResults partnerScroller = bpCri.scroll(ScrollMode.FORWARD_ONLY);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      // Loop all business partners using a ScrollabeResults to avoid performance issues&lt;br /&gt;
      while (partnerScroller.next()) {&lt;br /&gt;
        final BusinessPartner bp = (BusinessPartner) partnerScroller.get()[0];&lt;br /&gt;
        // Print the Identifier for every business partner&lt;br /&gt;
        log4j.info(bp.getIdentifier());&lt;br /&gt;
&lt;br /&gt;
        if ((i % 100) == 0) {&lt;br /&gt;
          OBDal.getInstance().getSession().clear();&lt;br /&gt;
        }&lt;br /&gt;
        i++;&lt;br /&gt;
&lt;br /&gt;
      }&lt;br /&gt;
      partnerScroller.close();&lt;br /&gt;
    } catch (Exception ex) {&lt;br /&gt;
      Throwable e = DbUtility.getUnderlyingSQLException(ex);&lt;br /&gt;
      log4j.error(&amp;quot;Error in DummyProcess&amp;quot;, e);&lt;br /&gt;
      throw new JobExecutionException(e.getMessage(), e);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Killable Process'''&lt;br /&gt;
&lt;br /&gt;
Now, see here the same dummy process but with Interface KillableProcess implemented with the kill method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;public class DummyProcessKillable extends DalBaseProcess implements KillableProcess {&lt;br /&gt;
&lt;br /&gt;
  private static final Logger log4j = Logger.getLogger(DummyProcessKillable.class);&lt;br /&gt;
&lt;br /&gt;
  // Add a variable 'stop' to control the kill implementation and set false by default&lt;br /&gt;
  private boolean stop = false;&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void doExecute(ProcessBundle bundle) throws Exception {&lt;br /&gt;
    try {&lt;br /&gt;
&lt;br /&gt;
      // Get all business partners&lt;br /&gt;
      final OBCriteria&amp;lt;BusinessPartner&amp;gt; bpCri = OBDal.getInstance().createCriteria(&lt;br /&gt;
          BusinessPartner.class);&lt;br /&gt;
      bpCri.setFetchSize(1000);&lt;br /&gt;
      final ScrollableResults partnerScroller = bpCri.scroll(ScrollMode.FORWARD_ONLY);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      // Loop all business partners using a ScrollabeResults to avoid performance issues&lt;br /&gt;
&lt;br /&gt;
      // Only continue with the process if the variable 'stop' is false&lt;br /&gt;
      while (partnerScroller.next() &amp;amp;&amp;amp; !stop) {&lt;br /&gt;
        final BusinessPartner bp = (BusinessPartner) partnerScroller.get()[0];&lt;br /&gt;
        // Print the Identifier for every business partner&lt;br /&gt;
        log4j.info(bp.getIdentifier());&lt;br /&gt;
        // Add a timeout of 30 seconds&lt;br /&gt;
        Thread.sleep(30000);&lt;br /&gt;
&lt;br /&gt;
        if ((i % 100) == 0) {&lt;br /&gt;
          OBDal.getInstance().getSession().clear();&lt;br /&gt;
        }&lt;br /&gt;
        i++;&lt;br /&gt;
&lt;br /&gt;
      }&lt;br /&gt;
      partnerScroller.close();&lt;br /&gt;
    } catch (Exception ex) {&lt;br /&gt;
      Throwable e = DbUtility.getUnderlyingSQLException(ex);&lt;br /&gt;
      log4j.error(&amp;quot;Error in DummyProcess&amp;quot;, e);&lt;br /&gt;
      throw new JobExecutionException(e.getMessage(), e);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  public void kill(ProcessBundle bundle) throws Exception {&lt;br /&gt;
    bundle.getLog().log(&amp;quot;process killed&amp;quot;)&lt;br /&gt;
    // When kill is called set variable 'stop' to true so the process will be interrupted in the&lt;br /&gt;
    // next iteration: while (partnerScroller.next() &amp;amp;&amp;amp; !stop)&lt;br /&gt;
    stop = true;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's comment the code...&lt;br /&gt;
&lt;br /&gt;
First we need to implement the KillableProcess interface.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;public class DummyProcessKillable extends DalBaseProcess implements KillableProcess {&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a variable 'stop' that we will use to check the continuity of the execution.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;// Add a variable 'stop' to control the kill implementation and set false by default&lt;br /&gt;
  private boolean stop = false;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the main loop of the process we add the check to stop the execution when the variable is set to true.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;      // Only continue with the process if the variable 'stop' is false&lt;br /&gt;
      while (partnerScroller.next() &amp;amp;&amp;amp; !stop) {&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also have added a sleep (30 seconds) to make the execution time longer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;        Thread.sleep(30000);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally we implement the kill method that set 'stop' to true.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;  @Override&lt;br /&gt;
  public void kill(ProcessBundle bundle) throws Exception {&lt;br /&gt;
    bundle.getLog().log(&amp;quot;process killed&amp;quot;)&lt;br /&gt;
    // When kill is called set variable 'stop' to true so the process will be interrupted in the&lt;br /&gt;
    // next iteration: while (partnerScroller.next() &amp;amp;&amp;amp; !stop)&lt;br /&gt;
    stop = true;&lt;br /&gt;
  }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we are able to kill the process from the Process Monitor. When a process is killed, the status in process monitor will be &amp;quot;Killed by User&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Category:Concepts]]&lt;/div&gt;</summary>
		<author><name>Wikiadmin</name></author>
		
	</entry>
</feed>