| By Parameswaran Seshan | Article Rating: |
|
| October 16, 2008 08:00 PM EDT | Reads: |
5,047 |
BPMS Implementation
The function of a BPMS is to help manage business processes through their lifecycle. Executing the processes at runtime to automate them is the primary responsibility of a BPMS server. At runtime, a typical BPMS server would need to take care of such things as execution of processes involving parallel paths, their merging, preservation of process state with context, asynchronous/synchronous execution of sub-process, and inbound calls to activities in the process from outside.
To execute processes, the BPMS server creates runtime instances from the process definition. Each process instance represents a unique runtime occurrence of the process based on a specific process invocation (instantiation) request from the originator of the process. The originator could be a customer, a business user, another process, or another role that can trigger process execution. For example, a customer could trigger the execution of an order fulfillment process by placing an order to buy some item. An executable process definition is typically in a standard format such as BPML (Business Process Modeling Language) or WS-BPEL (Business Process Execution Language for Web Services). Though we primarily mean BPML constructs here, the design and implementation applies as well to the equivalent WS-BPEL constructs, since the WS-BPEL constructs can be transformed into their equivalents in BPML and vice versa, retaining their semantics.
A BPMS server has to run process instances independent of other process instances at runtime, since each process instance is unique and has its own context (i.e., variables or parameters defined for the process) and state that has to be maintained throughout. The state and context of each process instance has to be stored in the process database at logical points during the process execution flow.
The process instance could be triggered by the originator synchronously (the process execution happens in the same thread as the caller's thread) or asynchronously (the process is executed in a separate thread and the caller's thread continues its own execution without waiting).
A process can contain a mix of system activities (that are executed automatically by the BPMS server) and user activities (that are performed by a user through a GUI). When the process is executed, its activities are executed by the BPMS server in the order specified in the process definition. The execution proceeds until a user activity is encountered, at which point the BPMS server makes the process wait for the user to perform the required activity.
Once the user completes the action, the user's GUI notifies the BPMS server to resume executing the rest of the process steps. Such a process would pause at all points where user interaction is involved in the process. To save computing resources, such process instances could be hibernated/passivated (removed from runtime memory) after some preconfigured time period once they enter the waiting state, and later revived when the user's GUI indicates to the BPMS server that the user action is complete. In addition to these moves, the BPML constructs such as "All" (Flow in WS-BPEL), which results in a split (fork) and join, "Call" of sub-process, and "Spawn" of sub-process have to be supported by the BPMS server.
All these functionalities require that the BPMS server be multithreaded, manage threads in a pool, and control them, i.e., a multithreaded execution model very much applies here.
Process Initiation Implementation
The execution model is to execute each process instance in an independent thread because a process might be long-running and the caller would not want to wait that long for it to complete. The BPMS server uses the class ThreadPoolExecutor from the concurrent library to set up and manage a pool of threads that can be used to execute process instances. We set the parameters such as maxpoolsize (from the configuration data), thread alive time (to five minutes), and corepoolsize (to 3) at the time of the server startup (see Listing 1).
Each process instance in memory is an instance of the Process class that represents the runtime version of the process. This object is created the first time a request for the execution of the process comes, by reading and translating the BPML process definition. It's subsequently cloned to create a new instance for each subsequent request for new process instance execution. It contains a Java.util.Vector of activities in a tree structure that mimics the activity order and nesting in the BPML process definition, and its run() method executes the activities sequentially iterating through this vector. To make the ThreadPoolExecutor execute this process object, it needs to be put in a Java.lang.Runnable object and supplied to the procPooledExecutor's execute method. So we create a ProcRunner class that extends Runnable and have a reference variable in it that points to this process object and the run() method of the ProcRunner would invoke the process.run() method to execute the process.
ProcRunner procRunner = new ProcRunner(process);
// Start the process in a new thread.
procPooledExecutor.execute(procRunner);
In the case of synchronous process execution (typically short-running process), the run() method of the process object is directly invoked in the caller's thread.
The ThreadPoolExecutor efficiently and effectively manages the pool of threads, relieving the programmer of that responsibility. Depending on the expected load on the system (i.e., the number of process instances expected to be triggered), the configuration setting for the maximum pool size can be changed so that the thread pool size is optimum.
All Activity Implementation
The "All" activity in BPML is a complex activity that means it is composed of one or more activities. An "All" activity executes all the activities that it is composed of in parallel. The equivalent construct for it in WS-BPEL is "flow." We can see "All" in terms of a fork and join, i.e., the main process execution path forks into parallel paths - as many paths as there are activities in All - executes them in parallel, and once the parallel paths complete execution, they join (merge) together with the main process path.
The join is a synchronization point that the parallel path threads converge on. The threads reaching this point first wait till others join them and they all synchronize at this point with the main process thread. Then their executions end, and the main path continues thereafter with the process execution moving to the next activity after the "All." From the concurrent utility, we use the classes ThreadPoolExecutor to realize fork and CyclicBarrier to implement the join (i.e., synchronization).
For the fork, we have an ActivityRunner class (similar to the ProcRunner mentioned in the above section) that extends the Java.lang.Runnable and holds reference to an activity object that it would execute in its run() method. For each activity in the activity set of the All activity, we create an instance of the ActivityRunner and put the reference to the activity object in it. Then the ThreadPoolExecutor's execute() method is called to run it in an independent thread. To handle the join part, CyclicBarrier is used. It is a sync point that lets a set of threads wait for each other to reach a common barrier point. Once all the threads join this barrier, a common task can be performed before each of them is released. The common task needs to extend Java.lang.Runnable and it's useful for updating the shared-state before any of the parties continue.
Published October 16, 2008 Reads 5,047
Copyright © 2008 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Parameswaran Seshan
Parameswaran Seshan is a Senior architect with E-Comm Research Lab, Infosys Technologies Limited, Bangalore, India. He has around 14 years of work experience in the IT industry, involving research, teaching, architecture, and programming. His areas of interest include Process-centric architecture, Intelligent software systems, software architecture, Business Process Management systems, Web services and Java.
- Kindle 2 vs Nook
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- Confessions of a Ulitzer Addict
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- It's the Java vs. C++ Shootout Revisited!
- Cloud Computing Can Revitalize Your Career as Software Developer
- IBM Could "Reinvent" Java: Mills
- Oracle & Cloud Computing: Exclusive Q&A with SVP Richard Sarwal
- A Brief History of Cloud Computing
- Kindle 2 vs Nook
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing Expo: Exclusive Q&A with Yahoo! SVP Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- What's New in Eclipse?
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- i-Technology Predictions for 2007: Where's It All Headed?



































