...
To create a multithreaded process, you need to create two process classes extending com.crm.process.CRMProcessRunBean implementing at least one method each. The first one (main) will be used to create and run new threads and the second one will implement the business logic executed by a thread.
...
- Retrieves the billable accounts by calling getBillableAccounts() method, which runs an SQL script to retrieve the billable accounts.
- Retrieves the number of threads to be used, using getNumberOfThreads() method of com.crm.process.CRMProcessRunBean super class . The default number is 4. To change it, go to Foundation > Platform > Manage Admin Settings > Set up General Settings > System Restrictions > Default Number of Threads for Batch Processes.
- Creates an instance of com.crm.framework.threads.EJBThreadPoolExecutor class passing the following parameters:
- The session handle which can be retrieved by calling getCRMSessionHandle() method
- The name of the class implementing the method executed by a thread
- The name of the method executed by a thread
- The number of the threads that will run simultaneously
- Then number of the objects to be processed
The maximum time that excess idle threads will wait for new tasks before terminating
- The time unit for (f) value
- The log filename
- For every billable account, a new thread is submitted to the thread pool executor, using submitTask method of com.crm.framework.threads.EJBThreadPoolExecutor class. otherparams object array is used for defining the parameters needed by billAccount method which is the method executed by a thread. Note that this method, which processes the retrieved entities, should be implemented in a separate EJB, and not the main EJB which retrieves the entities to be processed.
- The thread executor is shut down using shutDown method of com.crm.framework.threads.EJBThreadPoolExecutor class.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public class CRMProcessAccountBilling extends CRMProcessRunBean { ... public void billAccounts(Integer threads,String logFileName) throws Exception { ResultSetUtil billableAccounts = getBillableAccounts(); Integer threads = getNumberOfThreads(); Boolean logFailed = new Boolean(true); Boolean logSuccess = new Boolean(true); if (billableAccounts != null && billableAccounts.getRowCount()>0) { EJBThreadPoolExecutor threadExecutor=new EJBThreadPoolExecutor(getCRMSessionHandle(), "ejb/CRMProcessBillAccount", "billAccount",threads, billableAccounts.getRowCount(), 10, TimeUnit.SECONDS, logFileName); while (billableAccounts.next()) { String accRecID = billableAccounts.getString("ACCRECID"); Object[] otherparams = new Object[] {accRecID}; threadExecutor.submitTask(otherparams); } threadExecutor.shutdown(); } } ... } |
Note that the default transaction timeout value of the main process class, which in this case is CRMProcessAccountBillingBean, must be increased. For more information on setting EJB transactions timeout value go to Change EJB Transaction Timeout.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public class CRMProcessBillAccountextends CRMProcess { ... @EJB private CRMProcessLog processLog; ... public void billAccount(String accrecID, CRMDOProcessRunLog processRun, Boolean logSuccess, Boolean logFailed) throws Exception { try { //put the code to bill the account here ... ... } catch(Exception e) { //log the error details here ... ... //Rollback the changes getSessionContext().setRollbackOnly(); } } ... } |