UEngine English Version Wiki
Uwiki
User Manual
Open Source BPMS - uEngine Introduction
This manual tries to explain the whole processes of practical uses via uEngine open source BPMS which is available to everybody without charge. Therefore, anybody who is interested in making use of uEngine BPMS or providing services to others can experience useful processes much more directly.
The uEngine BPMS is the first professional open source product in Korea. It is designed that all components of the product can be easily embedded. Recently, many companies focus on adopting BPMS, with their existing software integration, duplicate functionality, and TCO(Total Cost of Ownership), these difficulties can be positively solved by the uEngine BPMS.
The core of uEngine consists of component framework which makes possible on special integration patterns such as new activity types, external organization charts, united data managements between external applications. It is a big difference that the “embedded uEngine’s BPMS” has the capability of handling various overheads during integrations and customization tasks while most existing BPM solution providers can not avoid these problems.
Embedded BPM
Since uEngine initially started developments based on component assembly architecture, it has experienced as an OEM provider integrated with various product suites from other companies. With history and technical based characteristic of the product, it helps users have not only a server/client mode, but also a library/framework mode which helps users integrate external organization charts via a callback implementation, data extraction through its engines’ event extraction, interfacing with external messenger or worklist as an implementation model. In addition, it provides an Activity wrapping functionality that users make use of various existing software products while modeling business processes.
Especially, this feature gives at lease impact on well structured existing application architectures (organization management(HR), approvals or groupware, EAI, in the case of standardization settled) . It can be a great choice for companies who want to internalize BPM. Those software companies who develop ERP, PDM, SCM, CRM, or existing management information systems can embed uEngines to their own software products under the LGPL license agreement with uEngine Solutions. It is effective that they make use of uEngine special features and able to upgrade or differentiate their own software products to be BPM based systems.
Practical Use of BPMS - Lifecycle
How to install and run uEngine
uEngine Download
Visit the page, http://sourceforge.net/projects/uengine/files/, and download the latest version of uEngine on the download page.
- - Java 1.5 or higher versions must be installed in order to run uEngine.
uEngine installation and execution
- Windows Environment
- Extract downloaded files in an appropriate folder.
- Set up JAVA_HOME in order to run the server properly.
- Click the “Environment Variables” under the “Advanced” tab menu in the System Properties. (Set up the folder path in which JDK is installed) [Figure 5-2]
- Set up the “System Variables” in the “Startup.bat” file. [Figure 5-3]
- Like [Figure 5-4] and [Figure 5-5] Run both DB and WAS.
Launch the web browser, type the url, http://localhost:8080/uengine-web. The part of url, ‘http://’ must be entered. Log in with the administrator account[ID:test / PW:test].
- uEngine User Interface
uEngine’s User Interface consists of two frames. The first frame is the menu area located on upper region of the screen,and the other frame is the user area except for the menu area. The menu area consists of Home, WorkList, Strategy, Process, Monitor, Process Manager, Analysis, Organization that link with Portlet pages. By clicking along the pages, user working space can appear on the screen.
| Portlet Page | Description |
| WorkList | Currently assigned work list according to the status of each task(in Progress, Completed, Cancelled). |
| Process | New work processes can be distinguished by field, and processes can be run in the page. It helps users understand the flow of the process at a glance. |
| Process Manager | By using this menu, processes can be easily manageable. The current processes in progress can be easily displayed. |
| Analysis | By using OLAP tool, users can view information in a preferred format such as table or chart. |
| Organization | Configure organizational structures via associate registration, responsibility management |
- Process Automation – Process Enactment
Process automation is the functionality that users execute existing electronic processes(Process Definitions) by themselves without the help of IT department. It distributes and controls each defined task. The characteristics of process automation are following.
- Users do not need to look for tasks. Tasks look for the people in charge of the assigned tasks instead.
- It maximizes the synergy effect between various systems related to the process execution.
Initiate Work
In order for the end user to initiate a work process, the "Process Map" under the “Process” menu is useful. Like the following [Figure 5-8] and [Figure 5-9], by selecting “Issue Tracking Process” and clicking the ”Initiate this Process” the selected task can begin.
Work Progress
From the previous instruction, by clicking “Initiate this Process” the first task of the work, ‘Create New Issue’ screen(called as a workitem handler) is loaded. The following figure shows that users type the trouble description simply and click the “Confirm” button, therefore, the process is initiated immediately.
The next task is that the ‘Assignee’ who is chosen by the previous step of the task writes an issue report after understanding the issue, therefore, only the selected users should log in.
By using user main screen or WorkList menu, assigned tasks can be displayed. The new task, ‘Issue Tracking Process’ can be clicked if it exists. As a result of that, the following workitem handler is loaded. The current task progress can be analyzed and the issue handling plan or results can be entered. And then, by clicking “Confirm” button, the task is finally completed.
The next step is that the initiator who writes an issue checks the handling plan or result, so with the initiator account, the access can be permitted in order to complete the step. After reviewing the issue report, the completion can be made based on the result. (According to the selection, issue reports can be needed again, or issue handling result registration or closure can be made.)
Process Monitoring
Monitoring functionality such as flow chart, Gantt chart, and dashboard helps users make sure current task progresses which are sometimes hidden. It is a notification function that shows various critical elements, therefore, users are able to take an action against the difficulties.
- Do not need to wait for incorrect task progress reports.
- It makes possible to plan effective task distributions by task managers.
- Overcome task delays due to emotional or political reasons in organization via a transparent task control.
Confirm Process Instance 'Progress' or 'Completion Status'
Visit the ‘Process Manager’ menu under the uEngine page.
Each instance whether it is in progress or completed can be shown on the “Process Instance List”. Current instances which are in progress are shown by clicking the instance like [Figure 5-13].
Like [Figure 5-14] shown above, it is an instance enacted by the “Issue Tracking Process” definition. It shows that the third task(handling the issue) is being executed. Moreover, users are able to check process variables and the information of participants .
Process Analysis
Process Analysis’s main goal is customer satisfactory resulted from the success of process bottleneck detection, optimized human resource allocation, and process execution outcomes that are critical issues in process operation.
With these analysis outcomes, the optimal elements that improve current process definitions can be brought up. BPM lifecycle can also be managed by continuous improvements of processes like the one mentioned earlier.
Process Analyzer Structure
In order to analyze processes, visit the “Analyzer” menu.
Process Analyzer consists of Menu Icons, OLAP Navigator, Pivot table, and Chart. OLAP Navigator is a design tool that displays the data generated from the Pivot table which is also extracted from instance data in any format. In addition, Pivot table shows the same data as OLAP Navigator has, and it is possible to drill down the detailed elements in a row or column, or swap the vertical and horizontal axes(Swap Axes). It is very similar to Excel’s Pivot functionality.
For various perspectives of data, the followings are the icons of OLAP Navigator which consists of multi-dimensions.
| Icons | Functionality |
| Move dimension to "Columns" area. | |
| Move dimension to "Rows" area | |
| Move dimension to "Filters" area. | |
| Move dimension up/down in the current area |
The Columns and Rows of OLAP Navigator are criterions which display the data composed with vertical or horizontal elements for each table respectively. Filters are essential elements that construct data, but the only filtered data by the “Filters” will be resulted in tables, even though hidden data is a part of the whole data. After manipulating data by “Pivot Table”, users are able to create charts that reflect the “Pivot Table”. By clicking “Chart Config” icon, the types and shapes of the charts can be configured.
Practical Analysis of Trouble Ticket Task
First of all, let us practice with an analysis example that shows the total or average hours consumed for the task by participant’s age based on year 2007 data. These “Resource by Birthday”, “Processing Time (Sum)” , “Processing Time (Avg)” fields are required. The following table, [5-3] describes the requirements in a simple way.
| Measures | ||
| ResourceByBirthday | Processing Time(Sum) | Processing Time(Avg) |
| 1968 | ||
| .... | ||
| .... | ||
| .... | ||
In order to create the table above, we need to configure the OLAP Navigator as below.
Click the “OK” button and Run the OLAP Navigator. You will see the changes of the table as below.
In order for us to configure details in [Figure 5-18], click “Measures” on OLAP Navigator, and uncheck the “Cost”, and uncheck “All Resources” from “ResourceByBirthday”,but keep the child fields of “All Resources” checked. Additionally, check “2007” from “Time” category, and click the “OK” button. Finally, the “Pivot Table” is completed like the [Figure 5-19] shown below.
Configure charts based on the data filtered previously, click this icon,
[Figure 5-21].
In [Figure 5-21] shown below, the completed analysis result can be obtained. According to the purpose of analysis, various charts can be configured.
Witam serdecznie!
Szukam i szukam i znalezc przyczyny nie moge... problem mam nastepujacy: moja strona (<a href=http://www.nieruchomosci-pila.net>mieszkania Piła wynajem</a>) raz sie otwiera innym razem z kolei dostaje jakies dziwne komunikaty albo w ogole przegladarka twierdzi, ze takiej strony nie ma. Do tego na niektorych kompad pod internet explorerem wyswietla mi sie wyszukiwarka binga - i tam pojawia sie na pierwszym miejscu link ktory... zazwyczaj otwiera strone. Macie jakies pomysly?
Bede wdzieczny za wszelkie propozycje, nagroda - szczegoly na PW!
Basic Process Modeling
How to Use Modeling tools
Process Definition Creation
Process Managers need to create a new folder if there is no related folder existing in the “Process Definition” tree. It is a good way to manage process definitions by related groups like file folders.
In order to create a new folder like the [Figure 6-1] shown above.
- Under the root of “Definitions” tree, the toggle function which is working with the clicks of a mouse allows users to view the whole list of process definitions in active.
- Open the whole list of process definitions by the right clicks of a mouse on the selected folder under the root of “Definitions” tree.
- After right-clicking on the “Definitions” tree with your mouse, a shortcut menu appears on the screen, choose the “New” and click the “Child Folder”.
- A small [Insert name] window pops up, enter a new folder name(for instance, “Test”)
Like the [Figure 6-2] shown above, we make sure that the “Test” folder is just created.
For creating new process definitions under the folder which we created previously, right-click on the folder, select the “New” menu, and select the “Process”, As a result of that, the “Process Designer”[Figure 6-3] is executed automatically.
The top region of the “Process Designer” which consists of various Activity types is also called Activity Type Palette. Among these activity types, “Human Work” Activity under the “Document” group can be clicked or drag and drop the Activity icon onto the “Flow Chart” region or Working space.
Like [Figure 6-5], the selected Activity is added into the center of “Flow Chart” region on the “Process Designer”
When removing added Activities, there are several ways to conduct the removal. The first one is that select the Activity which has a transparent rectangle with red dotted line around it and hit the “Delete” key. The second way is to right-click on the Activity and select the “Delete” button. Lastly, drag and drop the Activity into the “Trash Can” located on the bottom of the screen.
In order to configure properties for the selected Activity on the Flow Chart, double-click the Activity. In the case of “Human Work”, a new window pops up, and users are able to make changes on the properties of the selected “Human Work”. And then, we simply type “Trouble Ticket” for Activity name. The responsibility for the role can be “Initiator”. Finally, all the changes can be applied by clicking the “Apply” button.
If there are no error marks(
) , all the properties are configured correctly. In case, there are errors, we can check the error messages using “Integrity” menu under the “Properties” tab.
Process Enactment
For executing Process Definitions created by users, server deployment is required through either clicking the icon(
), located on the top tool bar or hitting the “Deploy” button on the bottom of the screen. As a result, a new dialog window appears on the screen. Type an appropriate process name for the task(For instance, subTest) and click the “Confirm” button. Finally, “Deployment” is completed
In order to make sure that the “Deployment” is successful, The [subTest] process must be created under the [Test] folder, and the “Set as a Production” button must be clicked, therefore, users are able to make use of the process that we just created.
For executing this Process Definition, like [Figure 6-9] the “Initiate” button must be clicked.
The following [Figure 6-10] shows the tasks in progress. By clicking the “Complete” button, the corresponding workitem is completed. So far, we have only one Activity, the whole process can be finished when clicking the “Complete” button.
The following [Figure 6-11] shows the result of completed workitems. The execution information of finished processes or processes in progress can be checked by selecting the “Process Manager”. (We called as a process instance which resulted after executing processes.)
<Figure 6-12> shown below describes that processes are currently executed or shows the information of completed process instance. In order to check the execution results of the completed “Trouble Ticket” instance, click the corresponding instance on the list of instances.
<Figure 6-13> shows the result of completed “Trouble Ticket” process after executing. The top of the screen allows users to view the step of executed instance via Flowchart tab menu along with process variables and participants’ role information.
Process Variable Configuration
This Process Definition does not request any tasks to users. We need to advance this process in order to receive or handle some type of data from users. For the purpose of this, the“Improve” button should be clicked, and the “Process Designer” is executed. Therefore, we are able to create process variables. Process variables can be created by these “Edit Variables” and “New” windows that appear on the screen accordingly after clicking near the “Variables” right next to the “Roles” on the bottom region of the “Process Designer”.
On [New Process Variable] window, Process Variables can be created like the [Figure 6-15] below
After typing all the information of Process Variable, click the “Update” button and close the “New Process Variable” window. With “Edit Variables” window like [Figure 6-16], users are able to view all the process variables that already created. Even they can view all the detailed information of the selected process variable by right-clicking on it which shows a popup menu, and select the “Open” from the menu.
After creating a Process Variable for “subTest” process for Trouble Ticket, users can configure the properties for the first “Report a Trouble” Activity of our example process. By clicking on the Activity, the second tab of the Human Work Activity, in the case of ‘Report a Trouble’ can be selected and scroll down its window, “Parameters” is placed in the bottom of the window. After then, click the “New” button right above the “Parameters” field, related process variables can be selected. The [Figure 6-17] shown below appears, therefore, the created process variable, “Trouble Type” can be selected.
After adding process variables to Activities, Another ‘Deployment’ is required. After then, a new version must be set into production in older versions, which are lower than ‘3.5.2’. From Process Definition List, select the “subTest” process for Trouble Ticket, and Hit the “Initiate” button.
Like the [Figure 6-19], the “Trouble Type” input box is created, and enter “System” value for the input box, and complete the task.
The following [Figure 6-20] shows that “System” value is displayed that it differs from previously defined process at the beginning of this process before adding ‘Trouble Type’ process variable to the Activity.
Basic Example of Process
- The Goal of this Process Example
Let us assume that we have a new work process in our organization. The work is called as “Trouble Ticket Process”, our users experience various system troubles while using our computer systems. The process conducts these works such as receiving troubles, solving the troubles by people in charge, giving feedbacks to the people who reported the troubles.
- A Scenario of this Process
- Users who experience troubles report the issues.
- Trouble handling manager reads the troubles, assigns appropriate people who can handle the troubles and forwards the description of the troubles.
- The people in charge write answers for the troubles.
- The answers are automatically delivered to the users who initially reported the troubles via email.
The following [Figure 6-21] depicts the whole steps of the process in an easy manner.
Process Definitions
After logging in, create a ‘Trouble-Ticket’ group folder in which we make some tests. Run the “Process Designer”, finally, we are ready to practice modelings. The followings are the steps in order to conduct modelings.
- Participant Definitions
- Process Variable Definitions
- Process Flow Definitions
These are three big parts. Each part works parallel if required
- Participant Definitions
“Participant Definitions” is a step which defines responsibilities for participants’ roles in the process. The followings are the responsibilities for the current example, “Trouble Ticket Process”
- User: People who report troubles
- Manager: Receives the troubles and assigns people in charge of handling troubles.
- right Person: A practical person who solves the assigned troubles.
The following [Figure 6-22] shows the steps of assigning responsibilities.
- Click the “Roles” definition panel on the bottom of the screen
- Click the “New” button after opening “Edit Roles” window
- Type Role ID and Display Name for the Role
With those ways, assign User, Manager, and right Person as participant.
| Role ID | Display Name for the Role |
| User | User |
| Manager | Manager |
| Rightperson | Right Person |
Table 6‑1 Role Definition Configuration
Process Variable Definition
There are process variables needed in order for all Activities to send/receive data each other in modeling. The following variables are needed for “Trouble-Ticket Process” example.
- Trouble_desc
- Trouble_result
- Trouble_type
The following [Figure 6-23] shows the steps of creating variables.
- Click the “Variables” panel on the bottom of the screen
- Click the “New” button on the “Edit Variables” window
- Process Variable Name(ID), Data Type, Display Name for the Process Variable, and Inputter located in the “Advanced Options” tab menu can be configured.
Table 6‑2 Process Variable Definition Configuration
| Process Variable ID (Delimiter which separates each process variable) | Data Type(Process Variable Data Type) | Process Variable Display Name(Easily recognized by this Display Name) | Inputter (Users provide data according to this input control type) |
| Trouble_desc | Text | Problem Description | TexetAreaInput(Cols : 80, Rows : 5) |
| Trouble_result | Text | Resolution | TexetAreaInput(Cols : 80, Rows : 5) |
| Trouble_type | Text | Problem Type | SelectInput(Values / Selections) - System/Systemic Problem - Hardware/Hardware Problem - Req_for_improvements/ Request for improvements |
When configuring each process variable, the input control type(Inputter) must be decided. The styles and properties of input control types are followings.
Select control – Option Selector
An option can be selected according to the task.
- Click the down arrow on the Select control
- Relevant option should be clicked
Properties
- Selections: The name of the currently selected option displayed on the screen
- Values: The value of the currently selected option
For instance, users select a trouble type on their screens, they click the down arrow, and select the relevant trouble type for the trouble ticket.
TextArea control
Users can describe troubles in the given TextArea.
Properties
- Cols, Rows: Limit the size of columns and rows in the TextArea
For instance, when users need to explain their troubles, they can write detailed descriptions in the TextArea.
Radio Button Control
Radio buttons are very similar to “Select” control, they are mutually exclusive. The only difference between two is the way of displaying options. Radio button provides all the selections at once on the screen, while “Select” control displays available options by clicking the “Select” control. Click an appropriate one among several radio buttons
Properties
- Selections: The name of the currently selected option displayed on the screen
- Values: The value of the currently selected option
For instance, users select a trouble type on their screens, they click the relevant trouble type among various radio buttons.
Activity Declaration / Flow Configuration
So far, we have completed participant definitions and process variable definitions that are essentially declared in order to define a work flow. From now on, we need to define all the actual tasks for each Activity along with a complete flow between them.
The detailed behaviors of each separate task can be defined by using various Activity types selected from the “Activity Type Palette” located on the top of the “Process Designer”.
Previously we defined 4 steps for this ‘Trouble Ticket’ process. The first 3 steps are handled by people that we simply call it as “Human Work” Activity. For the last step, there is no human involved. Its task conducts an email delivery after finishing the third step of the process. Email Activity(local) located in Messaging group can be used for this purpose.
Step 1 – The Step of Trouble Report
The first 3 steps for the “Trouble Ticket” process are 1) Trouble Report, 2) Task Distribution to People in charge, 3) Trouble handling. These 3 tasks are treated as “Human Work”. The followings show how to define the whole process.
① Select the “Human Work” in Document group from Activity Type Palette.
② Double-click the recently added “Human Activity type” in the Flowchart.
The Human Activity Property window with ”HumanActivity” name appears over the “Process Designer”.
- Configure Name and Description on the first Basic Properties tab menu, Role and Parameters on the second Human Work tab menu for the “Human Work”
The first step of the process is that users report troubles with the name, ‘Trouble Report’. We choose the ‘User’ which we already declared for the role. At this step, the process variables of “Problem Type” and “Problem Description” which are already declared get mapped through the “Parameters” on the second “Human Work” tab menu.
Step 2 – The step of selecting people in charge.
The second step conducts that the manager receives the contents from the previous first step. He/she reads the contents and distributes the tasks to appropriate people who can handle the troubles. Like the first step, simply add another “Human Work” and configure properties that are as follows
Activity Name: Assign a person in charge
Responsible Role: Manager
Parameters:
| Variable | Direction |
| Problem Type | in |
| Problem Description | in |
| [Role]Right Person |
• If “Direction” for any Process Variable is set with “in” value, users are only able to read the value of the process variable. It means that users can not make changes on corresponding process variables. By default, “in-out” is set, therefore, users are able to read and write something in a provided input control.
In this situation, the Manager is configured by the special person who is already decided and different from either initiator or Right Person. (initiator is automatically mapped with a user who executes the process while Right Person is dynamically selected during conducting tasks.) For this, from the “Role” panel located on the bottom region of the “Process Designer”, the “New Role” window is launched by clicking the “Role” and a Role picker window is popped via the “[ ... ]” button right next to the “Role” field in the “Advanced Options” tab menu. After clicking the “By Role” tab menu, select an appropriate group and role accordingly.
• Role Picker is a tool supported within the “Process Designer”. It provides functionality that allows users to apply rules which help actual people in charge get mapped with roles at any task step of the process.
When the direction of a parameter is set with “in” value, users only can read the contents, but writing is not allowed. The corresponding field is read-only. In conclusion, the manager views entered information by the previous step. The last parameter for “[Role]Right Person” shown the table above is in active at the second step of the process, therefore, the manager is able to select an appropriate person for the task by using the “Role Picker”.
Step 3 – The step of Handling Troubles(Write Resolutions)
This third step of process provides a screen in which the selected person who gets mapped from the second step enters trouble resolutions for the trouble. The properties are as follows.
Activity Name: Handling troubles
Responsible Role: Right Person
Parameters:
| Variable | Direction |
| Problem Type | in |
| Problem Description | in |
| Resolution |
Step 4 – The step of Handling Troubles(Write Resolutions)
Report the results to the user who opens the trouble ticket (Reply to the user)
At the last step, E-Mail Activity sends a notification email to the user who opened the trouble ticket. The email contains the trouble resolution written by the person in charge at the third step.
① Select the “E-Mail(local)” Activity in Messaging group from Activity type palette.
② Double-click the recently added “E-Mail(local)” Activity.
③ Configure Activity Name, Description, Sender Email Address, Recipient, Email Title, and Email Contents.
Table 6‑3 Human Work Property Configuration
| Property | Configuration Value |
| Activity Name | Report the Result |
| Sender | manager@uengine.org |
| Recipient | User |
| Email Title | This is the requested “Trouble Ticket” result. |
| Email Contents | Hello, This is the report of handling troubles. The results after handling the requested trouble are as follows.: <%=Trouble_result%> For more additional questions or requests, we will appreciate, if you contact us. |
How to Deploy Process Definitions
If there are no red error marks found, the process that we just created is well prepared for “Deployment”. So, we click the “Deploy” button located on the bottom right side of the “Process Designer” screen.
Process Enactment
Throughout the whole steps of the process, we have successfully created the “Trouble Ticket” process. From now on, any system user in our organization takes advantage of uEngine for creating new task processes. In order for end users to start any process created by administrator, the “Initiate” button located on the top of the “Process Definition” page must be pushed after clicking the process under the “Definitions” tree. After clicking any process on the “Process” page, the process flowchart can be displayed. Additionally, by clicking the “Initiate this Process”, the task just gets started.
Task Progress
Along the previous instructions, when the “Initiate this Process” button is clicked, the first task,”(Report Trouble)” of the “Trouble Ticket” process is being loaded. It is also called as a WorkItem handler. The following shows the steps of the process including entering trouble description, clicking the “Complete” button, and starting the process.
At the next step of the process, managers distribute the tasks to appropriate people who can handle the troubles. Therefore, only authorized managers must be logged on to do so. However, this process is set to the same user for convenience. The inbox, “WorkList”, is the place where users receive assigned works to do. As a result, users are able to check what tasks are assigned so far. If any necessary work related to task assignment, appropriate people who can understand the progress for a given task must be selected for the task role after reading the contents requested by initial users. For an easier approach for this matter, we simply select the “Tester”. Otherwise, we keep logging out and logging in to keep continuing the process. Finally, the “Complete” button must be clicked for the task completion.
The responsible user for this new step is the same user selected from the previous step. Without re-logging in, as a trouble handler, the trouble result or resolution must be entered and completes the task.
So far, all the human related works are completed. For the last task, an automatic email with the result of the task will be delivered to the user who opened the trouble ticket, so recipient email address must be checked for the successful email delivery.
If the recipient email address in organization chart is missing, we are not able to make sure that the email is successfully delivered, so, a test email address is needed and used for testing this “Trouble Ticket” process.
Processes using Forms
- Trouble Ticket Implementation via Forms
In general, process task format styles are either web or general documents like Microsoft Office files. However, uEngine provides a form editor in which users create any task document forms by themselves comfortably. At this time, let us create a process by using the given form editor.
From the “4. Basic Example Process”, we reconstruct the form based “Trouble Ticket” Process.
First of all, users need to create desired forms and register the created forms as a “Process Variable” which is used in “FormActivity”.
The following [Figure 6-37] shows the process that we reconstruct.
Form Creation
For creating forms, we need to right-click on a preferred folder of the “Definitions” tree. A popup menu appears on the focused folder, select the “New” menu, and an extended cascading menu appears, and select the “Form” from the sub menu. As a result, the form editor is automatically executed. The form editor helps users either construct useful forms by drag and drop supported various controls onto the workspace below or write scripts directly onto the workspace in source mode. (For more detailed usage of writing scripts, see in the chapter 23)
Form Editor like [Figure 6-38] requires an “Alias”, so a unique form alias must be entered. After completing form design, the “Save Page” button needs to be clicked.
Trouble Description
This form receives trouble descriptions by users. In Figure [6-39] , necessary controls are placed in the form, and the controls are defined like the [Table 6-4] below. Assign “TroubleTicketForm”to the Alias of this "Trouble Ticket Form".
Table 6‑4 Trouble Description Form
| Control Name | Variable Name |
| Calendar Control(Receipt Date) | receiptdate |
| Calendar Control(Due Date) | duedate |
| Input Field(Department) | part |
| Input Field(Name) | name |
| Input TextArea(Trouble Description) | difficulty(Columns: 80, Rows : 5) |
People in Charge for the task
This form helps users select people in charge for the task. The ways to configure the form are the same way that the “Trouble Description” form has. Assign “RoleAssignmentForm” to this form’s alias.
Table 6‑5 The form of Selecting people in charge
| Control Name | Variable Name |
| Calendar Control(Receipt Date) | receiptdate |
| Calendar Control(Due Date) | duedate |
| Input Field(Receipt Department) | part |
| Input Field(Name) | name |
| Input TextArea(Trouble Description) | difficulty(Columns: 80, Rows : 5) |
| Control of selecting People in charge | rightperson |
Trouble Ticket Resolution
From “4. Basic Example Process”, this form is related to the third step, “Role Assignment”(Assign people in charge). Receipt Date, Receipt Department, Trouble Description get mapped with the values of the form. More detailed value mappings will be brought up in the process configuration part. For this form, we give an alias name with "TroubleResolutionForm".
Table 6-6 Trouble Ticket Resolution Form
| Control Name | Variable Name |
| Calendar Control(Receipt Date) | receiptdate |
| Calendar Control(Complete Date) | duedate |
| Input Field(Receipt Department) | part |
| Input Field(Name of Person in charge) | rightperson |
| Input TextArea(Trouble Description) | difficulty(Columns: 80, Rows : 5) |
| Input TextArea(Trouble Resolution) | result(Columns: 80, Rows : 5) |
After completing forms, the forms must be set into production by clicking the “Set As Production”. Therefore, users are able to make use of the forms, otherwise, the forms will not be displayed on the selection list of creating process variable.
Participant Definition
Participants can be configured with the same way that “4. Basic Example Process” did. Especially Manager gets mapped with any user(ex, “tester”) via “Role Picker”.
Table 6-7 Role Assignment
| Participant ID | Participant Name(For display) |
| Initiator | Initiator |
| Manager | Manager |
| rightperson | Right Person |
Process Variable Definition
Corresponding process variables must be registered in order for users to utilize useful forms created previously.
Table 6-8 Process Variable Registration
| Process Variable | Form | Process Variable Name(for display) |
| TroubleTicketForm | Trouble Ticket Form | Trouble Ticket Form |
| TroubleResolutionForm | Trouble Resolution Form | Trouble Resolution Form |
| RoleAssignmenForm | Role Assignment Form | Role Assignment Form |
In [Figure 6-42], select the related form and click the “Update” button. All necessary process variables are configured in the same way as below.
Activity Declaration / Flow Configuration
For utilizing Form based process configuration, “FormActivity” is useful. Add a “FormActivity” into the flowchart from the “Document” group from the Activity Type palette located in the top of the “Process Designer”. Activity Name, Roles, Form Process Variable must be configured.
- Opening Trouble Ticket
Like [Figure 6-43], the elements of the “Trouble Ticket” Form must be mapped with Process Variables in order to make use of the form efficiently. In addition, Activity Name and Roles shown in Table 6-9 are configured accordingly.
Table 6-9 Activity Configuration
| Activity Name | Opening Trouble Ticket |
| Responsible Role | Initiator |
| Form Process Variable | Trouble Ticket Form |
- Trouble Ticket Receipt
At this step, managers select people in charge of resolving troubles by the manager after receving trouble tickets. Necessary Activitiy configuration is the same as previous step, ‘opening trouble ticket’. However, all necessary elements of this ‘Role Assignment Form’ need to get mapped with the elements of the previous form, ‘Trouble Ticket Form’. It is also known as Data Mapping.
The ways to conduct mapping between these 2 froms that include “Trouble Ticket Form” and “Role Assignment Form” are simply explained. The right hand side of the FormAcitivity receives the values of elements which link with relevant elements from the left hand side. The values of Receipt Date, Department, and Trouble Description for the “Role Assignment Form” are automatically shared by the “Trouble Ticket Form”. For the person in charge, the ‘rightperson’ process variable must be mapped with rightperson in the “Role Assignment Form”
Table 6 10 Activity Configuration
| Activity Name | Trouble Ticket Receipt |
| Responsible Role | Manager |
| Form Process Variable | Role Assignment Form |
- Solving Trouble Ticket
This step conducts that the person in charge resolves the requested trouble. The values of Receipt Date, Department, and Trouble Description for the “Role Assignment Form” are automatically shared by the “Trouble Ticket Form”.
Table 6-11 Activity Configuration
| Activity Name | Solving Trouble Ticket |
| Responsible Role | Right Person |
| Form Process Variable | Trouble Resolution Form |
- Closing Trouble Ticket
After solving troubles by people in charge, managers need to view the result. It displays the contents resulted from the third form, “Trouble Resolution Form”. Therefore, there is no additional form required. Only related process variables need to be created.
Table 6-12 Activity Configuration
| Activity Name | Closing Trouble Ticket |
| Responsible Role | Manager |
| Form Process Variable | Trouble Resolution Form |
- Solved Trouble Ticket Confirmation
This step allows the Initiator to view the result of the trouble ticket. At this step, we only need to configure only related process variables connected with the third form, "Trouble Resolution Form".
Table 6-13 Activity Configuration
| Activity Name | Solved Trouble Ticket Confirmation |
| Responsible Role | Initiator |
| Form Process Variable | Trouble Resolution Form |
- Implementation of Multiple Value Edition
The functionality of multiple value edition is like an online invoice which contains many items listed and provides an automatic line addition for users when an additional item needs to be entered to the system.
With a simple HTML manipulation, the implementation is simply made. Moreover, the values of added rows do not need to get mapped so as to transfer them to a different form. Like [Figure 6-48] the “AddRow” control button can be placed in the “Trouble Description” field of the “Trouble Ticket Form”. As a result, users are able to take advantage of its edition functionality for multiple values.
Multiple value entry
Transfer Multiple Values
In order to transfer the values of added rows which are automatically created, the parts that you want to transfer needs to be surrounded by <input:foreach variablename=”the control name”> and </input:foreach>. It is similar to HTML tags which come in pairs, an open and a close tag. The following [Figure 6-49] easily explains that the “TextArea” html tag is surrounded with “foreach” tags.
In addition, if the inside of the “foreach” is composed with input, TextArea, or other controls, only one among many control fields needs the value of variablename within the “foreach” script. The values of all other fields will be transferred automatically.
The configuration of this functionality is the same as a single mapping that one representing variable gets mapped, and the values of multiple rows will be transferred automatically.
The following [Figure 6-50] and [Figure 6-51] explain that in the Ticket Description field, users add one row and complete the form. At “Trouble Ticket Receipt”, we will learn that all the multiple values are automatically transferred.
Processes between Process Participants - Workflow
Flow Control for Conditional Branches
At this chapter, let us practice an extended version of “Trouble Ticket Process” which has conditional branches that have different task flows based on their trouble type. Our expecting process looks similar to the following figure [Figure 7-1] shown below.
The figure [Figure 7-1] shows that if a trouble type is either “S/W” or “H/W”, it will perform the following tasks that we practiced earlier. For “Request for improvement”, it skips the tasks and performs the last task of the process.
Define Execution Block for Conditional Branches
For building conditional branches, we take advantage of “SwitchActivity” in the “Flow Control” located under the second “Control” tab menu of the “Process Designer”.
For creating conditional branches, the related icon, “SwitchActivity” must be clicked and drag & drop it into an appropriate location where it is executed in the flowchart. Configure corresponding conditions. Subsequently, necessary activities are also defined accordingly as so to execute conditional branches. First of all, like the [Figure 7-3], drag and drop the corresponding activities into the conditional branch block.
Let us define another execution block for the second condition. First of all, click the “SkipActivity” from the “Activity Type Palette”, and it will be placed in the execution block by drag and drop.
In order to place the empty task Activity, “SkipActivity” into the second execution block, like [Figure 7-5] drag the “SkipActivity” and drop it onto the “SwitchActivity” icon(
).
After locating all the acitivities into desired places, click the label of execution block(default is condition0), and configure the same way as follows.
- The first execution label : S/W or H/W
- The second execution label : Request for Improvement
Eventually, we complete building basic execution blocks for the process with conditional branches.
Configure Conditions of Conditional Branches
Form now on, we need to make conditional branches executable when data is submitted via completed forms by users. The first activity, “Opening Trouble Ticket” receives values. Finally, we are able to configure conditional branches with them. After clicking the “Problem Type” process variable found on the bottom of the “Process Designer”, there are 3 configured choices that can be displayed while opening a trouble ticket.
| Value | Type |
| Software | Systemic Problem |
| Hardware | Hardware Problem |
| Req_for_improvements | Request for Improvements |
For System or Hardware problem type, it executes the first upper conditional branch, otherwise the second conditional branch is executed for the case with “Request for Improvements”. In the conditional branch property window, make sure that the first label is displayed on the first corresponding “Case” row. Open another property window by clicking on the “Conditional1” cell located in the first row, and configure properties accordingly.
Let us configure conditions for either SW or HW. Like the figure, [Figure 7-8] shown below, while keeping the property window open, select the process variable, “Problem Type”, and click on the “Direct Value” radion button, and select the “Text” data type, and finally enter the value with “Software” in the displayed input box.
The first two conditions execute the same branch block, so another condition for “Hardware” must be added in the same way as we did for “Software” earlier. As a result, they become an OR condition, and the OR condition requires that any of these conditions must be met for the first block execution.
At last, we select the “Otherwise” for the last “Request for Improvement” condition. If a condition does not belong to either“Software” or “Hardward”, it will follow the second execution block.
Let us take a practical test after deploying all the details that we discussed.
With the execution result above, it shows that the process moves to the first conditional block.
At this time, we will practice executing the second conditional block resulted from other cases that do not belong to either “Software” or “Hardware”, therefore it requests for improvements.
If a problem type is the case of “Request for Improvements”, it executes the second conditional branch that includes the empty and the last task, and it finishes the whole process. The conditional branch has the core functionality that helps users to implement decision making in business processes, therefore users need to practice for making good use of the functionality more comfortably.
Flow Control for Conditional Branches
Loop (Request for improvements)
At this chapter, if a problem type is neither “Software” nor “Hardware”, it conducts the second condition, “Request for Improvements”, so a user requests a proposal, and the code block of requested proposal keeps repeating until the proposal is approved by the manager. Throughout this task, we are able to learn this “Loop Control flow”.
Before moving onto the details for the second case, “Request for Improvements”, we need to remove the empty task, “SkipActivitiy” that we created earlier, and create necessary activities based on the following table. From the “Flow Control” menu, we need to add a “Loop Activity”, and then 2 human work Activities can be placed in the “Loop Activity”. It is very simple as it is, so we will skip the steps of flowchart creation. Additional process variables along with their configurations are as follows.
- Process Variable Definition
| Process Variable ID | Process Variable for Display | Process Variable ID | Process Variable for Display |
| Proposal | Proposal | Text | TextAreaInput(Cols : 80 , Rows : 5) |
| IsApproved | Is Approved? | Yes or No |
- Activity Definition
| Activity | Role | Parameters |
| Proposal | Right Person(Tester) | Proposal |
| Approval | Manager | Proposal (in), IsApproved |
For the “Proposal Activity”, the right person is not defined yet. Therefore, by using “Role Picker”, role must be mapped with a specific person(direct-mapping).
- Loop Flow Activity Definition
| Conditional Process Variable | Condition | Value |
| IsApproved | == | No (Direct Value) |
After completing the process like the figure above, click the “Deploy” button, and initiate this process via Web browser. At the step of approving the proposal, click “no” for the “Is Approved?” field, and the task block keeps repeating after “no” is clicked.
Sub Processes
Sub Process Definition(Request for Improvements)
Users can request proposals for the functional improvements of their trouble tickets. There are two ways resolving this request. Like [Figure A], related activities can be easily placed in the second conditional block. Otherwise, a sub process can be useful for this situation. Like [Figure B], additional processes can be separate from the current process, and complete the whole process.
The followings are several advantages if we use sub processes.
- Sub Process can be used in various main processes if needed(Recyclability).
- Large and complex processes can be broken down into smaller sub processes, and it can be structured. Moreover, users can understand complex processes much easily (Better Understanding).
First of all, let us create a sub process for the second conditional case, “Request for Improvements”, which is used in an example.
Locate a “Loop Activity” obtained from the “Control Flow” into flowchart, and then add two “Human Activities” into the “Loop Activity. It is very simple, so the configuration for the flowchart can be skipped. Participants and Process Variable definitions of the sub process will be coveniently created like the following tables.
- Participant Definition
| Participant ID | Participant for Display |
| Drafter | Drafter |
| Manager | Manager |
- Process Variable Definition
| Process Variable ID | Process Variable for Display | Data Type | Inputter |
| Proposal | Proposal | Text | TextAreaInput(Cols : 80 , Rows : 5) |
| IsApproved | Is Approved? | Yes or No |
- Activity Definition
| Activity | Role | Parameters |
| Proposal | Drafter | Proposal |
| Approval | Manager | Proposal (in), IsApproved |
- Loop Control Flow Activity Definition
| Conditional Process Variable | Condition | Value |
| IsApproved | == | No (Direct Value) |
After configuring all the definitions above, the deployment is property executed by clicking the“Deploy” button. Subsequently, the corresponding version is published into production. Otherwise, the process execution is not working as we wish.
Sub Process Configuration
From the “Activity Palette”, Click the “Control” tab menu, and select the “Sub Process Activity”, finally drag and drop the “Sub Process Activity” into the second branch block, and remove the empty activity, “Skip Activity”.
- Sub Process Basic Property Configuration
At this part, we will configure the properties of the sub process. After clicking on the “Sub Process Activity”, the property configuration window appears. By clicking on the second tab menu, we can select a sub process from the process definition list that we have created so far.
VersionSelectOption Configuration'
VersionSelectOption selects a process version which is being used for the process.
- Use the CURRENT production version : the current production version will be used
- Use the production version AT THE INITIATED TIME : The initial version of the process will be used.
- Use the production version AT THE DESIGNED TIME : The version that the corresponding process defintions are designed will be used.
- Use the version JUST SELECTED : The selected version will be used.
At this time, we had better select the “Use the Current production version” for a better maintenance.
Process Variable and Participant Recognition between Sub Process and Main Process
Process variable and participants defined within the sub process must be recognized by the main process, therefore, process variable mappings are required as figure[Figure 7-17] shown below. For the “RunAndForget” field located on the bottom part of the popup window, it asks whether the main process waits for the sub process until the sub process completes its work. Otherwise, the main process does not wait for the sub process, and keep moving forward to next task.
After completing sub process configurations, another deployment is required. We will learn that both the main process, “Extended Trouble Ticket Process” and the sub process, “SubProposalProcess” will be executed accordingly after selecting the third problem type, “Request for Improvements” at the first task, "Opening Trouble Ticket".
Processes between Systems - EAI
Database Connection
Hypersonic DB Configuration
At this chapter, we take advantage of “SQL Acitivity” that helps users record trouble ticket results resolved by technicians, “Person in Charge”. It can be useful as a FAQ that similar troubles are occurred by other users and the same trouble can be solved immediately by using the FAQ database. For the purpose of trouble ticket accumulation, a connection between uEngine and database is required. By using SQL statements, data can be stored and retrieved from the database consequently. Let us practice this by using the uEngine’s default database, “HyperSonic DB. For Hypersonic DB management, doubleclick the “runHSQLManager.bat” located under the directory, “/hsqldb/demo/” after running the “runHSQLServer.bat” executable file. The following figure[Figure 8-1] which is called a “Hypersonic client program” can be shown after performing the instructions above.
Select the “HSQL Database Engine In-Memory” of “Type” field, click the “OK” button on the bottom of popup window. Eventually, the list of database tables will be displayed.
Create a database table with a “TroubleTicket” name. The following table is the script for the table creation.
| Field Name | Data Type |
| Regno | INTEGER |
| ProblemType | VARCHAR |
| ProblemDescription | VARCHAR |
| Resolution | VARCHAR |
Let us get back to uEngine, and we utilize the “SQL Activity”.
SQL Activity
"SQL Activity" can be found in the “Connect” tab menu of “Activity Palette” in Process Designer. By drag and drop, the activity can be placed in the last task of the whole process like the figure[Figure8-2] below. We could change the name of the Activity into “Save to Database” for convenience.
In the property of the Activity, the following SQL statement can be written and transmits it to the database.
insert into TroubleTicket (Regno, ProblemType, ProblemDescription) values (<%=Instance.InstanceId%>, ? , ? )
Copy the SQL statement above and paste it into Sqlstmt text area. Necessary table columns are mapped with variables like the figure[Figure 8-3].
After applying recent changes of the process with deployment, we learn that problem types and problem descriptions are stored into the "TroubleTicket" table in the Hypersonic DB.
Practical Use of URL Form
Web Application Activity
The core functionality of Web Application Activity has Web Application Recyclability which is very useful during WorkItem handler development. Users are able to embed the functionality easily. More importantly, its functionality helps users synchoronize the handling of workItem completion and result recongnition. uEngine provides an interface for processing tasks, but, in order to apply created business processes to users’ organizations, the connection of current complete web sites is necessary in most cases. In this case, with the support of “Web Application Activity”, invoke necessary web pages and handle related results obtained by the use of Web browser URLs.
For practical use of the functionality, we now make a simple version of exisiting “Trouble Ticket” process. We require two URL Linked App Activities including both “Opening Trouble Ticket” and “Solving Trouble Ticket”. They are both connected to an external JSP program.
The following web files are required for the connection between these web pages and the example.
(Installed under the \was\webapps\uengine-web\sample_url_applications\troubleticket).
| File Name | Description |
| Register_index.jsp | Write a trouble report |
| Register_submit.jsp | The resulted description is stored into the DB |
| View.jsp | Display the status of tasks in progress |
Add a “Script Activity” located in the “Control” group under the “Control” tab menu into the flowchart. Configure participants and process variables in the same way as follows.
| Participant ID | Participant for Display | Property |
| User | User |
| Process Variable | Process Variable for Display | Property |
| Regno | Regno | Text |
| ResultURL | ResultURL | Text |
Process Variable, “Regno” contains a unique ID value that distinguishes among different trouble tickets requested by users. Additionally, “ResultURL” is another process variable keeping the address values of URLs resulted on browsers.
Report Trouble, URL Activity
Open the Web Application property window, and check the values.
| Item | Value |
| URL | web page address which is being invoked |
| URLWhenSuccess | A bridge web page so as to move to the next activity (If the configured page is displayed, it is considered that the task is successfully completed.) |
| ResultURLPV | A process variable keeps the value of URL when the activity completes. |
When the activity, “Opening Trouble Ticket” is executed, problem types and descriptions are obtained on the “register_index.jsp”. After then, the results are transferred to the database. The final page, “view.jsp” is displayed if the activity is successfully completed.
| Item | Value |
| URL | /uengine-web/sample_url_applications/troubleticket /
register_index.jsp |
| URLWhenSuccess | view.jsp |
| ResultURLPV | ResultURL |
Select “Initiator” for the role, and apply the changes.
Parsing for the results via Script Activity(Parsing)
At this time, let us practice how to use Script Acitivity which is essential functionality for “Form Control”.
The process variable, “ResultURL” contains the URL address resulted when the previous activity completes. A trouble ticket is stored into the database, the unique Regno value is included to URL, so the process requires parsing at the next page. Therefore, Regno can be referenced everywhere. From “register_submit.jsp”, we need to obtain the “Regno” value, and the following script is the parsing needed for the purpose.
| Script |
| var resultURL = instance.get("ResultURL"); var key = "regno"; var regno = resultURL.substring(resultURL.indexOf(key)+key.length+1); return regno |
The script gets the value cut right after “regno=” of the string. At last, the property of basic information display should be “Yes” and both “Apply” and “Deploy” buttons should be clicked for applying recent changes.
- Writing resolution’URL : Process Start Screen after application implemented.
- Process values after completing the first task
Figure 8-9 Execution Result
By the process variable page, we are able to learn that the process variable,“Regno” is obtained from the “ResultUrl” after parsing.
Other Types of Processes
Role Processes
BRE(Business Rule Engine) is a system that takes business requirements in a fast and correct way, because business rules are separate from applications. This separation also helps users manage and define business rules more efficiently. At this time, the goal is creating a process that helps users make decisions automatically based on the decision tables. For a better understanding of this point, a process follows rules which simply can be explained with a situation where people follow the rules and laws of the organization after joining to an organization. At this chapeter, we will practice with an insurance task that conducts pricing the insurance coverage based on the subscriber’s conditions. The resulted information including the insurance coverage can be stored into database, or after getting approval by the person in charge, the information finally transfer to the database and the information saved into database. The process we need to struct is the following.
Policy Pricing Decision Process
1-1. Policy Princing Decision Process(Rule Engine)’s Structure
The figure [Figure 9-3] is an essential decision table that helps users calculate the amount of basic insurance coverage. With this, we are able to construct the basic decision process.
Decision Process‘s Process Variable Configuration
Configure in the same way as the following table shows.
Table 9-1 Process Variables
| Process Variable ID | Process Variable for Display | Data Type | Default Value |
| age | age | Number | - |
| BasePrice | BasePrice | Number | - |
| LocationRiskProfile | LocationRiskProfile | Text | - |
| PriorClaims | PriorClaims | Number | - |
| Type | Type | Text | - |
Activity Configuration
Add an “AssignActivity” into the [Conditional Branches], “Switch Activity”, and configure conditions and values along with scripts for each conditional branch.
Enter the value of the process variable, [BasePrice] after clicking the “AssignActivity”
- ex) AssignValue: 800
- Variable: BasePrice
With the following table, configure the conditions of the “SwitchActivity”.
Table 9-2 Configuration of the Conditional Branches
| No | Case | Condition1 | Condition2 | Condition3 | Condition4 | Condition5 |
| 1 | 450AUD case | age>=18 | age<=24 | LocationRiskProfile == LOW | PriorClaims==1 | Type == COMPREHENSIVE |
| 2 | 200AUD case | age>=18 | age<=24 | LocationRiskProfile == MED | Type == FIRE_THEFT | |
| 3 | 300AUD case | age>=18 | age<=24 | LocationRiskProfile == MED | PriorClaims==0 | Type == COMPREHENSIVE |
| 4 | 300AUD case | age>=25 | age<=30 | PriorClaims==1 | Type == COMPREHENSIV | |
| 5 | 150AUD case | age>=18 | age<=24 | LocationRiskProfile == LOW | Type == FIRE_THEFT | |
| 6 | 150AUD case | age>=18 | age<=24 | LocationRiskProfile == LOW | PriorClaims==0 | Type == COMPREHENSIVE |
| 7 | 700AUD case | age>=18 | age<=24 | LocationRiskProfile == MED | PriorClaims==1 | Type == COMPREHENSIVE |
| 8 | 700AUD case | age>=18 | age<=24 | LocationRiskProfile == HIGH | PriorClaims==0 | Type == COMPREHENSIVE |
| 9 | 550AUD case | age>=18 | age<=24 | LocationRiskProfile == HIGH | Type == FIRE_THEFT | |
| 10 | 120AUD case | age>=25 | age<=30 | PriorClaims==0 | Type == COMPREHENSIVE | |
| 11 | 590AUD case | age>=25 | age<=30 | PriorClaims==2 | Type == COMPREHENSIVE | |
| 12 | 800AUD case | age>=25 | age<=35 | PriorClaims==3 | Type == THIRD_PARTY | |
| 13 | Otherwise |
Like [Figure 9-5], check “No” for the “InitiateFirstWorkItem” field, and click the “Deploy”.
1-2 Policy Pricing Configuration of an insurance company
Configure activities like the figure , [Figure 9-6] shown below.
Configuration of Process Participants and Process Variables
For process participants, add [User] and [Mananger]. The [Manager] gets mapped with [Members in the group with id 1] with the support of Role Picker”. The process variables are as follows.
Activity Configuration
- Input Profile Information
The figure, [Figure 9-1] shows that the participant and parameters are configured with “User”, “age”,”LocationRiskProfile”, “PriorClaims” relatively.
- Fire Rule
The process, “Policy Pricing Decision Process” we made ealier is added into this “Insurance” process as a sub process. Therefore, related process variables are required to get mapped with each other. The direction of the process variable, “BasePrice” should be “out”.
- Select Insurance Type
For participant, select “User” and “Type” and “BaseType” process variables are added into the third task, “Select Insurance Type”.
- Fire Rule
It should be the same as the first “Fire Rule” above. Simply copy the first one, and paste into the flowchart.
- Conditional Branches
The label of the first condition for the Conditional Branches is “Case1: Price is greater than $300”. The second one is “Case2: Price is less than $300 or equal to $300. Configure the same way as the figure shows below.
| No | Case | Condition1 |
| 1 | Case1:Price is greater than $300 or equal to $300 | BasePrice >= 300 |
| 2 | Case2:Price is less than $300 | Otherwise |
Table 9-3 Conditional Branches
- Confirm by Manager
The participant, "Manager" is responsible for this task, all process variables are required to be added through the [Parameters] field. The direction of all the process variables must be “in”.
1-3. Process Execution
Initiate the completed process, “Insurance Process”. Enter “30”, “LOW”, “1” for the process variables, “age”, “LocationRiskProfile”, “PriorClaims” respectively. After that click the “Complete” button.
Enter “COMPREHENSIVE" for the “Type” field, and click the “Complete” button.
The figure above, [Figure9-16] shows that if the “[BasePrice]” based on the rules is greater than $300 or equal to $300, the manager confirms the result, and approves the case by clicking the “Complete” button. The process is finally completed. On Instance List page, the following figure[figure 9-17] is found if we search excuted processes with a criteria which the [BasePrice] is $450 for instance.
Page Flow Processes
Page flow is an action that the same person receives tasks in a row and completes the tasks respectively when a process is in progress. In general, a new task is assigned, the assigned works can be found by clicking another tab menu. However, it looks like a current web page turns to another web page smoothly. Therefore, the second task page shows up on the screen, and enables users to complete tasks more efficiently. Let us take a practice with a following “Cellphone Process”. As a result, we will be able to understand the Page Flow Process in a better way.
2.1 Structure of Cell Phone Subscription Process
We struct the cellphone process in the same way as figure[Figure 9-18] shown below.
2.2. Configuration of Process Variables and Participants
Participants: [Initiator], [Approver] - [Approver]: Mapped with [Members in the group with id 1] by Role Picker.
Process Variable Configuration [AgeofSubscriber]: Date Type [EstimatedFee], [ExistingPhoneNumberCnt]: Number Type [IsDMB], [IsApproved], [IsUnpaid]: Yes or No Other Process Variable: Text Type [ActualUser]: Text, select the radio button type for Inputter. For “Values” and “Selections”, enter “For him/herself”, “For Other Person”, and “For Underage Person”.
2.3. Activity Configuration
1. Subscription Information Entry
- Roles: Add “Initiator”, for parameters, add “CustomerName”, “AgeOfSubscriber”, “aid”, “CustomerType”, “WishingNumber”, “RealCustomer”, “ TerminalModel”, and “IsUnpaid”.
2. Conditional Branches(1)
For the first conditional branch, we configure 2 condtions that are “Case1: Not Perfect Credit Customers who have ever Unpaid Bills”, “Case2: Excellent Credit Customers always Pay Bills on time”. The following figure shows the configuration.
| No | Case | Condition1 |
| 1 | Not Perfect Credit Customers who have ever Unpaid Bills | IsUnpaid == Yes(Yes or No) |
| 2 | Excellent Credit Customers always Pay Bills on time | Otherwise |
Table 9-4 Conditions of Condtional Branch(1)
3. Report for Approval
For the role of this task, assign “Initiator”, and Enter “This customer is not qualified to subscribe because of [<%=UnpaidResult%>].
Click "Complete" to escalate for this matter.” for the task instruction.
4. Approval
For this task, “Approver” is assigned as a person in charge. For parameters, add “CustomerName”, “AgeOfSubscriber”, “ActualUser”, and “TerminalModel”. Configure the “Direction” with “in”, for the “UnpaidResult”, “IsApproved”, Direction should be set with “in-out”.
5. Conditional Branches(2)
For conditions of this conditional branch, configure with “Case1: Approved”, “Case2: Rejected.
| No | Case | Condition1 |
| 1 | Approved | Rejected |
| 2 | Approve == Yes(Yes or No) | Otherwise |
Table 9-5 Conditions of Conditional Branches(2)
6. ApprovalRejected(MessengerActivity)
Select the “Initiator” for Recipient, Because customer "<%=CustomerName%>" has an issue related to <%=UnPaidResult%>, so notify this to the customer.” in the “Contents” field.
7. Conditional Branches(3)
For conditions of this third conditional branch, configure with “Case1: For Other Person”, “Case2: For Underage Person”, and “Case3: For him/herself.
| No | Case | Condition1 |
| 1 | For Other Perseon | ActualUser == For Other Person |
| 2 | For Underage Person | ActualUser == For Underage Person |
| 3 | For him/herself | Otherwise |
8. For both Actual User Information Entry, Guardian’s Information Entry, participant should be the Initiator, and no parameters required. We assume that there are necessary forms needed, but we skip the details for this time.
9. Loop Configuration
Configure “existingPhoneNumberCnt >= 1” on the “Condition1” cell.
10. Phone Number Selection(Whether the desired phone number for subscriber is already taken by somebody else). By using “SQLAcitivity”, we select the direct setting for ConnectionFactory. Configure in the same way as the figure shows below.
| UserID | sa |
| DriveClass | org.hsqldb.jdbcDriver |
| ConnectionString | jdbc:hsqldb:hsql://localhost:1701 |
| SQL Statement | select count(*) as existingPhoneNumberCnt from mobileAccount where phoneNumber = ? |
Table 9-6 Check Duplicate Phone Number
11. Change Message(Script Activity)
Enter this javascript message, “instance.set("errMsg", "This phone number is already used by another subscriber. Please choose another number");” on the property window of the “Script Activity”.
12. Subscription Registration(DB Mapping Activity)
Enter a tablename with “mobileaccount”, process variables, CustomerName and WishingNumber should be mapped with SUBSCRIBER, PHONENUMBER respectively.
2.4. Process Execution
Execute the “Cell Phone Subscription Process”. Fill out the following.
From the whole flow, we learn that the same participant keeps moving forward with stopping, so the participant does not need to look for next assigned tasks.
Exceptional Processes
Multiple Instances
- Multiple Instance Configuration
The functionality of “Multiple Instances” is creating more than 1 sub processes at the same time, and the number of sub processes is dynamically defined based on for instance, number of participants or number of process variables. For example, the purchase order process, the consumer requests quotations of purchase orders to various suppliers who need the same processes simultaneously. However, the most of existing BPMS are not able to handle multiple instances, so they overcome these difficulties via programming such as scripts, SI(System Integration). With uEngine’s Multiple Instance functionality, we can simply solve these difficulties through configuration not with programming.
From the previously created Trouble-Ticket process, we will change the role of “Manager” into “Trouble Manager” group.
In addition, for sub process participant's mapping, mangers from both main and sub processes get mapped each other. Like figure[Figure 10-2], the field, “ForEachVariable”, we select the manager”.
From the [Report trouble] task, select the “Request for Improvement” and click the “Complete”. The figure [Figure10-3] shows that various instances created from the “InstanceId of sub process”.
Event Handling (ScopeActivity and Event Handler)
“ScopeActivity” enables users to control various activities that we have created so far by tying them all together into a group. Included activities within the scope have the same event handler which makes the main process stop at any time, and execute sub processes or perform defined tasks. Let us practice this “ScopeActivity” with a simple example.
- Add “ScopeActivity” into Trouble-Ticket
The purpose of this example is that a person in charge receives trouble tickets and resoloves the issues via two steps of approvals and finally completes the process. If managers responsible for approvals of trouble tickets turn down any of two trouble tickets, the task moves back to the one where the person of charge writes a new resolution for the issues all over again.
Like [Figure 10-5], add one ScopeActivity into the flowchart, especially right after the “Handle Trouble Ticket” task, and Add two Human Works named “Approval1”, “Approval2”. Below the scope, add a sub process on the Event handler area. This sub process is being executed anytime even both “Approval1” and “Approval2” included within the scope are executed.
At this point, write a new process that links with the added sub process, “Improvement Rejection”. Let us create a new process in the same way as follows.
By making use of “BackActivity” from Activity Palette, the process goes back to the previous task, “Handle Troubles” where the person in charge handles requested trouble tickets. The properties of “BackActivity” are configured like the following figure below.
| Item | Value |
| TargetActivityPV | |
| TargetActivity / InstanceId | <%=Instance.MainProcessInstanceID%> |
| TargetActivity / TracingTag | 3 (Target Activity tracing tag number. In this case, 3 is the tracing tag of the previous task, “Handle Troubles”, so, the correct tracing tag must be entered.) |
TracingTag is a unique address pointer where the current task goes back to the location chosen. The values of tracing tags are found in the “Basic Properties” of selected activities.
We finally complete the “Approval Rejection” sub process. Click the “Deploy” button, and changes that we have made so far can be applied to the server. If the uEngine version is older than 3.5.2, the current version must be published into production. (Required)
From now on, let us return to the main process, and needs to register the sub process we just created above.
Let us make sure that this approval is working correctly. Execute the process, and select “system” for problem type, and explain the problem in detail. After submission by users, the person in charge handles the issues, and writes the resolution for the trouble ticket. From the figure below, we are able to see that the process is still running and currently working for the “Approval1” task.
Open Manager’s workitems, we will see that “Approval Rejection” button is displayed.
With the following figures we are able to see that the sub process completes its works, and returns to the main process when the “Approval Rejection” button is clicked.
Compensation Handling
- Compenstation Handling
Compensation Handling is used that the process goes back a specific work item by the request of user or system while the process instance is in progress. If it happens, all the work items processed between the current task and the task where it goes back to must be back to the original in the same way as if the changes have never made.
Our expected “Compensation Handling process is like the figure[Figure 10 9] displayed below. After entering all the information needed from the “Report Trouble”, click the “Complete” button. At the “Insert into DB” task, information is inserted into “TroubleTicket” table. In that case, the flow goes back to the first task, “Report Troubles” by users, delete the current data from the “TroubleTicket” table, and finally the flow moves back the first task.
For participants, we only use “Initiator”, the process variables are as follows[Table 10 1].
| Process Variable | Data Type | Process Variable for Display | Inputter |
| ProblemType | Text | ProblemType | |
| ProblemDescription | Text | Problem Description | TextArea(60,5) |
Both “Trouble Report” and “Confirmation” acitivities are configured as follows[Table 10 2].
| Activity | Role | Parameters |
| Trouble Report | Initiator | ProblemType, ProblemDescription |
| Confirmation | Initiator | ProblemType(in), ProblemDescription(in) |
For “DB Insertion” activity, [Figure 10 10] and [Table 10 3] can be refereced.
| Activity | SQL Statement | Parameters |
| DB Insertion | insert into troubleticket(instid,problemtype,problemdesc) values(<%=instance.instanceId%>,?,?) | ProblemType, ProblemDescription |
| Confirmation | delete from troubleticket where instid='<%=instance.instanceId%>' |
Configure “DB Deletion” activity as well by using [Table 10-3]. Finally, ScopeActivity can be configured by using both [Figure 10-11] and [Table 10-4]. After configuring both activities, Deployment is followed, at last, execute the process.
| Item | Value |
| TriggeringMethod | When the scope is compensated |
| OpenRoles | Initiator |
| Name | compensationHandling |
| DisplayName | CompensationHandling |
After executing the process, necessary information is entered at the first task, “Trouble Report”. At the last task, “Confirmation”, the executed information is confirmed. Like the figure[Figure 10-13], an inserted record can be viewed by connecting to the Database.
Like [Figure 10-13], check the entered information. In another way, like [Figure 10-14] at the last task, “Confirmation”, we return back to the first task, “Trouble Report” by clicking the “Back” button displayed on the flowchart.
As figure[Figure 10 15] shown below, the flow returned back to the first task, “Trouble Reprot”, and we are able to check the record which we were able to check at [Figure 10 13], was removed by looking at figure[Figure 10 16].
Exceptional Handling
- Fault Handling
Fault Handling is an action when a specific activity has an error during the process, so users such as administrators will be immediately notified.
In an example, [Figure 10-17], Let us configure that if the “DB Update” Activity is in failure, let managers know the error message via Messenger Activity.
Process variables, participants, “Trouble Report”, and “Confirmation” except for “Scope Activity”, “SQL”, “Messenger Activity” are configured in the same way as the “Compensation Handling” had previously. So the ways of detailed configuration will be skipped.
| Activity | SQLStatement | Parameters |
| DB Update | update troubleticket set problemtype=? , problemdesc=? where instanceid='<%=instance.instanceId%>' | ProblemType, ProblemDescription |
Like [Table 10 5], configure “DB Insertion” activity in the same way as the table describes. In SQL statement, the column, instanceid does not exist in the database. Therefore, users will be notified that an error is occured when this DB Insertion activity is executed. The figure[Figure 10 18] shown below has the configuration information of Messenger Activity. We just need to follow the instructions. After clicking on the “Messenger Activity” the property window pops up, and clicking the second tab, type this message, “An error occurred while trying to update the table.” for the “Contents” field. At last, configure the “ScopeActivity” based on the figure [Figure 10 19] and the table [Table 10 6]. After configuration, click the “Deploy” and execute the process.
| Item | Value |
| TriggeringMethod | When one of child is in fault |
| OpenRoles | Initiator |
| Name | faultHandling |
| DisplayName | FaultHandling |
After initiating the process, “Trouble Report” will be successfully completed, however, the”DB Update” activity occurs an error and users will be notified by the “Notification to Manager” activity. An Error Notification email will be delivered.
Practical Use of Process Modeling
In Part3, we learned modeling techniques by extending the good example, “Trouble Ticket” process. In Part4, we improve our ability of implementation on process modeling via various practical examples.
Sales Order Contract Management
Task Description
The most important goal for many companies is generating income via sales. One part, “Sales Order Contract Management” in Sales decides whether the order is beneficial for companies. Throughout the whole process, companies review approximate income that can be generated. In advance, it helps companies calculate reasonable quotations that keep from risking by reckless order contracts and quotations. Therefore, companies are able to generate more profits than without the process.
By creating a process for the whole activities mentioned above, we learn how the process can be useful in actual business activities. For a better understanding of this process, we will make use of a simple task happened in a small business as a model.
A flow of “Sales Order Contract Management” includes that a sale person receives orders and report them to a manager. After getting an approval from the manager, a person in charge of quotation completes the quotation forms. Finally, the sale person receives the requested quotation form, and it finishes the whole process.
Process Scenario
- A sales person reports an order description
- A president reviews the order, and makes a decision abount taking the order, and asking an estimator for a quotation.
- After receiving the order, the estimator completes the quotation form based on the order taken by the sales person, and report the quotation form to the president.
- The president makes an approval decision whether the quotation is reasonable for the company.
- Approved quotation form is delivered to the sales person and finishes the process.
Process Defintion
Summary of Process Definition
| Order Report | Order Review | Write Quotation Form | Quotation Review | Result Notification | |
| Participant | Sales Person | President | Estimator | President | Sales Person |
| Process Variable | IsOrderApproved | IsQutationApproved | |||
| Form | Order_Report_Form | Order_Report_Form | Quotation_Form | Quotation_Form | Quotation_Form |
For order approval, there are two ways we can have for the result. The first one is the “Quotation Request” after getting an approval by the president. The second one is that the order can not be allowed. For quotation approval, the decision can be made whether filling out another quotation form is needed again for the same order.
Form Creation
We need two forms(“Order Report”, “Quotation”) before creating a process. Two form need the same basic information such as “customer name”, “phone number”, “project name”, and “a person in charge”. So we take advantage of the one that we created first. For approval, radio buttons must be inserted into each form.
| Entry Field Name(Form) | Order_Report_Form(Order Report Form) | Quotation_Form (Quotation Form) |
| Quotation_Form (Quotation Form) | y / n | y / n |
- For entry fields, the field names must be alphanumeric (space, special characters are not allowed)
Participant Definition
Let us define participants required for the process. A person who reports an order to the manager is a sales person(the process initializer), an estimator who completes the quotation form, and a president who approves both “order report” and “quotation” forms, so three participants get involved in the process.
| Participant ID | Participant Name for Display |
| Initiator | Sales Person |
| President | President |
| Estimator | Estimator |
There is only one president working in the company, so we select the persident(special user) directory by selecting the first tab menu, “Direct Mapping” of the Role Picker. The title of the estimator is Manager, so we select Manager for the participant by selecting the second tab menu,”By Role” of the Role Picker.
Process Variable Definition
Two forms(Order Report Form, Quotation Form) that we created ealier must defined as a process variable. The last values, “Approved/Rejected”, on each form required for deciding whether the proposal is approved or rejected are also declared additionally, because the values included in the forms(internal values of the forms) can not be a direct process variable. Therefore, additional process variables must be mapped with values existed in the forms.
| Name | Data Type | FormDefId(Defined Form) | Process Variable Name for Display |
| Order_Report_Form | Html Form | OrderReportForm | Order Report Form |
| Quotation_Form | Html Form | QuotationForm | Quotation Form |
| Order_Approval | Text | Order Approval | |
| Quotation_Approval | Text | Quotation Approval |
Process Flow Definition
First of all, define “Order Report” and “Order Review” activities. Two activities need forms, so we selecte two FormActivities from the Activity Palette, and drag & drop them into the flow chart. After clicking each activity, select a relavant form that we created earlier for “VariableForHtmlFormContext” field located under the second tab menu, “FormActivity”.
| Activity | Order Report | Order Review | Write Quotation Form | Quotation Review | Result Notification |
| Participant | Sales Person | President | Estimator | President | Sales Person |
The other three tasks including “Write Quotation Form”, “Quotation Review”, and “Result Notification” can be composed with “FormActivity”. At these steps, all the process variables of basic information are passed from the “Order Report Form” by mapping. Let us define a flow of the process. First of all, after completing “Order Review” with an approval by president, the step moves to the “Write Quoation Form”, otherwise, the process stops moving forward. From “Write Quotation Form” to “Quotation Review”, it keep repeating until a quotation approval is made by the president.
Taking one of the possible branch paths or conditioning loop requires an approval made on the “Order Review”, “Quotation Review” forms respectively. So each approval field on forms needs to get mapped with a created process variable correspondly.
| Activity | Form Field | Process Variable |
| Order Review | order_apr (radio button of Order Review Form) | IsApproved(Order Review) |
| Quotation Review | IsApproved(radio button of Quotation Review) | IsQuotationApproved(Quotation Review) |
Based on the result of order review approval, the flow moves to the task of “Write Quotation Form”. If the values is ‘n’, the process stops, otherwise, the next task will appear on the screen.
| Case | Condition |
| Approved | IsApproved == (Direct Value) y |
| Rejected | otherwise |
A quotation created by the estimator must be approved by the president. If the president is not satisfied with the quotation, loop starts working, so the configuration of loop condition is needed. If the condition is ‘n’ , the estimator fills out another quotation form again.
| Condition1 | IsQuotationApproved == (Direct Value) n |
After completing this, we finally complete the process design. After deploying, our definition will be found on the list of Definitions.
Process Enactment
"'Order Report' and 'Quotation' tasks for a Sales person, assistant manager Mr Kim in A corporation"
An assistant manager, Mr. Kim got an order from B corporation, and connected to the system of A corporation, and starts the “Sales Order Contract Process”, and filling out the first task, “Order Report”.
The president of A corporation, reads the “Order Report” made by the assistant manager, Mr. Kim, and decides whether the order is profitable for the corporation. If it is reasonable, then approves it, otherwise rejects the request. However, in this case, we assume that the corporation had better take the opportunity, so approves the request.
The approved task is delivered to an estimator, manager Mr Lee, and he fills out a quotation form based on the order taken by the sales person.
A written quotation form is delivered to the president. After reviewing the quotation, he approves the quotation because the quotation is very reasonable for the corporation.
The approved quotation form is delivered to the Sales Person, assistant manager, Mr Kim. He doublechecks the quotation, and finally he completes the contract with B corporation.
Developer Manual
Introduction
1.Introduction
Today’s e-business trend is interactions with network applications like web services. In order for us to follow this trend, we need to be able to integrate business resources in a real time or keep up with fast moving technology. With that reason, uEngine’s component based BPMS provides us to have adaptability and flexibility. uEngine not only supports Business Process Management for companies, but also B2B(Business to Business) and even EAI(Enterprise Application Interface) between applications as an integrated business operating system. uEngine is built based on GNU philosophy with developers’ active and cooperative involvements in development. [Note] This manual is written based on uEngine standalone v3.5.2 version. The followings are essential that you need to understand before moving ahead.
- Workflow Management System
- Web Services (SOAP/WSDL/UDDI)
- J2EE
- Object oriented framework
- JAVA Beans framework and reflection
- Design Patterns
- XML and XML Binding framework (JAXB)
- JSP and simple Portlet
[Note] The component based uEngine follows the unique OKF(Open Kernel Framework) development methodology that supports abstraction, persistence, and tools. Moreover, with efficient and proved workflow methodology, the component becomes formalized. Therefore, users maximize usability in business environment. In conclusion, with the focus on business environment implementation preferences, it attracts developers to deliver recyclable components that have high frequency of use. It definitely differs from other component based development methodologies, frameworks, and templates.
2.Strengths
Unsolved Workflow Problems
Workflow(Workflow Management Systems or Business Process Management Systems) based development helps users reduce burdens on not only business process implementation and design but also process execution and monitoring, and many more. However, there are unsolved issues that the workflow does not cover in development even though it is very easy and efficient.
- Does workflow satisfy all the requirements in development?(Customization Problem)
Even though, workflow supports much functionality needed in development, there are chances that we must add new activity types according to the requirements or changes of business or techniques. Mostly, technical understanding, implementations, and refactoring process are required in order to add new activities into workflow engines. We might be worried about “how we could complete the project before the deadline with limited time, cost, and workflow product supports”. This is a hazard that we might confront during early or in the middle stage of the project.
- Is it recyclable in different environments if we have workflows?(Portability Problem)
All packaged products have the same recycling problems. Packaged applications are well understandable and useful by its engines. However, users are mostly required to re-develop their applications when different environments or applications involved. This also brings a new issue whether workflow is applicable when the project is just initialized.
- Is it well implemented among different types of workflow engines? (Interoperability Problem)
Workflow integration between organizational workflows or B2B(Business to Business) transactions by using process connections is the most powerful feature. In spite of significant efforts toward standardization, it is still difficult to have flexible integrations under different system environments developed in different programming languages along with its own workflow engines.
uEngine Design Principles
With limitation on existing workflow engines, uEngine tries to overcome the unsolved issues with the following two ideas.
1) Component frameworks
2) Apply Web Service design principles.
Component based adaptable/growing engine
In Java development environment such as JavaBeans, EJB, the separation between business logic and techniques is available on component based frameworks under component environment. It also helps developers extend functionality that requires XML, Web Services, Swing, Message Queuing, even EJB that are simply added without understanding of these technologies.
- Component based development methodology : It is supported with a component addition environment like plugin method that keeps applying new technical, functional requirements without engine change. It is possible that the special object oriented structure, OKF(Open Kernel Framework) is installed under the uEngine.
- Especially, not only new features but also new process flow patterns can be extended that basically differ from engines developed by other organizations.
- It helps developers not to make the same mistakes that they already made during the development because experiences that obtained from various projects are effective for them not to make the same mistakes. The topic will be brought up in next development strategy chapter.
Based on Web Services
The process made by uEngine becomes a Web Service as is. Users can benefit from the dynamic integration of WSDL-SOAP Web Service (integration without technical knowledge) and make use of its strengths. It helps other workflow engines integrate with uEngine process in the simple and easy way of Web Services. In addition to that, uEngine is not only for opening processes, but also applying engine development design for the purpose of process implementation between web services.
- XML based Process Variables : uEngine contains XML-type systems for process variable declaration, assignment, and job processing. This also supports fundamental functionalities for data delivery between web services and web services based workflow resource integration management.
- Dynamic Web Service Activity : It provides activity types that help users make use of the detection, integration, and invocation of web services. With these features, users are able to build the Internet business environment successfully.
- Integrated Resource Management : Workflow resources (IT, employees, business partners) are well managed as an integrated resource management with various web services by wrapping. All resources defined within uEngine can be recyclable anywhere.
Architecture
2.Architecture
This chapter explains regarding uEngine design and even overall architecture process models in order for users to understand advanced programming source codes.
System Architecture
uEngine is based on the combination of the most popular architectures.
J2EE is chosen as uEngine system framework
J2EE helps uEngine be operated under the circumstances that include managed transactions, messaging, and managed persistence in the same state of uEngine logic. The following 6 Beans are structured.
- One stateless Bean(ProcessManagerBean) : It is the entrance responsible for receiving service requests such as process management, operation, and external web service invocation.
- Two Message Driven Beans(WorkProcessBean, FaultProcessorBean) : Physically, the process ends.
- Three Entity Beans : Preserve transactional data
All business logic and database entities are not structured by EJB . Actually, OKF(Open Kernel Framework) and JE22 placed in the center of the uEngine are responsible for receiving requests and executing logic by workflow related components, and returning the results. It provides professional component interface to workflow engines. For more detailed description, a separate chapter will be used.
Interface between configured workflow elements via Web Services
uEngine’s sub-structured modules and workflow with the configured elements that contain workflow engine, workflow handlers, email server are separated as much as possible, also these are interfacing by web services. This means that it is easily replaceable by other types of components and becomes the foundation of the system which has potential to be recognized universally. For instance, users are able to use uEngine Process management functionality with their existing portal systems or intranets that interface with the uEngine via supported Web Services, while they keep their comfortable user interfaces
Web Service tools - Axis / WSDL4J / UDDI4J
uEngine creates Web Service stubs at design time by Axis tools invoked by Ant. And then, process definitions are open and being hosted. WSDL4J is used for getting connection information needed for Web Service invocation of Process Designer. For various Web Services search, UDDI4J and uddibrowser(hosted in sf.net) which is the open source UDDI search tool are used.
Persistence – XML Serialization plus Entitiy Beans
In order to preserve XML formatted data, XGen is used to convert Java Objects into XML at run time. The converted XML is saved by Java Beans. uEngine also takes into consideration on adopting Apache Xindice, XML specialized databases for the next version.
Easy approaches on the Internet via Java Web Start
JWS technology is a recent client design methodology that is easy to use. On the Web browser, Process Designer developed by Java Swing is open, and users continue working on it.
[Note] Metaworks is a framework used to create UI(User Interfaces) like Process Designer, Workitem Handlers. For more detailed introduction to Metaworks, it will be brought up in a separate chapter.
Process Manager Interface
For external access, the session bean, org.uengine.processmanager.ProcessManagerBean is supported. The following shows the definitions of Process Manager interface. For overhead issue, uEngine makes use of “Stateless Bean” rather than “Stateful Bean”. It is possible that overhead for resource persistence is avoided with the use of “Stateless Bean”. For the purpose of the issue, process definition names or instance IDs should be passed as arguments when invoking various methods if needed.
[Note : Detailed Interface information, see Appendix C - ProcessManagerRemote API Reference]
//initialize process manager –Process Start related APIs public String initialize(String processDefinition, String instanceId, RoleMapping loggedRoleMapping) throws RemoteException; public String initializeProcess(String processDefinition, String instanceName) throws RemoteException; public String initializeProcess(String processDefinition) throws RemoteException; public String initializeProcessIfRequired(String processDefinition, String instanceId) throws RemoteException; //process execution – Process Execution related APIs public void executeProcess(String instanceId) throws RemoteException; public void executeProcessByWorkitem(String instanceId, ResultPayload resultPayload) throws RemoteException; //process variable – Process Variable related APIs public void setProcessVariable(String instanceId, String scope, String varKey, Serializable val) throws RemoteException; public Serializable getProcessVariable(String instanceId, String scope, String varKey) throws RemoteException; public String getProcessVariableInXML(String instanceId, String scope, String varKey) throws RemoteException; public Hashtable listProcessVariableValues(String instanceId) throws RemoteException; //role – Responsibility/Role related APIs public void putRoleMapping(String instanceId, String roleName, String endpoint) throws RemoteException; public void putRoleMapping(String instanceId, RoleMapping roleMapping) throws RemoteException; public void delegateRoleMapping(String instanceId, String roleName, String endpoint) throws RemoteException; public void delegateRoleMapping(String instanceId, RoleMapping roleMapping) throws RemoteException; public String getRoleMapping(String instanceId, String roleName) throws RemoteException; public RoleMapping getRoleMappingObject(String instanceId, String roleName) throws RemoteException; //messaging, triggering, event, workitem handling – Message, Trigger, Event, Workitem related APIs public Serializable sendMessage(String instanceId, String message, Serializable payload) throws RemoteException; public Serializable sendMessageXML(String instanceId, String message, String payload) throws RemoteException; public void completeWorkitem(String instanceId, String tracingTag, String taskId, ResultPayload payload) throws RemoteException; public void saveWorkitem(String instanceId, String tracingTag, String taskId, ResultPayload payload) throws RemoteException; public void executeEventByWorkitem(String mainInstanceId, String eventName, ResultPayload resultPayload) throws RemoteException; public void executeEventByWorkitem(String mainInstanceId, String eventName, String triggerActivityTracingTag, ResultPayload resultPayload) throws RemoteException; public String[] delegateWorkitem(String instanceId, String tracingTag, RoleMapping roleMapping) throws RemoteException; //flow control – Activity Flow Control related API public void flowControl(String command, String instanceId, String tracingTag) throws RemoteException; //process definition – Process Definition related APIs public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String pdid) throws RemoteException; public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String belongingPdid, String objectType) throws RemoteException; public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String defId, String objectType, String alias, String superDefId) throws RemoteException; public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, ProcessDefinition def, String folder, String pdid) throws RemoteException; public void removeProcessDefinition(String definitionName) throws RemoteException; public void renameProcessDefinition(String pdName, String newName) throws RemoteException; public String getProcessDefinitionIdByAlias (String alias) throws RemoteException; public void setVisibleProcessDefinition(String defId, boolean isVisible) throws RemoteException; //get ProcessDefinitionRemote – Process Information related APIs public ProcessDefinitionRemote[] listProcessDefinitionRemotesLight() throws RemoteException; public ProcessDefinitionRemote[] findAllVersions(String pdid) throws RemoteException; public ProcessDefinitionRemote getProcessDefinitionRemote(String processDefinition) throws RemoteException; public ProcessDefinitionRemote getProcessDefinitionRemoteWithInstanceId(String instanceId) throws RemoteException; //Production Version – Process Version related APIs public String getProductionVersionIdAtThatTime(String defId, Date thatTime) throws RemoteException; public String getFirstProductionVersionId(String defId) throws RemoteException; public void setProcessDefinitionProductionVersion(String pdvid) throws RemoteException; public String getProcessDefinitionProductionVersion(String definitionGroupId) throws RemoteException; public String getProcessDefinitionProductionVersionByAlias(String alias) throws RemoteException; public String getProcessDefinitionProductionVersionByName(String pdName) throws RemoteException; //get ProcessDefinition – Process Information Collection related APIs public ProcessDefinition getProcessDefinition(String processDefinition) throws RemoteException; public String getProcessDefinition(String processDefinition, String encodingStyle) throws RemoteException; public ProcessDefinition getProcessDefinitionWithInstanceId(String instanceId) throws RemoteException; public String getProcessDefinitionWithInstanceId(String instanceId, String encodingStyle) throws RemoteException; //get Resource – Form Resource Collection related APIs public String getResource(String resourceId) throws RemoteException; //get ProcessInstanceRemote – Process Operation Information related APIs public ProcessInstanceRemote[] listProcessInstanceRemotes() throws RemoteException; public ProcessInstanceRemote[] listProcessInstanceRemotes(String definition) throws RemoteException; public ProcessInstanceRemote[] listProcessInstanceRemotes(String definition, String status) throws RemoteException; public ProcessInstanceRemote[] listProcessArchiveRemotes() throws RemoteException; //process Instance – Process Operation related APIs public void removeProcessInstance(String instanceId) throws RemoteException; public void stopProcessInstance(String instanceId) throws RemoteException; public ProcessInstance getProcessInstance(String instanceId) throws RemoteException; public void setProcessInstanceInfo(String instanceId, String info) throws RemoteException; public void setProcessInstanceStatus(String instanceId, String status) throws RemoteException; //Activity – Activity related APIs public Serializable getActivityProperty(String processDefinition, String tracingTag, String propertyName) throws RemoteException; public Hashtable getActivityDetails(String processDefinition, String tracingTag) throws RemoteException; public Hashtable getActivityInstanceDetails(String instanceId, String tracingTag) throws RemoteException; public String getActivityStatus(String instanceId, String tracingTag) throws RemoteException; public HashMap getInitiationParameterMap(String pvdid) throws RemoteException; //ActivityInstanceProperty – Activity Property related APIs public Serializable getActivityInstanceProperty(String instanceId, String tracingTag, String propertyName) throws RemoteException; public void setActivityInstanceProperty(String instanceId, String tracingTag, String propertyName, Serializable value) throws RemoteException; public void setActivityInstanceProperty(String instanceId, String tracingTag, String propertyName, Serializable value, Class valueType) throws RemoteException; public Serializable doActivityAction(String instanceId, String tracingTag, String actionName, Serializable[] parameters, Class[] parameterTypes) throws RemoteException; //import and export – Process Definition and Download and Loading related APIs public void exportProcessDefinitionbyDefinitionId(String defId, boolean allVersion) throws Exception; public void exportProcessDefinitionbyVersionId(String defVerId) throws Exception; public Vector importProcessDefinition(String parentFolder, InputStream loadedZipFile, UEngineArchive editedUa, String[] command ) throws Exception; public Hashtable importProcessAliasCheck(InputStream is) throws Exception; //flow chart – Flowchart related APIs public String viewProcessDefinitionFlowChart(String processDefinition, Map options) throws RemoteException; public String viewProcessInstanceFlowChart(String instanceId, Map options) throws RemoteException; //folder – Folder related APIs public void removeFolder(String folderName) throws RemoteException; public void addFolder(String folderName, String parentFolder) throws RemoteException; public void moveFolder(String pdid, String parentFolder) throws RemoteException; //dynamic change – Process Definition Change Management related APIs public void changeProcessDefinition(String instanceId, String definitionInXML) throws RemoteException; public void changeProcessDefinition(String instanceId, ProcessDefinition definition) throws RemoteException; //test – Test Processing related APIs public void setFault(String instanceId, String tracingTag, Exception fault) throws RemoteException; //signaling all the changes can be applied – Handling Change related APIs public void applyChanges() throws RemoteException; public void cancelChanges() throws RemoteException; //user can pass some parameters into the kernel – Handling login information related APIs public void setGenericContext(Map genericContext) throws RemoteException; public void setLoggedRoleMapping(RoleMapping roleMapping) throws RemoteException; public EventHandler[] getEventHandlersInAction(String instanceId) throws RemoteException; public ActivityReference getInitiatorHumanActivityReference(String pdvid) throws RemoteException;
Each invocation is handled by the abstract framework, OKF(Open Kernel Framework) that will explain in the next chapter. [Note] By checking jsp files in was/webapps/uengine-web directory or scripts supported by scriptcosole, you will understand how each interface works.
Persistence Framework
uEngine completely separates logic from kernel for data preservation. Process definitions are obtained from “org.uengine.kernel.ProcessDefinitionFactory”. All transactional data is handled by “org.uengine.kernel.ActivityInstance class. In addition, EJBProcessInstance class is used as a default. There are various ways of preservation mechanisms plugged into uEngine. The reason is that we are not able to take responsibility for the risk on complex database design which is critical on performance.
Default Preserved Framework
The default ProcessDefinitionFactory class and EJBProcessInstance class take advantage of XML Serializer and Entity Beans together. It is considered an intermediate way to approach. Objects need to be serialized into XML-Text format, in order to save overall data. For the purpose of a better search performance, it should be saved into Entity Beans. With the default preservation framework that consists of the following three entity beans and XML-Serializer, data can be finally preserved.
1. org.uengine.persistence.processdefinition.ProcessDefinitionRepositoryBean
| Description | Process Definitions in XML Text are saved |
| Fields | ID – Definition name, Description – Definition Explanation, Definition – Definition XML Content |
| Note | For large volume of database based process definition analysis, definitions need to be stored in a fine-grained way that contains as many tables as possible. |
2. org.uengine.persistence.processinstance.ProcessInstanceRepositoryBean
| Description | Simple information is saved into database that contains the summarized explanation of Process Instances. |
| Fields | ID – Process Instance ID, Definition – Process Definition name (for the reference), StartedDate – Start Date & Time |
3. org.uengine.persistence.processdefinition.ProcessVariableRepositoryBean
| Description | With XML Serializer use, objects saved in text format, so process variables are stored in Generic type. Therefore, Complex database design can be avoided however, the performance of transactional data based analysis can not be guaranteed |
| Fields | ID – Primary Key, InstanceId – Instance ID(Foreign Key), KeyString – Variable Key name, Value – Actual data value (regardless of variable data type, because of its XML format) |
| Note | For transactional data analysis or fast search result, we recommend using SQLActivity class which is an indirect way to do. Instead of using actual data stored by uEngine, necessary information based on requirements for the focus on user’s analysis is better saved into database by adding programming codes into SQLActivity class that is the indirect way doing it. This improves database performance and system complexity. |
[Note] 3.3 For more examples in implementation, see Appendix F 3.3.
Composite Pattern
The next figure 2 explains process definition object models used by uEngine. This model is the famous extended version of ‘Composite Pattern ’ .
Block type flow models are well designed to be saved by object models. Simple and complex activities both contain execution commands and easily added. However complex activities have logic commands additionally.
Simple Activity types include Web Service invocation, sending emails, and human works, while complex activity types control managing between such activities like sequence, all, switch. These two activities are structured by inheritance between Activity and ComplexActivity. It is useful that Activity and ComplexActivity share the same protocol. The same structure makes framework simple and can be extended to generic.
Main class
For a better understanding of uEngine process meta models, there are essential classes that we need to understand before jumping into the details.
1. Activity Definition Class – Activity
Activity.java consists of fields composed with basic activities, callback method declaration, fundamental structure codes, and several utilities. [Note] 3.5.1 For more examples, see Appendix F 3.5.1.
2. Activity Flow Control Class – ComplexActivity
ComplexActivity.java can have child activities. It also controls flows between child activities. Basically, child activities are executed sequentially. AllActivity that executes parallelly is inherited from parent Activity class. In the process meta model addition to that, setter/getter is followed by programming convention, through reflection, design time support is available. uEngine Process Design is working like a Beanbox that helps users be able to make changes on activity types in a Java Bean format by given forms on which its values are automatically set. Developers are able to create activity types according to the rules without understanding AWT or Swing technology. [Note] 3.5.1 For detailed examples, please see Appendix F 3.5.1
It is a class that holds one process definition. It basically works sequentially because it inherits to ComplexActivity class. Additional information is held and required for process definitions.
3. Process Definition Class – ProcessDefinition
It is a class that holds one process definition. It basically works sequentially because it inherits to ComplexActivity class. Additional information is held and required for process definitions.
4. Roles and Role Mapping Class – Roles and RoleMapping
The role decides participants declared in Process Definition. RoleMapping is also a class that holds the information of an initiator who executes Process Definition initially. Role holds the name of responsibility, while RoleMapping holds the email address or endpoint URI(in the case of Web Service) of the participant who executes an assigned work.
5. Process Variable Class – ProcessVariable
ProcessVariable is a class used for Process Variable declaration. It holds variable name, data type, and QName(in the case of XML). The actual value is saved into XML by using the set method of ActivityInstance class.
[Note] 3.5. For more examples, see Appendix F 3.5.
Component Framework
uEngine is based on component framework that helps users continuously extend the system with new activity type additions. This feature helps developers not to make the same mistakes that already made from experiences obtained during other projects. It also improves productivity and quality simultaneously.
uEngine is followed by a component based development methodology which is stable and guaranteed along with the proved analysis of workflow. This is similar to other component based methodologies, but with the focus on business environment implementation preferences, it attracts developers to deliver recyclable components that have high frequency of use. In conclusion, with the efficient and proved workflow methodology, the component becomes formalized. Therefore, users maximize usability in business environment. Under the uEngine, OKF(Open Kernel Framework) is based. The following UMLs show the steps of overall delegation how it works.
Design, Validation, Monitoring, Viewing, Persistence, and Execution control needed for Workflow life cycle are controlled by the kernel(hot-spot). During the working period with the lead of kernel, these are managed by activity execution related properties and logic invocation on necessary ActivityType.
This minimizes the dependency by using separation between application logic and workflow system logic. Therefore, the only jobs for developers are to write properties and implement the properties according to the logic interface required for each situation. Without related technical knowledge, they are able to add new activity types into stable and automatically managed environments.
- Component Interfaces
There are Activity execution related Activity components in uEngine, however many additional components need to be declared into separate classes. The reason of separation between given Activity components and additional Activity components written by users is that it is easy to manage by different type. With inheritance, unnecessary code dependencies are reduced effectively.
[Note] Each component that has examples can be found in its class file located in its cohesive package.
First of all, there are one Activity type and the related components.
- Process Viewers (org.uengine.kernel.viewer.*)
| Description | It is a viewer component that shows process flow at monitoring time. |
| Interface |
public interface ActivityViewer{ |
| Name | [Activity Name]Viewer ex) SQLActivityViewer |
| Time in use | Monitoring Time |
| Invocation Kernel | org.uengine.processmanager.ProcessManagerBean |
- Activity Descriptors (org.uengine.kernel.descriptor.*)
| Description | In general, with the purpose of additional properties(caption and input control definitions) at design time, Metaworks framework used for creating UI(User Interface) |
| Interface |
(Please refer to the separate chapter for Metaworks’s explanation.) |
| Name | [Activity Name]Descriptor ex) SQLActivityDescriptor |
| Time in use | Design and Monitoring Time |
| Invocation Kernel | org.uengine.processdesigner.ProcessDesigner Sharing with Metaworks framework |
- Activity Designers (org.uengine.kernel.designer.*)
| Description | In order to modify given activities via designer component(UI component) |
| Interface |
public interface ActivityDesigner{ |
| Name | [Activity Name]Designer ex)SQLActivityDesigner |
| Time in use | Design Time |
| Invocation Kernel | Created by getActivityDesigner method in org.uengine.kernel.Activity class Used by org.uengine.processdesigner.ProcessDesigner |
- Activity Image (org.uengine.kernel.images.svg.*)
| Description | Each Activity icon image |
| Interface | |
| Name | [Activity Name].svg ex)SQLActivity.svg |
| Time in use | Design and Monitoring Time |
| Invocation Kernel | Used by org.uengine.processdesigner.ProcessDesigner |
The following components except for Activities due to genuine high frequency of use are generally being used in uEngine.
- Unified Serializers (org.uengine.components.serializers.*)
| Description | Overall, it manages components that conduct various serializing mechanisms |
| Interface |
public interface Serializer{ |
| Name | [Serialized mechanism name]Serializer ex)BPELSerializer, BeanSerializer, and AxisSerializer |
| Time in use | All of the time phase |
| Invocation Kernel | uengine.kernel.GlobalContext |
- Process Model Adapters (org.uengine.processpublisher.*)
| Description | For import/export support between uEngine process object model and various process languages |
| Interface |
public interface Adapter{ |
| Name | 1. Importer: [language name]/importer/[original language class name]Adapter 2. Exporter: [language name]/exporter/[activity name]Adapter |
| Time in use | All the time phase |
| Invocation Kernel | Each language serializer. |
ERD
In uEngine, there are database tables that are basically required in definition and customization stages. With several necessary SQL query examples, users are able to check the process information whether it is correct.
DAO
- 1. DAO Types
- Named DAO
IDAO is useful without type definition. Due to lack of type definition, corresponding source codes need to be changed. However, it is impossible, unless users understand all the tables, columns along with data types correctly.
// Using IDAO … IDAO person = (IDAO )GenericDAO.createDAOImple(cf, ” select * from person where name=?name”, IDAO.class); person.set(“name”,“kim bo sang”); // The first parameter is the column name, the second parameter is the value of the first parameter. person.Insert(); …
- Typed DAO
Instead of IDAO, it is possible to validate source codes by complier like eclipse, because it uses a declared type(interface). It helps developers reduce typos or mistakes. High frequency of use can benefit better than rare use. However, it is inconvenient when database table information changes, we also need to change the type accordingly.
- createDAOImple method can be found in org.uengine.util.dao.GenericDAO class
//Person Type definition
public Interface Person extends IDAO{
String getName();
void setName(String name);
}
// Getting the DAO object of Person type
…
Person person =(Person) GenericDAO.createDAOImple(cf /* ConnectionFactory */,
”select * from person where name=?name” /* SQL statement*/,
Pserson.class /* class type */);
person.setName(“kim bo sang”); // a method declared by Interface Person
person.Insert();
…
- 2. DAOs used by uEngine
- GenericDAO
It has automatic connection management functionality, if transactional connection is used, connections could be broken, so it is useful when we need to use DefaultConnectionFactory. After using DAO, the releasing the connection resource is not necessary.
… DefaultConnectionFactory cf = new DefaultConnectionFactory(); // In order to get DAO, GenericDAO class method is used IDAO person = GenericDAO.createDAOImple(cf, ”select * from person where name=?name”, IDAO.class); person.set(“name”,“kim bo sang”); person.Insert(); …
- ConnectiveDAO
The difference between ConnectiveDAO and GenericDAO is that in ConnectiveDAO, there is no automatic connectivity management functionality. Therefore, in some cases, we need to make sure that there must not be the automatic connectivity management functionality like transaction handling. The result of the purpose, we need to use ConnectiveDAO instead.
… TransactionContext tc = new TransactionContext(); ConnectionFactory cf = tc.getConnectionFactory(); IDAO person = ConnectiveDAO.createDAOImple(cf, ” select * from person where name=?name”, IDAO.class); person.set(“name”,“kim bo sang”); person.Insert(); …
- 3. Transaction
- Transaction Preservation
DAO is created by getting a connection from TransactionContext, and able to preserve the transaction. We should be aware that when a connection ends, make sure that the transaction should be disconnected as well.
// transaction safe
TransactionContext tc = new TransactionContext();
try{
ConnectionFactory cf = tc.getConnectionFactory();
Person person =( Person) ConnectiveDAO.createDAOImpl(cf, "insert into Person (?name, ?age)", Person.class);
person.setName("jju");
person.setAge(32);
person.insert();
tc.commit();
}catch(Exception e){
tc.rollback();
}finally{
tc.releaseResources();
}
Through DefaultConnectionFactory, besides the transaction, DAO is created separately by getting connectivity, so connectivity should be managed manually well. So, we must make sure that connectivity must be disconnected when it is no longer needed.
// transaction not safe
DefaultConnectionFactory cf = new DefaultConnectionFactory();
try{
Person person =( Person) GenericDAO.createDAOImpl(cf, "insert into Person (?name, ?age)", Person.class);
person.setName("jjy");
person.setAge(32);
person.insert();
}catch(Exception e){
}finally{ }
- 4. Relationship between TransactionContext and TransactionListener
TransactionContext includes one or more than one TransactionListener. When commit() or rollback() methods are invoked, all the included TransactionListeners are automatically invoked as well.
- 5. Caching Enabled
At this point, caching is collecting all the tasks carried after creating a transaction. After then, all the tasks are being batch processed right before the commit. In a simple way to describe the caching, it keeps all the tasks processed before the commit. The following codes are an example that transaction listeners are added into transaction and conducting the corresponding logic when beforeCommit() method is invoked.
TransactionContext tc = new TransactionContext();
…
tc.addTransactionListener( new TransactionListener(){
public void beforeCommit(TransactionContext tx) throws Exception {
ConnectionFactory cf = tc.getConnectionFactory();
Person person = ConnectiveDAO.createDAOImpl(cf,
"insert into Person (?name, ?age)",
Person.class);
person.setName("jju");
person.setAge(32);
person.insert();
tc.commit();
}
public void beforeRollback(TransactionContext tx) throws Exception {}
public void afterCommit(TransactionContext tx) throws Exception {}
public void afterRollback(TransactionContext tx) throws Exception {}
}
)
- The invocation time of the beforeComment() method of TransactionListener is found in the commit() method of TransactionContext class in org.uengine.processmanager package.
- 6. Synchronized DAO (automatically cached DAO)
SynchronizedDAO is explained in chapter 3.3 that it is a DAO methodology with caching functionality. There is one careful attention needed that commit() method is used instead of either insert() or update() method when applying all the processed works.
- createSynchronizedDAO()
A new DAO is created and added into SharedContext when createSynchronizeDAO is invoked, while DAO is recyclable until commit() method is being invoked. For a better understanding of SharedContext, it is the DAO list of transactions being used. All the saved DAO list is initialized automatically when commit() method is executed. In addition, once a DAO is added into SharedContext, the same DAO needs to add again, it conducts the same task 2 times until the commit statement is passed, it delays performance. Therefore, once a DAO object is created by createSynchronizeDAO() method, you can avoid duplicate creations of the same DAO object by using findSynchronizedDAO() method. For this method, 4 parameters are needed. The first one is table name, and the second one is primary key, and the third one is value, and the last one is DAO class name.
TransactionContext tc = new TransactionContext();
Person person = (Person)tc.createSynchronizedDAO("Person", "name", "jjy", Person.class);
person.setName(“jjy”);
...
Person someone = (Person)tc.findSynchronizedDAO("Person", "name", "jjy", Person.class);
someone.setAge(32);
…
tc.commit(); // Insert person
- findSynchronizedDAO()
It is a method that gets the DAO saved in SharedContext through createSynchronizeDAO. The arguments of findSynchronizedDAO are the same as createSynchronizeDAO method.
TransactionContext tc = new TransactionContext();
Person person = (Person)tc.findSynchronizedDAO("Person", "name", "jjy", Person.class);
person.setName(“kbs”);
setAge(30);
…
tc.commit(); /// update person
- 7. SQL Generation
SQL generation’s functionality is generating a SQL query statement automatically. SQL query statements are not required for DAO creation. There are 2 ways to create SQL query statements. One is applying the autoSQLGeneration option when DAO is declared. The other one is generating SQL query statements through createInsertSql() method right before commit() method invocation.
- createInsertSql()
SQL query statement creation must be used right before invoking commit() method, because it is created with the only information carried until createInsertSql() method invocation, as a result of that, complete SQL query statements can be generated right before the commit() method invocation.
IDAO dao = ConnectiveDAO.createDAOImpl(tc, null, IDAO.class);
dao.getImplementationObject().setTableName("Person");
dao.getImplementationObject().setKeyField("name");
dao.set("name", "jjy");
dao.set("age", 32);
dao.getImplementationObject().createInsertSql();
dao.insert();
- setAutoSQLGeneration()
SQL query statements are generated automatically when invoking setAutoSQLGeneration(true) method, it is internally set to ‘true’ value as a default. By calling createInsertSql() method right before the commit execution, it generates SQL query statements.
IDAO dao = ConnectiveDAO.createDAOImpl(tc, null, IDAO.class);
dao.getImplementationObject().setTableName("Person");
dao.getImplementationObject().setKeyField("name");
dao.getImplementationObject().setAutoSQLGeneration(true);
dao.set("name", "jjy");
dao.set("age", 32);
dao.insert();
- 8. EJBProcessInstance
This EJBProcessInstance class is one of typical classes that TransactionListener is being used for this class. It is an implementation class of an abstract ProcessInstance class, and it implements TransactionListerner. So, once an instance is created, one TransactionListener is registered into TransactionContext. As chapter 3.3 explained, many processed tasks are put aside, it is actually applied when beforeCommit() method is invoked.
// Member variables that save Processed tasks
Map modifiedKeyMap;
Map modifiedRoleMappings;
Map cachedRoleMappings;
//Methods of TransactionListener
public void beforeCommit(TransactionContext tx) throws Exception{
applyChanges(); // Apply all the tasks into engine
}
public void beforeRollback(TransactionContext tx) throws Exception{
}
public void afterCommit(TransactionContext tx) throws Exception {
}
public void afterRollback(TransactionContext tx) throws Exception {
}
public void applyChanges() throws Exception{
MeasuringContext mc = new MeasuringContext("EJBProcessInstance:applyChanges()");
ProcessInstanceDAO procInsDAO = getProcessInstanceDAO();
procInsDAO.getImplementationObject().setTableName("BPM_PROCINST");
procInsDAO.getImplementationObject().setKeyField("INSTID");
procInsDAO.setModDate(GlobalContext.getNow(getProcessTransactionContext()).getTime());
if(isNew){
procInsDAO.getImplementationObject().createInsertSql();
}else{
procInsDAO.getImplementationObject().createUpdateSql();
}
procInsDAO.update();
if(modifiedKeyMap !=null){
…
}
At this point, we might think that this class is also implemented via SynchronizedDAO. However, this class had been implemented before uEngine’s engine adopted SynchronizedDAO.
- 9. Persistence
- EJB Mode Change
The script, ‘use.ejb=false’ is found in the uengine.properties setting file. This means that engine is working under either EJB mode or already implemented uEngine. By clicking uEngine’s ProcessManager menu, there is the process definition tree displayed on the left side of the screen. In order to display the tree menu with created process definitions, ProcessDefinitionList.jsp is invoking listProcessDefinitionRemotesLight() method in ProcessManagerbean.
public ProcessDefinitionRemote[] listProcessDefinitionRemotesLight() throws RemoteException{
try{
ProcessDefinitionRepositoryHomeLocal pdhr = GlobalContext.ceateProcessDefinitionRepositoryHomeLocal(getTransactionContext());
ProcessDefinitionVersionRepositoryHomeLocal pdihr = GlobalContext.createProcessDefinitionVersionRepositoryHomeLocal(getTransactionContext());
Collection definitions = pdhr.findAllProcessDefinitions();
Vector processDefinitionRemotes = new Vector();
for(Iterator iter = definitions.iterator(); iter.hasNext();){
ProcessDefinitionRepositoryLocal pdrl = ((ProcessDefinitionRepositoryLocal)iter.next());
…
Looking carefully at ceateProcessDefinitionRepositoryHomeLocal method, it is set to ‘use.ejb=false’ and returns ProcessDefinitionRepositoryHomeLocalImpl, which makes EJB not work. In the case of ‘use.ejb=true’, it returns processDefinitionRepositoryHomeLocal, which makes EJB work. With the following codes, users are able to switch the engine mode.
public static ProcessDefinitionRepositoryHomeLocal createProcessDefinitionRepositoryHomeLocal(TransactionContext tc) throws Exception{
/*
* org.uengine.kernel.GloabalContext
* If it is not under EJB mode, returns ProcessDefinitionRepositoryHomeLocalImpl.
* ProcessDefinitionRepositoryHomeLocalImpl is woking under uEngine’s implemented logic
* If it is EJB mode, returns processDefinitionRepositoryHomeLocal.
*/
if(!useEJB)
return new ProcessDefinitionRepositoryHomeLocalImpl(tc);
if(processDefinitionRepositoryHomeLocal==null){
processDefinitionRepositoryHomeLocal =
(ProcessDefinitionRepositoryHomeLocal)
getInitialContext().lookup("ProcessDefinitionRepositoryHomeLocal");
}
return processDefinitionRepositoryHomeLocal;
}
- RepositoryHomeLocalImpl class
From the previous page, ProcessDefinitionRepositoryHomeLocal is generally declared as an interface, which is inherited from javax.ejb.EJBLocalHome. How about ProcessDefinitionRepositoryHomeLocalImpl? We do not know why we need this as well. The answer is here that ProcessDefinitionRepositoryHomeLocalImpl is an implementation class for ProcessDefinitionRepositoryHomeLocal in order to make use of all the uEngine DAO types.
//ProcessDefinitionRepositoryHomeLocalImpl’s creation method
public ProcessDefinitionRepositoryLocal create(Long id) throws CreateException {
final ProcessDefinitionDAO pd;
try {
pd = (ProcessDefinitionDAO)ConnectiveDAO.createDAOImpl(tc, null, ProcessDefinitionDAO.class);
pd.getImplementationObject().setTableName("BPM_PROCDEF");
pd.setDefId(id);
tc.addTransactionListener(new TransactionListener(){
public void beforeCommit(TransactionContext tx) throws Exception {
pd.getImplementationObject().createInsertSql();
pd.insert();
}
public void beforeRollback(TransactionContext tx) throws Exception {
}
public void afterCommit(TransactionContext tx) throws Exception {
}
public void afterRollback(TransactionContext tx) throws Exception {
}
});
return pd;
} catch (Exception e) {
throw new CreateException(e.getMessage());
}
}
Development
Install and Build the Project
How to Download and Run the uEngine Standalone
- Visit this page, http://www.sf.net/projects/uengine
- Download uEngine_standalone version.
- Directory descriptions are shown below after downloading the uEngine Standalone version.
| Directory | Description |
| defaultcompany | Customization file directory location |
| doc | User guide, in the case of “apidoc”, use the “javadoc” instead |
| hsqldb | Hypersonic Database is given default |
| META-INF | Metaworks directory as a Database development tool |
| src | uEngine project directory |
| src/build.xml | Useful commands are supported by Ant tool |
| was | Tomcat directory given by standard WAS |
| was/bin/startup.bat | Useful scripts for executing Tomcat |
How to run the uEngine-web
- Run “runServer.bat” in the “hsqldb/demo” directory. (hsqldb execution)
- Run “startup.bat” in the “was/bin” directory. (Tomcat execution)
- Visit the page, http://localhost:8080/uengine-web/.
After running the uEngine, with “test” ID for English version, cf. “test_ko” for Korean version, access can be permitted. For uEngine Standalone version, standard UI and activities are supported. You can also make changes on them by adding and updating the functions as you wish.
[Note] uEngine Server is successfully tested on JRE 1.5 or higher versions, However, you need JRE 1.6 or higher versions for “Process Designer”(Swing Independent Client Application) execution. If the server is not working properly, please add the following script in the top of “startup.bat” file.
set JAVA_HOME=<jre1.5 or jdk1.5 location >
[Note] In the case of the relative directory path issue, data files could not be found. Please add the following script in the top of “startup.bat” file.
Cd <The absolute directory path of “was\bin”>
After building defaultcompany project, changes can be applied
“defaultcompany” directory is the place where you can apply additional development. Source code changes and additions can be applied by using “Ant”. uEngine customizing methods will be explained in the next chapter, for this time, we perform how to build the uEngine project. The followings should be configured, before compiling “Ant”.
C:\> set JAVA_HOME=C:\Program Files\Java\jdk1.5.0 C:\> set UENGINE_HOME=C:\uengine_standalone C:\> path %PATH%;C:\apache-ant-1.7.0\bin
And then, execute the “ant” command in the “uEngine_standalone\src\” directory. In addition to that, execute the “ant” command in the “defaultcompany” directory, the following screen below will appear, and it becomes the latest version.
C:\uEngine_standalone\defaultcompany> ant Buildfile: build.xml Compile: Apply: Signjar: [echo] jarfile= ./build/uengine_settings.jar BUILD SUCCESSFUL Total time: 1 second
The properties of uengine.properties
Standard configuration values are already written and different changes can be applied in the “uengine.properties” file located in the setup directory, “..\uEngine_standalone\was\webapps\uengine-web\WEB-INF\classes\org\uengine”.
| Property | Description | Example |
| pd.inputterpackages | Process Designer customizing purpose. For additional inputters, the names of different packages are separated by comma(,). | org.metaworks.inputter.webInpputer |
| pd.logo.image | The location of logo image resource that appears on the Process Designer, the whole path except for the file extension. | |
| pd.rolepicker.class | Customizable role picker class | |
| worklistservice.class | Worklistservice class | org.uengine.webservices.worklist.JDBCExtWorkList |
| Daofactory.class | DAOTYPE of the database being used | org.uengine.persistence.dao.HSQLDAOFactory |
| processinstance.class | ProcessInstance class being used. | org.uengine.kernel.EJBProcessInstance |
| rolemapping.class | RoleMapping class | org.uengine.liferayintegration.LiferayRoleMapping |
| server.definition.path | The directory path of definition file. | <was>/bin/uengine/definition |
| Web.context.root | Web context root path. For Tomcat version, the path is different | Jboss :/html/uengine-web tomcat :/uengine-web |
| datasource.jndiname | JNDI name of Datasource. | java:/uEngineDS |
| usertransaction.jndiname | JNDI name of user transaction | UserTransaction |
| portlet.width | The lengths of the width and height of Portlet | 950 |
| emailactivity.smtp.ip emailactivity.smtp.userid emailactivity.smtp.password |
SMTP server account for sending emails via Email Activity. | smtp.mail.yahoo.co.kr pongsor 123456 |
| messengeractivity.msn.id messengeractivity.msn.password |
Account for sending messages via MSNMessenger Activity or AlarmActivityFilter | uengine_82@hotmail.com pongsor2 |
| org.uengine.components.activityfilters. olapetlfilter.datasource.name |
Data Source name of OLAP DataMart, or for OlapEtlFiler use. |
java:/uEngine-DW-DS |
| Defaultactivityfilters | A type of Defaultactivityfilter class (different values are separated by comma(,). | org.uengine.components.activityfilters.OlapEtlFilter (Loading the results of work into DM),org.uengine. components.activityfilters.AlarmActivityFilter (any messages delivered to users like Messenger), org.uengine.components.activityfilters. CalendarFilter(It is possible when JBoss is running, calendar scheduling function supported) |
| use.ejb | Whether EJB is needed | false |
| use.managedtransaction | Transaction management option (Container or uEngine), if you want all the controlling done by uEngine, set to ‘false’, otherwise ‘true’. | true |
| use.auto.usertransaction.demarcation | If 'UserTransaction' is not needed ‘set to true’, otherwise ‘false’ For instance of use.ejb=true, the function is disabled | true |
| was.type | The name of WAS | JBOSS |
Customization functions
How to Develop Customizable Workitem Handlers (WIH)
WIH written in JSP is simply explained that it is the screen seen by user when the process is being executed. It is important, because it occupies the largest space in the customization area. It also retrieves necessary information from the server and submits data to the server through ProcessManager interface.
Figure 8. shows one example of uEngine Workitem handler functions. The WIH is also the user interface for workitem result submission. Users can select a workitem in the worklist(to-do list), the next step of process appears on the screen, finally users click the “Complete” button, the result will be transferred to the server, and the next step will proceed as it shows.
How WIH works
When index.jsp file is loaded, worklist requests all the information to index.jsp that WIH requires in order to display the results via “request.getParameter() method. It also retrieves chart and the information defined in the Process Designer via PrcessManager bean function. At last, users submit the entered data to submit.jsp, while submit.jsp is collecting the results generated from index.jsp and transmits them after invoking ProcessManager bean function.
In general, users underestimate the system which actually has outstanding execution capabilities or functions, because the quality of their customized designs was poor. Therefore, the best focus on the WIH customizing is UI(User Interface) modifications as users wish by using index.jsp. Basically, create the best screen for users while keeping the standard index.jsp functions.
How to Apply Workitem Handler
WIH can be found in “<UENGINE_HOME>/webapps/uengine-web/wih” directory, after uEngine is installed successfully. It basically defines “defaultHandler”, but additional handlers can be conveniently added if necessary.
Develop Customizable Activity Type
A new activity type can be added as we follow the process object model explained earlier. With a great example, we can add a new activity type. For this time, we create an activity that executes SQL queries.
How to add an activity type
- 1. Activity types are already defined in “defaultcompany\src\org\uengine\processdesigner\activitytypes.xml” file. New activitiy definition classes can be added by following steps.
- 2. Save “SQLSampleActivity.java” file into “defaultcompany\src\com\defaultcompany\activitytypes” directory.
- 3. The image, “SQLSampleActivity.gif” that its name is the same as activity name except for the file extension should be saved into two directory locations below.
- 1) “defaultcompany\src\com\defaultcompany\activitytypes\images”.
- 2) “defaultcompany\WebContent\uengine-web\processmanager\images”.
- 4. Apply with “ant” command execution in the “defaultcompany”.
- 5. ”Ant” tutorials can be found on chapter 4.2.
- 6. Restart Tomcat.
Ways to test new activity types.
- 1. Run the “Process Designer” and click the right button under the “Definitions”, the root node of “Process Manager” tree, and click the “New Process”.
- 2. Check the left menu whether SQLSampleActivity is created
- If it is not found, please doublecheck the followings
- 1) Is added activity group name in “activitytypes.xml” file different?
- 2) Is added activity package name in “activitytypes.xml” file different?
- 3) Is any error found in “SQLSampleActivity.java” file(check base class).
- 3. In the new process, creates SQLSampleActivity, changes the process name into “ActivityTest”, click the “Apply” button on the bottom of the screen.
- 4. Click the “Deploy” button.
- 5. Click the “View” menu under the recently created “ActivityTest” under the Definitions, the root node of “Process Manager” tree.
- 6. Click the “Initiate” button on the top and right side of the screen.
- 7. Click the instance ID with “ActivityTest” name in the Process Manager.
- 8. Click the “Start” button on the flow chart.
- 9. Check the Tomcat console screen whether it shows that “this is SQLSampleActivity”.
As the result of that, activity types are defined in the “activitytypes.xml” file.
For setter/getter parts implemented in the “SQLSampleActivity.java”, we could check that the data entry window can be automatically popped up and applied in the Activity Definition part in the “Process Designer” as shown in Figure 10.
Some users might be curious about why only test entries are applied. Here is the answer for the question that we will solve the curiosity at the Metaworks part in the near future.
Especially, we will learn that executeActivity function parts are eventually executed, when the activity is being invoked.
Implement Customizable Organization Chart
Mostly, BPM systems have their own organization models. Due to the issue, sometimes, synchronization such as batch processing must be made in order to integrate between BPM system and other enterprise applications. However, uEngine not only has its own organization model, but also it provides the strategy interface where users make use of essential strategy components that fit with their own organization models. This key feature helps them prevent from organization data duplication or other complex organization model dependency.
Basically, the ERD shown above is simply given in the actual organization model installed within “hypersonic db”.
This model is too simple to satisfy all the requirements given by organization, for a better understanding of an organization model, it is simply made as an example, therefore, users must be able to make changes that reflect their own organization models or applications by using the “strategy components(see the next chapter)”.
Rolemapping class
'RoleMapping' class is responsible for retrieving the detailed information from a specific organization chart. It is one of uEngine key strategy components.
Steps to proceed the role mapping
- Request role information from Activity.
- Role requests RoleMapping information to ProcessInstance
- ProcessIntance sends RoleMapping information to Activity.
- Proceed RoleMapping via RoleResolutionContext if RoleMapping information is not found, and send information to Activity.
The following codes below show the implementation that ‘Default Company’s RoleMapping class connected with existing organization’s database gets filled with detailed resource information.
In general, RoleMapping holds only endpoints, due to the large amount of resource waste. If RoleMapping holds all the information that databases have, we will waste a lot of resources. uEngine simply invokes fill(..) method in RoleMapping class when sending emails or requiring detailed information. And then, RoleMapping gets filled with information. However, in order to apply newly created RoleMapping class, we need to configure uengine.properties in the same way as the one below.
rolemapping.class=com.defaultcompany.organization.DefaultCompanyRoleMapping
RoleResolutionContext class
'RoleResolutionContext' is a component that decides the right person who is the best fit for the role. It is also called a rule definition expression. In a company, for instance, the rules of assigning people from ‘RoleUserTable’ will be explained in 'DefaultCompanyRoleResolutionContext'. The component consists of two parts. One is build time, and the other one is run time. The first build time includes property declaration, metaworks-callback, and getDisplayName() method. Property declaration also gets loaded by entry forms that handle the type information of reflection APIs and RoleResolutionContext. Additionally, with getDisplayName() method, user for the RoleResolutionContext is finally able to understand the screen with returned information. Moreover, ‘metaworks-callback’ provides a static method that makes use of RoleResolutionContext’s GUI when Role Picker is executed by the process designer.
‘getActualMapping(..)’ method will be referenced after roles are defined and being invoked. For example, ‘roleID’ searches for the appropriate users whose property is “Role”, and returns the ‘RoleMapping’ object. If you wish to use the RoleResolutionContext class, you need to configure uengine.properties and rebuild the ‘defaultCompany’ project like the one below.
roleresolutioncontexts=org.uengine.kernel.DirectRoleResolutionContext,com.defaultcompany.organization. DefaultCompanyRoleResolutionContext
- Login Mechanism – getLoggedUser.jsp and login.jsp
In order to check current active users on uEngine portal, ‘getCurrentUser.jsp’ and ‘loggedUserXXX’, ‘loggedRoleMapping’ variables can be directly used for the purpose. If you are willing to change the ‘login’ mechanism as you wish, you need to make changes on ‘getLoggedUser.jsp’ in ‘uengine-web/common’ directory. The current login information can be obtained from servlet session, and deliver to ‘getCurrentUser.jsp’ page.
- Organization Chart Browser - organizationChart.jsp and organizationChartXML.jsp
It is working similar to ‘getLoggedUser.jsp’. The pages, ‘organizationChart.jsp’ and ‘organizationChartXML.jsp’ can be customized by users based on their organizational culture or structures. Especially, those two pages are automatically referenced within uEngine when any screen needs to pick the best people for the role.
How it works? The results can be returned from the database based on the selection criteria that users check on ‘check-boxed tree’ like the Figure 15. shown above. For ‘getSelectedUsers()’ and ‘SelectedInfo()’ methods, their object creations are written in ‘organizationChart.jsp’ template. For declaration parts, it is better not to make changes. If necessary, you need to fully understand these two 'organizationChartPicker.jsp' and ‘org_uengine_kernel_RoleMappingInput.java’ files.
Metaworks / UI Generation Framework
uEngine takes advantage of Metaworks framework to develop Process Designer, the User Interface creation of work processor, and metadata based programming. Metaworks stands for “metadata-oriented database framework”. It is an automatic framework working with metadata selected from the database such as SQL, UI, Web, and EJB. Metaworks is an object oriented framework or component generators different from usual RAD tools or legacy modernizers that mostly working as a source generator. A source code generating method is a burden for developers who need to keep maintaining their programming source codes. However, the uEngine is well designed using design patterns that have great strengths. Those strengths are recycling, extendability, ease of maintaining, and generating useful components. For instance, by changing metadata, all the related technical implementations can be easily updated. Furthermore, it helps you reduce cost and delays in development by using special methodologies such as ‘Customization from default application’ and ‘JIT UI personalization.
[Note] Independently working Metaworks is a sister project with uEngine. For more detailed information, visit here, http://metaworks.sourceforge.net/korean.
- Type Declaration
- After declaring type class, retrieves information from created tables with criteria using similary like the “create” statement of database.
- [Note] 5.4.1. for more useful examples, please see Appendix F 5.4.1.
- Automatic UI Creation – InputForm Type Use
- Metaworks is creating a ‘Form Panel(Swing JPanel) that can receive one row of data entry in a given type. For instance, by invoking metaworksCallback method, name and the date of birth can be entered by users. As we learned from chapter 5.2. “Develop Customizable Activity Type”, with use of setter/getter, we could control entry fields for users. Additionally, we are able to create User Interfaces on processDesigner.
- [Note] 5.4.2. For more examples, please see Appendix F 5.4.2
- Consistent ways to input data - Inputter
- Swing entry UI components are useful for consistent ways to process and it is an interface where recycling and abstraction are easily made, therefore it is flexible, extensible, and especially useful for UI development.
- Standard Inputters supported (com.cwpdm.util.db.inputter.*)
| Inputter class | Description | Default type |
| TextInput | JTextField entry window | Types.VARCHAR |
| NumberInput | Only numeric type allowed, right aligned JTextField | Types.INTEGER |
| DateInput | Calendar DateButton | Types.DATE |
| SelectInput | JComboBox, only one option allowed | N/A |
| RadioInput | RadioButton, only one option allowed | N/A |
| ReferenceInput | JTextField entry window | selection PopupButton, only one option selected from the database |
The sixth argument for the parameter of “FieldDescriptor” class can be entered.
new FieldDescriptor("JOB","Job Selection", 12, false,
new FieldAttribute[]{
new FieldAttribute("default", new String("Unemployeed")),
},
new SelectInput(new String[]{"", "Unemployeed", "Student", "Employeed"})
),
new FieldDescriptor("BookCount","No of videos borrowed, 0,false,
null,
new NumberInput()
),
...
After defining data types, you can create “Form Panel” by using InputForm class. [Note] 5.4.3. For more examples, please see Appendix F 5.4.3.
- Consistent ways to validate - Validator
- In order to validate entered data whether it is in correct format, consistent interfaces are supported. Especially, for the combination of several validation conditions, it is possible to check all the requirements for passing the validation, and error handling with appropriate error messages is automatically supported through InputForm.
- Standard validators supported (com.metaworks.validator.*)
Validator class Description Default type NotNullValid Whether the data is entered(null), in the case of database, not null constraint N/A NumberValid Whether the entered data is numeric Types.INTEGER - How to Use
- The seventh argument for the parameter of “FieldDescriptor” class can be entered.
- Not only supported validators, but also validators that users are willing to have can be implemented by using abstract class inheritance.
- You can see the automatic UI creation example near the validator of ObjectType declaration part explained earlier.
FieldAttribute Use
- The fifth argument for the parameter of “FieldDescriptor” class can be entered.
- It explains a few properties of Field Descriptor.
- It is optional information that handles each SQL column separately by Type class (Access permission: Saving not allowed, update not allowed as well)
Attribute Keys
Key Value Description Example Default Initial value when creating InputForm new FieldAttribute("default", "male")) Size Maximum number of length of entered component allowed new FieldAttribute("size", new Integer(10)) Hidden Hidden fields. When creating InputForm, it is not shown. In most cases, display values after processing. The second argument of the object is initially displayed new FieldAttribute("hidden", "test") Mandatory Required entry fields. With a red triangle, it can be recognized new FieldAttribute("mandatory", new Boolean(true)) Source For SQL processing, already written default strings are used. Database server date (sysdate) or sorting expressions can be used directly. new FieldAttribute("source", "sysdate") Dontcare It can be ignored new FieldAttribute("dontcare", new Boolean(true)) ※ Only object types allowed, primitive types such as int, char, and boolean should not be entered. In the case of primitive int type, the following way can be used for this case. new Integer(value). - Data delivery to Inputter (After initializing, data can be passed to InputForm)
public static void main(String args[]) throws Exception{ // Create a table. In the case of database, ‘create’ statement Type AddressBook= new Type ( "AddressBook= ", // table name // column type size new FieldDescriptor[]{ new FieldDescriptor(“PERSONNAME”,”user name”, 0 , false, new FieldAttribute[]{ new FieldAttribute("default", new String('pongsor')), new FieldAttribute("size", new Integer(10)) }, ), new FieldDescriptor(“AGE”,”age”, 0,false new FieldAttribute[]{ new FieldAttribute("default", new String('1')), } ) } ); }At this chapter, we learn how to apply Metaworks explained chapter 5.4 to uEngine Process Designer and customize it.
ActivityType Design Time Customizing
In Activity Type, we simply make changes by using Metaworks with Inputters. With the following codes, a DriverClass can be selected in SqlSampleActivity rather than typing. Especially “metaworksCallback_changeMetadata” method is working with properties generated through setter/getter. The properties can be changed with the selected DriverClass.
public class SQLSampleActivity extends DefaultActivity { //Activity Property definition ///////////////////////////// //---------------------------------------------------------- public static void metaworksCallback_changeMetadata (Type type){ FieldDescriptor fd; // Property name argument that needs changes fd = type.getFieldDescriptor("DriverClass"); //Data type that needs changes fd.setInputter(new SelectInput(new String[]{"Oracle","MS-Sql","HyperSonic"})); type.setName("SqlSampleActivity"); } TextContext sqlStmt; public TextContext getSqlStmt(){ return sqlStmt; } public void setSqlStmt(TextContext value){ sqlStmt = value; } String connectionString; public String getConnectionString(){ return connectionString; } public void setConnectionString(String value){ connectionString = value; } String userId; public String getUserId(){ return userId; } public void setUserId(String value){ userId = value; } String password; public String getPassword(){ return password; } public void setPassword(String value){ password = value; } String driverClass; public String getDriverClass(){ return driverClass; } public void setDriverClass(String value){ driverClass = value; } public SQLSampleActivity(){ setName(“SQLSampleActivity”); } public void executeActivity(ProcessInstance instance) throws Exception{ //Execution parts //Console shows that “this is SQLSampleActivity” System.out.print(“This is SQLSampleActivity.”); } }
Figure 17. Input Type Changed Screen of Activity Type
Process Variable Object ExtensibilityIn order to customize the “Process Variable” declaration screen, it is the same way that Activity Type does. The properties that you are willing to have can be added through setter/getter. Input types are also applied by using metaworksCallback_changeMetadata method. You can find “ProcessVariable” class in org.uengine.kernel package, so the following codes should be added.
- ProcessVariable.java
… //metaworksCallback_changeMetadata fd = type.getFieldDescriptor("ExtValue1"); fd.setInputter(new RadioInput(new String[]{"a","b","c"})); } //setter/getter String extValue1; public String getExtValue1() { return extValue1; } public void setExtValue1(String extValue1) { this.extValue1 = extValue1; } …Ways to test the changes
- Execute “ant” command in src directory where updated ProcessVariable class is placed.
- Restart the server.
- Run Process Designer.
- Click “Variable Declaration” in Process Designer.
- Click the “New” button, the following UI screen shown below appears.
Figure 18. Process Variable Configuration Screen
Role Object ExtensibilityLet us make changes on role mapping configuration screen. The following codes should be added into Role class in org.uengine.kernel package. When the selected person is not able to complete the assigned work, with the reason of sick leave, out of office, or many more, another person can continue the assigned work instead of the other person originally assigned. At this situation, we can make use of “delegatorUser” function.
- Role.java
… //metaworksCallback_changeMetadata fd = type.getFieldDescriptor("DelegatorUserId"); fd.setInputter(new XMLValueInput("/usermanager/organizationChartXML.jsp")); } //setter/getter String delegatorUserId; public String getDelegatorUserId() { return delegatorUserId; } public void setDelegatorUserId(String delegatorUserId) { this.delegatorUserId = delegatorUserId; } …Pay attention to setInputter region. We will see that “organizationChartXML.jsp” is an argument that retrieves user information and converts it in XML format, finally loads into inputter. In addition to that, we could also customize the jsp according to user information obtained from database.
Figure 19. Role Mapping Change
Tips. Run the ‘Process Designer’ test via eclipse.- Run the uEngine server.
- Hit the ‘Run’ button on eclipse.
- Add “ProcessDesigner” for the “Run” profile.
- Enter “-Dbpm_port=8080 -Dbpm_host=localhost” as a VM argument.
- Click “Run” button and Choose “ProcessDesigner”.
- Click “Participate” button in ProcessDesigner.
- Doublecheck whether it is correctly added by clicking “New” button on the top of the screen.
Figure 20. eclipse Run Configuration Screen
[Note] 5.5.3. For more examples, please see Appendix F 5.5.3.Appendix A - ProcessManagerRemote API Reference
initialize process manager –Process Start related APIs
File name Org.uengine.processmanager.ProcessManagerRemote.java Method name public String initialize(String defVerId, String instanceId, RoleMapping loggedRoleMapping) throws RemoteException; Purpose Make processManager initialzed. This command conducts that if instanceID is returned with null, with initializeProcess functionaility, processInstance is created, returns ID value. ( same as initializeProcessIfRequired function) Parameters - defVerId - definition version’s ID value
- instanceId – instance’s ID value
- loggedRoleMapping – contains role mapping information, RoleMapping object
Return Values Instance’s ID value Example instanceId = initialize(“100”, instanceId,rolemapping);
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String initializeProcess(String defVerId, String instanceName) throws RemoteException; Purpose Create a Process Definition instance of a corresponding defVerID Parameters - defVerId - definition version’s ID value
- instanceName – instance’s name.
Return Values Instance’s ID value Example
File name Org.uengine.processmanager.ProcessManagerRemote Method name public String initializeProcess(String defVerId) throws RemoteException; Purpose Initialize process. Parameters - defVerId - definition version’s ID value
Return Values Instance’s ID value Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String initializeProcessIfRequired(String defVerId, String instanceId) throws RemoteException; Purpose If instanceId is null, returns instanceid after initializing process.( check initialize) Parameters - defVerId - definition version’s ID value
- instanceId – instance’s ID value
Return Values Instance’s ID value Example process execution – Process Execution related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void executeProcess(String instanceId) throws RemoteException; Purpose Start Executing ProcessInstance of a corresponding instanceID Parameters - instanceId – instance’s ID value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void executeProcess(String instanceId) throws RemoteException; Purpose Start Executing ProcessInstance of a corresponding instanceID Parameters - instanceId – instance’s ID value
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example resultPayload.setExtendedValues(new KeyedParameter[]{
new KeyedParameter("TASKID", taskId)});
process variable – Process Variable related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setProcessVariable(String instanceId, String scope, String varKey, Serializable val) throws RemoteException; Purpose Process Variable Configuration Parameters - instanceId – instance’s ID value
- scope – always empty strings entered (Not implemented yet)
- varKey – process variable name.
- Val – Returns the values of variables serialized.
Return Values No returns(void) Example resultPayload.setExtendedValues(new KeyedParameter[]{
new KeyedParameter("TASKID", taskId)});
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable getProcessVariable(String instanceId, String scope, String varKey) throws RemoteException; Purpose Gets process variable values Parameters - instanceId – instance’s ID value
- scope - always empty strings entered (Not implemented yet)
- varKey – process variable name
Return Values No returns(void) Example Returns the values of variables serialized.
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessVariableInXML(String instanceId, String scope, String varKey) throws RemoteException; Purpose Gets process variable values Parameters - instanceId – instance’s ID value
- scope - always empty strings entered (Not implemented yet)
- varKey – process variable name
Return Values Converts values into XML string type. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Hashtable listProcessVariableValues(String instanceId) throws RemoteException; Purpose Gets all the process variables of a corresponding instanceId Parameters - instanceId – instance’s ID value
Return Values Returns process variables in Hashtable Example role – Role related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void putRoleMapping(String instanceId, String roleName, String endpoint) throws RemoteException; Purpose Assign the people for the role by a corresponding instanceId. Already assigned workitems can not be applicable to this assignment. Parameters - instanceId – instance’s ID value
- roleName – Role name
- endpoint – user endpoint values
Return Values Returns process variables in Hashtable Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void putRoleMapping(String instanceId, RoleMapping roleMapping) throws RemoteException; Purpose Assign the people for the role by a corresponding instanceId. Already assigned workitems can not be applicable to this assignment. Parameters - instanceId – instance’s ID value
- roleMapping – RoleMapping object that contains role mapping information
Return Values Returns process variables in Hashtable Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void delegateRoleMapping(String instanceId, String roleName, String endpoint) throws RemoteException; Purpose Pass the tasks to new people selected by a corresponding instanceId. Already assigned all the workitems can be passed to the new people for the role(Role Delegation). Parameters - instanceId – instance’s ID value
- roleName – role name
- endpoint – user’s endpoint value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void delegateRoleMapping(String instanceId, RoleMapping roleMapping) throws RemoteException; Purpose Pass the tasks to new people selected by a corresponding instanceId. Already assigned all the workitems can be passed to the new people for the role(Role Delegation). Parameters - instanceId – instance’s ID value
- roleMapping – RoleMapping object that contains role mapping information
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getRoleMapping(String instanceId, String roleName) throws RemoteException; Purpose Get the person for the role whose ID matches a corresponding instanceId Parameters - instanceId – instance’s ID value
- roleName – role name
Return Values Returns RoleMapping object Example Messaging, triggering, event, workitem handling related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable sendMessage(String instanceId, String message, Serializable payload) throws RemoteException; Purpose Deliver messages to BPM Server via WebServices. Parameters - instanceId – instance’s ID value
- Message – The contents that delivered to the recipient.
- Payload
Return Values The data delivered to the recipient Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable sendMessageXML(String instanceId, String message, String payload) throws RemoteException; Purpose Parameters - instanceId – instance’s ID value
- Message – The contents that delivered to the recipient.
- Payload
Return Values The data delivered to the recipient Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void completeWorkitem(String instanceId, String tracingTag, String taskId, ResultPayload payload) throws RemoteException; Purpose Completes workitems, which belongs to a corresponding instanceid. Keep proceeding if next step of the task exists. Parameters - instanceId – instance’s ID value
- tracingTag – Current activity tracing tag value
- taskId – workItem’s taskId value
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void saveWorkitem(String instanceId, String tracingTag, String taskId, ResultPayload payload) throws RemoteException; Purpose Saves workitems, which belongs to a corresponding instanceid. Stop proceeding even though next step of the task exists. Parameters - instanceId – instance’s ID value
- tracingTag – Current activity tracing tag value
- taskId – workItem’s taskId value
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void executeEventByWorkitem(String mainInstanceId, String eventName, ResultPayload resultPayload) throws RemoteException; Purpose Starting tasks of Workitem Handler for event handler Parameters - mainInstanceId – instanceId value of processInstance that uses event handler
- eventName – event handler name.
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void executeEventByWorkitem(String mainInstanceId, String eventName, String triggerActivityTracingTag, ResultPayload resultPayload) throws RemoteException; Purpose Start processing workitem handlers for event handler Parameters - mainInstanceId – instanceId value of processInstance that uses event handler
- eventName – event handler name.
- triggerActivityTracingTag
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String[] delegateWorkitem(String instanceId, String tracingTag, RoleMapping roleMapping) throws RemoteException; Purpose delegates the people for the workitem by a corresponding instanceId. Only one workitem can be passed on to the new person. delegateRoleMapping is for changing the people for the role, while, delegateWorkitem is for delegating workitem only to the new person. The function comparison for assigning people to task roles (O: delegation is possible, X: delegation is not possible). Works processed previously can not be delegated to others.
Works that currently in progress Works that need to be processed delegateRolemmaping() O O putRolemmaping() X O delegateWorkitem() O X Parameters - instanceId – instance’s ID value
- tracingTag – Current activity tracing tag value
- taskId – workItem’s taskId value
- resultPayload – resultPayload gets loaded with Process Variable Changes or Additions when executing processInstance.
Return Values No returns(void) Example Delegated people’ endpoints
Messaging, triggering, event, workitem handling related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable sendMessage(String instanceId, String message, Serializable payload) throws RemoteException; Purpose Deliver messages to BPM Server via WebServices. Parameters - instanceId – instance’s ID value
- Message – The contents that delivered to the recipient.
- Payload
Return Values The data delivered to the recipient Example flow control – Activity Flow Control related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void flowControl(String command, String instanceId, String tracingTag) throws RemoteException; Purpose Current stage(Activity) moves to a pointed stage by flowControl. For instance, backActivity is used to return back to the pointed stage. Parameters - command – It is used for flow control.
suspend It stops resume Returns back to where it was skip Skip the stage compensate Go back to previous stage compensate to Go back to the pointed stages < table. Command’s Types >
- instanceId – instance’s ID value
- tracingTag – tracing tag where it moves to
Return Values No returns(void) Example pm.flowControl("resume”, instanceId, "3");
process definition – Process Definition related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String defId, String alias) throws RemoteException; Purpose Add a new definition Parameters - name - definition's name
- version - Added definition's version
- description - Additional detailed description for definition
- isAdhoc -
- strDef - definition's definition description.
- Folder - The saving directory location
- defId - definition's ID.
- Alias - recognizable strings that show definition.
Return Values Return VersionId of definition Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String defId, String objectType, String alias) throws RemoteException; Purpose Add a new definition Parameters - name - definition's name
- version - Added definition's version
- description - Additional detailed description for definition
- isAdhoc -
- strDef - definition's definition description.
- Folder - The saving directory location
- defId - definition's ID.
- Alias - recognizable strings that show definition.
- objectType - definition's type (process, form …etc).
Return Values Return VersionId of definition Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, String strDef, String folder, String defId, String objectType, String alias,String superDefId) throws RemoteException; Purpose Add a new definition Parameters - name - definition's name
- version - Added definition's version
- description - Additional detailed description for definition
- isAdhoc -
- strDef - definition's definition description.
- Folder - The saving directory location
- defId - definition's ID.
- Alias - recognizable strings that show definition.
- objectType - definition's type (process, form …etc).
- superDefId - parent definition's ID.
Return Values Return VersionId of definition Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String addProcessDefinition(String name, int version, String description, boolean isAdhoc, ProcessDefinition def, String folder, String defId) throws RemoteException; Purpose Add a new definition Parameters - name - definition's name
- version - Added definition's version
- description - Additional detailed description for definition
- isAdhoc -
- strDef - definition's definition description.
- Folder - The saving directory location
- defId - definition's ID.
Return Values Return VersionId of definition Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void removeProcessDefinition(String defVerId) throws RemoteException; Purpose Remove definition of VersionId Parameters - defVerId - definition's VersionId value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void renameProcessDefinition(String pdName, String newName) throws RemoteException; Purpose Change definition’s name Parameters - pdName - definition's name before change
- newName - definition's name after change.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinitionIdByAlias(String alias) throws RemoteException; Purpose Get definitionId by a corresponding alias Parameters Alias - recognizable strings that show definition.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setVisibleProcessDefinition(String defId, boolean isVisible) throws RemoteException; Purpose Control display (show/hide) for definitions in Definition tree. Parameters - defId - definition's ID.
- isVisible - (be displayed:true, hidden:false).
Return Values No returns(void) Example getProcessDefinitionRemote- Process Definition Collection related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote[] listProcessDefinitionRemotesLight() throws RemoteException; Purpose Get all the process definitions created Parameters Return Values Return with an array type of ProcessDefinitionRemote Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote[] findAllVersions(String defId) throws RemoteException; Purpose Get all definitions and versions by a corresponding definitionID Parameters - defId – definition’s ID value
Return Values Return with an array type of ProcessDefinitionRemote Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote getProcessDefinitionRemote(String defVerId) throws RemoteException; Purpose Get all definitions by a corresponding VersionId Parameters - defVerId – VersionId’s value of definition
Return Values Return with an array type of ProcessDefinitionRemote Example getProcessDefinitionRemote- Process Definition Collection related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote[] listProcessDefinitionRemotesLight() throws RemoteException; Purpose Get all the process definitions created Parameters Return Values Return with an array type of ProcessDefinitionRemote Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote[] findAllVersions(String defId) throws RemoteException; Purpose Get all definitions and versions by a corresponding definitionID Parameters - defId – definition’s ID value
Return Values Return with an array type of ProcessDefinitionRemote Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote getProcessDefinitionRemoteByDefinitionId(String defId) throws RemoteException; Purpose Get a definition by a corresponding definitionID Parameters - defId – definition’s ID value
Return Values Return with an array type of ProcessDefinitionRemote Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinitionRemote getProcessDefinitionRemoteWithInstanceId(String instanceId) throws RemoteException; Purpose Get a definition by a corresponding instanceId Parameters - instanceId – instance’s ID value
Return Values Return with an array type of ProcessDefinitionRemote Example
production version – Version related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProductionVersionIdAtThatTime(String defId, Date thatTime) throws RemoteException; Purpose Get definition’s VersionId by a corresponding definitionId that published into production Parameters - defId - definition's ID value
- thatTime - Production Date
Return Values Return VersionId of definition. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getFirstProductionVersionId(String defId) throws RemoteException; Purpose Get definition’s VersionId by a corresponding definitionId that originally published into production. Parameters - defId - definition's ID value
Return Values Return VersionId of definition. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinitionProductionVersionByAlias(String alias) throws RemoteException; Purpose Get definition’s VersionId by a corresponding alias that published into production. Parameters - defId - definition's ID value
Return Values Return VersionId of definition. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setProcessDefinitionProductionVersion(String pdvid) throws RemoteException; Purpose Set definition into production by definition VersionId Parameters - defVerId - definition's VersionId value
Return Values Return property value that is Serializable type Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinitionProductionVersion(String defId) throws RemoteException; Purpose Get version of definition in production by definitionId Parameters - defId - definition's ID value
Return Values Return String type production version Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinitionProductionVersionByName(String pdName) throws RemoteException; Purpose Get version of name definition in production by a corresponding definition. Parameters - defId - definition's ID value
Return Values Return String type production version Example get ProcessDefinition - Process Definition Collection related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinition getProcessDefinition(String defVerId) throws RemoteException; Purpose Get a definition by a corresponding definition VersionId. Parameters - defVerId - definition's VersionId value
Return Values Return ProcessDefinition object type Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinition(String defVerId, String encodingStyle) throws RemoteException; Purpose Get a definition's definition description by a corresponding definition VersionId. Parameters - defVerId - definition's VersionId value
- encodingStyle - encoding style
Return Values Return String type definition description of definition Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessDefinition getProcessDefinitionWithInstanceId(String instanceId) throws RemoteException; Purpose Get a definition that belongs to a corresponding instanceId Parameters - instanceId - instance's ID value
Return Values Return ProcessDefinition object type. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getProcessDefinitionWithInstanceId(String instanceId, String encodingStyle) throws RemoteException; Purpose Get a definition that belongs to a corresponding instanceId Parameters - defVerId - definition's VersionId value
- encodingStyle - encoding style
Return Values Return String type definition description of definition Example get Resource - Resource Collection related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getResource(String resourceId) throws RemoteException; Purpose Get definition description of a definition that belongs to a corresponding definition VersionId Difference between getProcessDefinition and this is that definition is in use except for process
Parameters - defVerId - definition's VersionId value
- encodingStyle - encoding style
Return Values Return String type definition description of definition Example From formActivity… String html = pm.getResource(prodVerId); get ProcessInstanceRemote - Process Operation(instance) Information Collection related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessInstanceRemote[] listProcessInstanceRemotes() throws RemoteException; Purpose Return all processInstances. Parameters Return Values Return an array type of ProcessInstanceRemote. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessInstanceRemote[] listProcessInstanceRemotes(String defId) throws RemoteException; Purpose Return a processInstance by a corresponding definitionId. Parameters * defId - definition's ID value Return Values Return an array type of ProcessInstanceRemote. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessInstanceRemote[] listProcessInstanceRemotes(String defId, String status) throws RemoteException; Purpose Return a corresponding status of processInstance by a definitionId Parameters - defId - definition's ID value
- Status - processInstance's status value
Return Values Return an array type of ProcessInstanceRemote. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessInstanceRemote[] listProcessArchiveRemotes() throws RemoteException; Purpose Return a corresponding status of processInstance by a definitionId Parameters Return Values Return an array type of ProcessInstanceRemote. Example
process instance - Process Operation (instance) related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void removeProcessInstance(String instanceId) throws RemoteException; Purpose Remove processInstance by a corresponding instanceId. Parameters - instanceId - processInstance's ID value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void stopProcessInstance(String instanceId) throws RemoteException; Purpose Make a corresponding processInstance stop. Parameters - instanceId - processInstance's ID value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ProcessInstance getProcessInstance(String instanceId) throws RemoteException; Purpose Get processInstance object by a corresponding instanceId Parameters - instanceId - processInstance's ID value
Return Values Returs ProcessInstance object. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setProcessInstanceInfo(String instanceId, String info) throws RemoteException; Purpose Enter additional descriptions into processInstance by a corresponding instanceId. Parameters - instanceId - processInstance's ID value
- Info - Additional description.
Return Values Return ProcessInstance object. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setProcessInstanceStatus(String instanceId, String status) throws RemoteException; Purpose Enter additional descriptions into processInstance by a corresponding instanceId. Parameters - instanceId - processInstance's ID value
- status - processInstance status value
Return Values No returns(void) Example Activity- Activity related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable getActivityProperty(String defVerId, String tracingTag, String propertyName) throws RemoteException; Purpose Get Activity properties of tracking tag that belongs to definition VersionId's definition. The definition here is an initial value that an instance is not yet created.
Parameters - defVerId - definition's VersionId value
- tracingTag - Activity's tracingTag.
- propertyName - Property name.
Return Values Return Serializable type of property value. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String getActivityStatus(String instanceId, String tracingTag) throws RemoteException; Purpose Get tracingTag Activity status value of instanceId that belongs to definition. Parameters - defVerId - definition's VersionId value
- tracingTag - Activity's tracingTag value
Return Values Return String type of status value. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Hashtable getActivityDetails(String defVerId, String tracingTag) throws RemoteException; Purpose Get tracingTag Activity status value of definition VersionId that belongs to definition. Parameters - defVerId - definition's VersionId value
- tracingTag - Activity's tracingTag value
Return Values Return property value stored in Hashtable. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public HashMap getInitiationParameterMap(String pvdid) throws RemoteException;; Purpose Get Activity Parameters of the first human work in the first stage of definition. Parameters - defVerId - definition's VersionId value
- tracingTag - Activity's tracingTag value
Return Values Return String type of status value. Example ActivityInstanceProperty- Activity Property related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Hashtable getActivityInstanceDetails(String instanceId, String tracingTag) throws RemoteException; Purpose Get tracingTag Activity property value of definition in which instanceId belongs Parameters - defVerId - definition's VersionId value
- tracingTag - Activity's tracingTag value
Return Values Return property value stored in Hashtable. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable getActivityInstanceProperty(String instanceId, String tracingTag, String propertyName) throws RemoteException; Purpose Get Activity properties of tracking tag that belongs to instanceId's definition. The property value here is that the setting value when instance is executed. it also affects a corresponding instance.
Parameters - instanceId - processInstance's ID value
- tracingTag - Activity's tracingTag.
- propertyName - Property's name.
Return Values Return Serializable type of property value. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setActivityInstanceProperty(String instanceId, String tracingTag, String propertyName, Serializable value) throws RemoteException; Purpose Set Activity properties of tracking tag that belongs to instanceId's definition. The property value here is that the setting value when instance is executed. it also affects a corresponding instance.
Parameters - instanceId - processInstance's ID value
- tracingTag - Activity's tracingTag.
- propertyName - Property's name.
- Value - Property value.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setActivityInstanceProperty(String instanceId, String tracingTag, String propertyName, Serializable value, Class valueType) throws RemoteException; Purpose Set Activity properties of tracking tag that belongs to instanceId's definition. The property value here is that the setting value when instance is executed. it also affects a corresponding instance.
Parameters - instanceId - processInstance's ID value
- tracingTag - Activity's tracingTag.
- propertyName - Property's name.
- Value - Property value.
- valueType - value's objectType
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Serializable doActivityAction(String instanceId, String tracingTag, String actionName, Serializable[] parameters, Class[] parameterTypes) throws RemoteException; Purpose This function is useful when creating activity parameters remotely in EJB mode. Parameters - instanceId - processInstance's ID value
- tracingTag - Activity's tracingTag.
- actionName - Action's name.
- parameters - Parameters' values.
- parameterTypes - parameter values' object types
Return Values No returns(void) Example Ways to set up Activity's Parameters
<in- process way>
ProcessDefinition pd = pm.getProcessDefinition("100");
Activity act = pd.getActivity("2");
HumanActivity ha = (HumanActivity)act;
Ha.createParameter(instance);
<remote way >
Pm.doActivityAction("1","2","createParameter",new serializable[]{…..},new Class[]{….})
Import and export- Process Definition Download related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void exportProcessDefinitionbyDefinitionId(String defId, boolean allVersion) throws Exception; Purpose Download process definitions by a corresponding definitionId. Parameters - defId - definition's ID value
- allVersion - Chooses whether all process versions need download or only production version.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void exportProcessDefinitionbyVersionId (String defVerId) throws Exception; Purpose Download process definitions by a corresponding definition VersionId. Parameters - defVerId - definition Version's ID value
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Vector importProcessDefinition(String parentFolder, InputStream loadedZipFile, UEngineArchive editedUa, String[] command ) throws Exception; Purpose Load exported process definition files. Parameters - parentFolder - Folder ID that needs import.
- loadedZipFile - exported process definition files
- editedUa - property updated process definition.
- Command - import command type (add, update)
Return Values Return imported process definitionIds. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Hashtable importProcessAliasCheck(InputStream is) throws Exception; Purpose Check process definition or configuration files that need import Parameters - is - zip file that needs import
Return Values Return imported process definitionIds. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public Hashtable importProcessAliasCheck(InputStream is) throws Exception; Purpose Check process definition or configuration files that need import Parameters - is - zip file that needs import
Return Values Return imported process definitionIds. Example flow chart - Flowchart related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String viewProcessDefinitionFlowChart(String defVerId, Map options) throws RemoteException; Purpose Get the flowchart of definition by a corresponding definition VersionId. Parameters - defVerId - definition Version's ID value
- Options - options for configuring chart.
Return Values Return string type of flowchart value. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String viewProcessInstanceFlowChart(String instanceId, Map options) throws RemoteException; Purpose Get the flowchart of definition by a corresponding instanctId. Parameters - instanceId - processInstance's ID value
- Options - options for configuring chart.
Return Values Return string type of flowchart value. Example folder - Folder related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void removeFolder(String folderName) throws RemoteException; Purpose Remove folders by a corresponding folder name. Parameters - folderName - folder name.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public String addFolder(String folderName, String parentFolder) throws RemoteException; Purpose Create a child folder under parent folder with the same name of a corresponding folder name Parameters - folderName - folder name.
- parentFolder - parent folder ID
Return Values Return created folder ID. Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void moveFolder(String defId, String parentFolder) throws RemoteException; Purpose Move a corresponding folder into parent folder. Parameters - defId - folder ID.
- parentFolder - parent folder ID
Return Values Return created folder ID. Example
dynamic change - Change Management related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void changeProcessDefinition(String instanceId, String definitionInXML) throws RemoteException; Purpose Update definition of executing instanceID. Parameters - instanceId - processInstance's ID value
- definitionInXML - ProcessDefinition defined in XML
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void changeProcessDefinition(String instanceId, ProcessDefinition definition) throws RemoteException; Purpose Update definition of executing instanceID. Parameters - instanceId - processInstance's ID value
- definition - ProcessDefinition's object
Return Values No returns(void) Example
Test - Process Handling related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setFault(String instanceId, String tracingTag, Exception fault) throws RemoteException; Purpose Set exception handling for tracingTag's Activity of a corresponding instanceId. Parameters - instanceId - processInstance's ID value
- tracingTag - Activity's tracingTag value
- fault - Exception object
Return Values No returns(void) Example signaling all the changes can be applied - Change Handling related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void applyChanges() throws RemoteException; Purpose Submit updated contents to the server and applies. Parameters Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void cancelChanges() throws RemoteException; Purpose Cancel to apply updated contents. Parameters Return Values No returns(void) Example
user can pass some parameters into the kernel - Login Information Processing related APIs
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setGenericContext(Map genericContext) throws RemoteException; Purpose Submit special information to the server. Parameters - genericContext - information that needs submission to the server
ex) request, respose, loggedRoleMapping
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public void setLoggedRoleMapping(RoleMapping roleMapping) throws RemoteException; Purpose Set up rolemapping of logged in users. Parameters - roleMapping - RoleMapping's object, it contains rollmapping information of logged in users.
Return Values No returns(void) Example
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public EventHandler[] getEventHandlersInAction(String instanceId) throws RemoteException; Purpose Get event handlers that can be invoked for definition by a corresponding instanceId. Parameters - instanceId - processInstance's ID value
Return Values Return an array type of event handler object, EventHandler. Example Org.uengine.processmanager.ProcessManagerRemote
File name org.uengine.processmanager.ProcessManagerRemote.java Method name public ActivityReference getInitiatorHumanActivityReference(String pdvid) throws RemoteException; Purpose Get starting workitem handler references of defintion by a corresponding definition VersionId. Parameters - pdvid - definition Version's ID value
Return Values Return an object type of ActivityReference. Example Appendix B – Useful Examples that used APIs
For this time, we learn various customizing ways by using uEngine’s available APIs with a proposal process scenario that happens in a real company situation.
Example Title org.uengine.processmanager.ProcessManagerRemote.java Creation Steps - Process Modeling [Process Designer]
- Create DB tables
- Separate Activities[Proposal, View, WorkLists, Approval, Return, Refused] Task screen creation [Web(JSP) Programing]
Proposal Process
There are 2 steps for proposal process as shown in figure 21 that are a ‘Proposal Registration’ and a ‘Proposal Approval’. From Proposal Registration accepts the proposal contents. When the ‘Proposal Approval’ approves the proposal contents, it completes the process. However, if it returns, it will go back to the first step of the process, and repeat the same steps.
Figure 21. Proposal Process
There are ‘regno’ and ‘approve’ process variables. ‘regno’ variable saves the sequential number of proposal contents, while ‘approve’ receives the result either ‘proposal approved’ or ‘proposal rejected, and it passes the result to switchActivity and then decides which one to follow and execute.
SAMPLE_PROPOSAL Table
Column Name Data Type Description PROPOSAL_ID INT Create a sequentially incremented ID PROPOSAL_NM VARCHAR(100) Proposal name CHARGE_NM VARCHAR(50) Person name in charge of the task PROPOSAL_BACKGROUND VARCHAR(1000) Proposal background REG_ID VARCHAR(19) Register ID Workitem Handler Customizing
WIH of Proposal Registration Activity consists of the entry screen where the content is entered by users, Proposal Approval Activity needs to develop a workitem handler that makes a decision whether the proposal is approved or rejected.
RegisterProposal
At this time, let us create a WIH for proposal registration Activity. Create this directory, ‘wih/proposal/registerProposal’ and locate a customized index.jsp file into the directory that we just created. As we learned from Process Definition part, there is rejection functionality in this Activity, therefore, the same entered information must be displayed in the stage of the task where it goes back to after rejection is made.Figure 22. Proposal Registration Execution Screen - index.jsp
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="org.uengine.util.dao.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //======================= Variable initialization ========================================// // Gets ProcessManagerRemote object and process information in order to use APIs. // Make use of APIs after getting ProcessManagerRemote object. ProcessManagerRemote pm = processManagerFactory.getProcessManager(); //Gets instanceid in order to use APIs String instanceId = request.getParameter("instanceId"); //Gets values in order to transmit the values to submit.jsp String definitionId = request.getParameter("processDefinition"); //Gets tracingTag in order to check the status String tracingTag = request.getParameter("tracingTag"); // Variable declaration for proposal rejection. String proposal_nm = ""; String background = ""; //Variable the boolean value whether process is being executed boolean isRunning = true; //========================= Due to the rejection, the same steps of tasks repeat =================================// //if instanceid is not null, //rejection contents must be displayed at the entry screen if rejection is made. if(instanceId!=null){ //API that helps us get ProcessInstance ProcessInstance instance = pm.getProcessInstance(instanceId); //API that helps us get status String status = pm.getActivityStatus(instanceId, tracingTag); //Check the status whether it is in execution if(status!=null && !status.equals("Running") && !status.equals("Timeout")){ isRunning = false; } //API that helps us get regno process variable Number regno = (Number)pm.getProcessVariable(instanceId, "", "regno"); //Database SQL query by using IDAO class //Codes needed for getting the rejection context of a corresponding regno IDAO dao = ConnectiveDAO.createDAOImpl( instance.getProcessTransactionContext(), "select * from sample_proposal where proposal_id = ?regno", IDAO.class ); //Assign rejected proposal regno into proposal_id and execute the SQL query. //assign values into ?regno part dao.set("regno", regno); dao.select(); //API that receives the values that obtailed after executing SQL query //if the rejection content exists, gets (dao.next()==true). if(dao.next()){ proposal_nm = (String)dao.get("proposal_nm"); background = (String)dao.get("proposal_background"); } } %> //============================== User Interface ===========================================// <h1>Proposal Registration </h1> <p> <form action="submit.jsp"> // Variables that will be sumitted to submit.jsp. <input type=hidden value="<%=definitionId%>" name="processDefinition"> <input type=hidden value="<%=instanceId%>" name="instanceId"> <input type=hidden value="<%=tracingTag%>" name="tracingTag"> // displayed screen on users’ screens Proposal Name: <input name="proposalName" value="<%=proposal_nm%>"><br> Proposal Company : <input name="proposalCompanyName"><br> Person in charge for the proposal : <input name="rightPersonName" value="<%=loggedUserFullName%>"><br> The phone number of the person in charge: <input name="rightPersonPhone" value=""><br> Proposal Background: <input name="background" value="<%=background%>"><br> Service Summary: <input name="serviceDesc"><br> <p> //If the process is in execution, submit button will not be displayed <% if (isRunning){%> <input type=submit> <%}%> </form>- submit
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="javax.transaction.*, org.uengine.util.dao.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //=========================== Variable Initialization ===========================================// // Gets ProcessManagerRemote object and process information for using APIs // gets ProcessManagerRemote object. ProcessManagerRemote pm = processManagerFactory.getProcessManager(); //process information received by index.jsp. //parameters for process initialization String definitionId = request.getParameter("processDefinition"); //completeWorkitem function parameters for completing woritem String tracingTag = request.getParameter("tracingTag"); //Receives instanceid for using APIs. String instanceId = request.getParameter("instanceId"); // String(request.getParameter("proposalName").getBytes("8859_1"), "UTF-8") for proper Korean encoding //Receives proposal name String proposal_nm = new String(request.getParameter("proposalName").getBytes("8859_1"), "UTF-8"); //Receives the name of person in charge. String charge_nm = new String(request.getParameter("rightPersonName").getBytes("8859_1"), "UTF-8"); //Receives the proposal background content String proposal_background = new String(request.getParameter("background").getBytes("8859_1"), "UTF-8"); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext. USERTRANSACTION_JNDI_NAME) : null); try{ //Start a transaction if(tx!=null) tx.begin(); //============================= Process initialization ============================================// //necessary initialization work for process execution. //Process Initialization instanceId = pm.initialize(definitionId, instanceId, loggedRoleMapping); //use genericContext for submitting login information to the server Map genericContext = new HashMap(); genericContext.put(HumanActivity.GENERICCONTEXT_CURR_LOGGED_ROLEMAPPING, loggedRoleMapping); genericContext.put("request", request); pm.setGenericContext(genericContext); // API that helps us get ProcessInstance ProcessInstance instance = pm.getProcessInstance(instanceId); //============================== enter proposal content into database ===============================// // Variable for getting SEQ_PROPOSAL Number regno = new Long(0); //execute SEQ_PROPOSAL //gets the data of current regno value plus 1. // regno value becomes proposal_id. IDAO dao = ConnectiveDAO.createDAOImpl( instance.getProcessTransactionContext(), "select NEXT VALUE FOR SEQ_PROPOSAL as regno from dual", IDAO.class ); dao.select(); if(dao.next()) regno = (Number)dao.get("regno"); //contents entered by users save into database. dao = ConnectiveDAO.createDAOImpl( instance.getProcessTransactionContext(), "insert into SAMPLE_PROPOSAL( "+ " proposal_id ,"+ " proposal_nm ,"+ " charge_nm ,"+ " proposal_background ,"+ " reg_id "+ ") values ("+ " ?proposal_id,"+ " ?proposal_nm ,"+ " ?charge_nm ,"+ " ?proposal_background ,"+ " ?reg_id"+ ")", IDAO.class ); //Assign values into respective variables. dao.set("proposal_id", regno); dao.set("proposal_nm", proposal_nm); dao.set("charge_nm", charge_nm); dao.set("proposal_background", proposal_background); dao.set("reg_id", loggedUserId); dao.update(); //Passes regno value into Process variable. pm.setProcessVariable(instanceId, "", "regno", regno); //Completes workitem. pm.completeWorkitem(instanceId, tracingTag, null, null); //Applies any changes to the server pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> <h1><font color=green> This proposal is successfully accepted!! <% }catch(Exception e){ e.printStackTrace(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception e){} } %>signProposal
At this time, let us create a WIH for proposal acceptance Activity. Create this directory, ‘wih/proposal/ signProposal’ and locate customized index.jsp and submit files into the directory that we just created. At this proposal acceptance stage, the received proposal content completes when it is approved, otherwise, it goes back to the stage where the proposal registration form appeared.
Figure 23. Proposal Approval
- index.jsp
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="org.uengine.util.dao.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //===========================Variable initialization ======================================// //Gets instanceid in order to use APIs String instanceId = request.getParameter("instanceId"); //definitionid that will be submitted to submit.jsp String definitionId = request.getParameter("processDefinition"); //tracingTag that will be submitted to submit.jsp String tracingTag = request.getParameter("tracingTag"); // Gets ProcessManagerRemote object for using APIs ProcessManagerRemote pm = processManagerFactory.getProcessManager(); // API function that gets ProcessInstance ProcessInstance instance = pm.getProcessInstance(instanceId); %> //============================ User Interface ===================================// <h1>Proposal Approval</h1> <p> <form action="submit.jsp"> //values that will be submitted to submit.jsp <input type=hidden value="<%=instanceId%>" name="instanceId"> <input type=hidden value="<%=definitionId%>" name="processDefinition"> <input type=hidden value="<%=tracingTag%>" name="tracingTag"> /* * At proposal registration stage, regno value needed in order to display entered information * regno value is obtained from the previous stage where the value is stored * Display the proposal registration content from database by a corresponding regno */ <% //receives regno via Process Variable Number regno = (Number)pm.getProcessVariable(instanceId, "", "regno"); //Execute SQL query that helps us get corresponding information from database IDAO dao = ConnectiveDAO.createDAOImpl( instance.getProcessTransactionContext(), "select * from sample_proposal where proposal_id = ?regno", IDAO.class ); dao.set("regno", regno); dao.select(); String proposal_nm = ""; String background = ""; //if a corresponding data exists, take them. if(dao.next()){ proposal_nm = (String)dao.get("proposal_nm"); background = (String)dao.get("proposal_background"); } //obtains rolemapping infromation RoleMapping user = pm.getRoleMappingObject(instanceId, "initiator"); %> //Parts that are displayed on the screen Proposal name: <%=proposal_nm%><br> Proposal background: <%=background%><br> BP person in charge: <%=user.getResourceName()%> <hr> Do you approve this proposal? <input type=radio name="approve" value="yes">Approval <input type=radio name="approve" value="no">Rejection <p> <input type=submit> </form>- submit
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="javax.transaction.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //============================ Variable initialization ======================================// // Gets ProcessManagerRemote object for using APIs ProcessManagerRemote pm = processManagerFactory.getProcessManager(); //receives entered contents from index.jsp String instanceId = request.getParameter("instanceId"); String definitionId = request.getParameter("processDefinition"); String tracingTag = request.getParameter("tracingTag"); //Variable that contains the proposal either approved or rejected String approve = request.getParameter("approve"); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext. USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); //=============================== Process initialization and apply to the server =======================================// //Initialization instanceId = pm.initialize(definitionId, instanceId, loggedRoleMapping); //pass the approval value that gets from index.jsp to process variables //With this value, switchActivity decides which way it follows pm.setProcessVariable(instanceId, "", "approve", approve); //Complete a workitem pm.completeWorkitem(instanceId, tracingTag, null, null); //Apply changes to the server pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> <h1><font color=green> The proposal is successfully <%="yes".equals(approve) ? "approved" : "rejected "%>! <% }catch(Exception e){ e.printStackTrace(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception e){} } %>Check Processes
At this time, we will make a page that has the functionality of checking workitems. In order to check the workitems, we need criterions, because users only need to see filtered workitems. Therefore, at present, we are making a proposal process, let us add necessary functions for the purpose.
Figure 24. Workitem List
As Figure 24 shows, there are 2 proposals listed, and 3 buttons are displayed on the bottom left side of the proposal list. These are “Dismiss”, “Reject”, and “Select people in charge”. “Dismiss” means that the selected proposals will be permanently removed from the workitem list. “Reject” proceeds the functionality that the first page of the process will appear, and repeat the process all over again. “Select people in charge” includes the functionality that currently assigned people in charge can be changed to other people. With this page implementation, workitems will be automatically displayed on the assigned workers. Therefore, listing criterions can be customized according to the assigned workers for the tasks.
workItemListworkItemList retrieves workitems and displays them on the user’s screen. For instance, we will create a special work list page that displays only workitems in the approval stage of the proposal process. We assume that the proposal process definition(defid) is 23 and the proposal approval tracingTag which is the second step of the process is 2. Create ‘uengine-web/proposal’ directory and save the following jsp file under the directory.
- proposalList.jsp
<%@include file="../common/header.jsp"%> <%@include file="../common/getLoggedUser.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="org.uengine.util.dao.*"%> //================================ function declaration part ==========================================// <script> //It executes a corresponding WIH on the new window after clicking the list. function viewTaskInfo( taskid, instanceId, tracingTag ){ var option = "width=500,height=400,scrollbars=yes,resizable=yes"; ///workitemHandler.jsp is responsible for finding WIH and executing it. var url = "../processparticipant/worklist/workitemHandler.jsp?taskId="+taskid+"&instanceId="+instanceId+"&tracingTag ="+tracingTag; window.open(url, "wihspace", option) } //It works when the “Dismiss” button is pushed, the selected proposals will be removed from the list function dropInstance(){ var instanceId=""; for(i=0; i<document.forms[0].selectedInstance.length; i++) { If(document.forms[0].selectedInstance[i].checked==true) instanceId= document.forms[0].selectedInstance[i].value; } var option = "width=500,height=400,scrollbars=yes,resizable=yes"; var url = "dropProposal.jsp?instanceId="+instanceId; window.open(url, "wihspace", option) } //When the “Reject” button is pushed, it returns to the previous stage of the process. function backInstance(){ var instanceId=""; for(i=0; i<document.forms[0].selectedInstance.length; i++) { If(document.forms[0].selectedInstance[i].checked==true) instanceId= document.forms[0].selectedInstance[i].value; } var option = "width=500,height=400,scrollbars=yes,resizable=yes"; var url = "backProposal.jsp?instanceId="+instanceId; window.open(url, "wihspace", option) } //Changes the people in charge, it executes roleMappingChangeForm. function setCharge(){ var instanceId=""; for(i=0; i<document.forms[0].selectedInstance.length; i++) { If(document.forms[0].selectedInstance[i].checked==true) instanceId= document.forms[0].selectedInstance[i].value; } var option = "width=500,height=400,scrollbars=yes,resizable=yes"; var url = "../processmanager/roleMappingChangeForm.jsp?instanceId="+instanceId+"&roleName=Initiator"; window.open(url, "wihspace", option) } </script> //=============================== User Interface=================================// <form> <table border=1> <tr> <td>Select</td> <td>proposal_nm</td> <td>charge_nm</td> <td>starteddate</td> <td>info</td> <td>instid</td> <td>trctag</td> </tr> <% //A query for retrieving the list, the query criteria is important. //Retrieve only worklists in progress after joining 3 different tables. IDAO dao = GenericDAO.createDAOImpl( DefaultConnectionFactory.create(), "select "+ " sp.proposal_nm, "+ " sp.charge_nm, "+ " pi.starteddate, "+ " pi.info, "+ " pi.instid, "+ " wl.trctag, "+ " wl.taskid "+ "from "+ " bpm_worklist wl, "+ " bpm_procinst pi, "+ " sample_proposal sp "+ "where "+ " pi.defid = 23 "+ " and wl.endpoint=?endpoint "+ " and (wl.status='NEW' or wl.status='CONFIRMED') "+ " and wl.trctag=2 "+ " and pi.instid = wl.instid "+ " and pi.ext1 = sp.proposal_id ", IDAO.class ); //assign logged in user id to endpoint. dao.set("endpoint", loggedUserId); dao.select(); //displays workitems after selecting the workitems while(dao.next()){ //proposal name String proposal_nm = dao.getString("proposal_nm"); //person in charge String charge_nm = dao.getString("charge_nm"); //proposal creation date Date starteddate = (Date)dao.get("starteddate"); //explains the stage that is being processed String info = dao.getString("info"); //instanceid Number instid = (Number)dao.get("instid"); //taskid Number taskId = (Number)dao.get("taskid"); //TracingTag String trctag = dao.getString("trctag"); %> <tr> // construct the list <td><input type=radio name="selectedInstance" value="<%=instid%>"></td> //A new window popup, and the task starts processing after the list is clicked <td><a href="javascript:viewTaskInfo( '<%=taskId%>', '<%=instid%>', '<%=trctag%>')"><%=proposal_nm%></a></td> <td><%=charge_nm%></td> <td><%=starteddate%></td> <td><%=info%></td> <td><%=instid%></td> <td><%=trctag%></td> </tr> <% } %> // print out the button </table> <input type=button onclick="dropInstance()" value="Dismiss"> <input type=button onclick="backInstance()" value="Reject"> <input type=button onclick="setCharge()" value="Select people in charge"> </form>When executing this page, http://localhost:8080/uengine-web/proposal/proposalList.jsp, we are able to see the workitems that is in the approval stage. Additionaly, click one of proposal_nm column items, a new window appears and WIH is being executed on it. The reason can be explained by looking at “workitemHandler.jsp” file, the file searches a corresponding WIH and executes the WIH. Multiple ways of SQL query can be assumed, just design an appropriate one according to the situation.
Select people in charge The functionality of selecting people in charge for the tasks is useful when we want to change the current people to different people . It simply works by selecting one from the organization chart and clicking the “Select people in charge” button. After that, ‘roleMappingChangeForm’ is automatically executed. This is already implemented and the selected associates can be people in charge for the task, and instanceid and rolename must be passed to the page.
Figure 25. The screen of selecting people in charge
RejectionThis rejection is exactly working in the same way like the one we learned previously. For this time, we do not make use of process variables. However, we directly use APIs instead. Most of source codes are familiar, but for this time, we make use of flowControl function, and the third argument for the tracingtag parameter should be 1. After that, it goes back to the first stage of the process. The behavior is called “Rejection”.
- backProposal.jsp
<%@include file="../common/header.jsp"%> <%@include file="../common/getLoggedUser.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="javax.transaction.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //================================== Variable initialization ============================================// //Get the ProcessManagerRemote object by using APIs. ProcessManagerRemote pm = processManagerFactory.getProcessManager(); //For flowcontrol’s second argument of instanceid parameter, we need the instanceid. String instanceId = request.getParameter("instanceId"); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); //=============================== Conduct “Rejection” process ============================================// //Proposal creation activity’s trcTag = 1 //For rejection, set the value of “trcTag” with 1. pm.flowControl("compensateTo", instanceId, "1"); // <<<<<<<<<<<<<<<<<<<<<<<<<<<< pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> <h1><font color=green> This proposal is successfully rejected!! <% }catch(Exception e){ e.printStackTrace(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception e){} } %>Dismission
The source codes of dismission are almost same as the rejection. Then only difference is that we use the stopProcessInstance function with an instanceid argument.
- dropProposal.jsp
<%@include file="../common/header.jsp"%> <%@include file="../common/getLoggedUser.jsp"%> <%@page pageEncoding="KSC5601"%> <%@page import="javax.transaction.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% //==================================== Variable initialization ===========================================// // Get the ProcessManagerRemote object by using APIs. ProcessManagerRemote pm = processManagerFactory.getProcessManager(); //get an instanceid for stopProcessInstance String instanceId = request.getParameter("instanceId"); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); //================================ Conduct proposal dismission ==========================================// //dismiss the proposal by invoking “stopProcessInstance”. pm.stopProcessInstance(instanceId); pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> <h1><font color=green> This proposal is successfully dismissed!! <% }catch(Exception e){ e.printStackTrace(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception e){} } %>Appendix C – Sample Code
3.3. ProcessManager Interface Example #1. - initiateProcess.jsp
<%@include file="../common/header.jsp"%> <%@page import="javax.transaction.*"%> <LINK href="../style/uengine.css" type=text/css rel=stylesheet> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /><% ProcessManagerRemote pm = processManagerFactory.getProcessManager(); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); String definitionName = decode(request.getParameter("definitionName")); String productionVersionId = pm.getProcessDefinitionProductionVersionByName(definitionName); String instanceId = pm.initializeProcess(productionVersionId); pm.applyChanges(); try{ tx.commit(); }catch(Exception txe){ } %> Process instance '<%=instanceId%>' has been successfully initialized.<p> <% }catch(Exception e){ try{ pm.cancelChanges(); }catch(Exception txe){ } try{ tx.rollback(); }catch(Exception txe){ } throw e; }finally{ try{ pm.remove(); }catch(Exception ex){ System.out.println("error when to remove pm"); ex.printStackTrace(); } } %>3.3. ProcessManager Interface Example #2. - startProcess.jsp
<%@include file="../common/header.jsp"%> <%@page import="javax.transaction.*"%> <LINK href="../style/uengine.css" type=text/css rel=stylesheet> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /><% ProcessManagerRemote pm = processManagerFactory.getProcessManager(); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); String instanceId = decode(request.getParameter("instanceId")); pm.executeProcess(instanceId); pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> Process instance '<%=instanceId%>' has been successfully started.<p> <% }catch(Exception e){ try{ pm.cancelChanges(); }catch(Exception ex){ } if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception ex){ } } %>3.3. ProcessManager Interface Example #3. - initiateAndStartProcess.jsp
<%@include file="../common/header.jsp"%> <%@page import="javax.transaction.*"%> <LINK href="../style/uengine.css" type=text/css rel=stylesheet> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /><% ProcessManagerRemote pm = processManagerFactory.getProcessManager(); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); String definitionName = decode(request.getParameter("definitionName")); String productionVersionId = pm.getProcessDefinitionProductionVersionByName(definitionName); String instanceId = pm.initializeProcess(productionVersionId); pm.executeProcess(instanceId); pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> Process instance '<%=instanceId%>' has been successfully initialized and started.<p> <% }catch(Exception e){ try{ pm.cancelChanges(); }catch(Exception ex){ } if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception ex){ } } %>3.3. ProcessManager Interface Example #4. - getProcessVariable.jsp
<%@include file="../common/header.jsp"%> <%@page import="javax.transaction.*"%> <LINK href="../style/uengine.css" type=text/css rel=stylesheet> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /><% ProcessManagerRemote pm = processManagerFactory.getProcessManagerForReadOnly(); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); String instanceId = decode(request.getParameter("instanceId")); String variableName = decode(request.getParameter("variableName")); Serializable value = pm.getProcessVariable(instanceId, "", variableName); %> The value is '<%=value%>'.<p> <% }catch(Exception e){ throw e; }finally{ try{ pm.remove(); }catch(Exception ex){ } } %>3.3. ProcessManager Interface Example #5. - setProcessVariable.jsp
<%@include file="../common/header.jsp"%> <%@page import="javax.transaction.*"%> <LINK href="../style/uengine.css" type=text/css rel=stylesheet> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /><% ProcessManagerRemote pm = processManagerFactory.getProcessManager(); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); String instanceId = decode(request.getParameter("instanceId")); String variableName = decode(request.getParameter("variableName")); String value = decode(request.getParameter("value")); pm.setProcessVariable(instanceId, "", variableName, value); pm.applyChanges(); try{ tx.commit(); }catch(Exception txe){ } %> Value has been set.<p> <% }catch(Exception e){ try{ pm.cancelChanges(); }catch(Exception txe){ } try{ tx.rollback(); }catch(Exception txe){ } throw e; }finally{ try{ pm.remove(); }catch(Exception ex){ } } %>3.5.1 Activity Definition Class Reference Codes #1 - Activity.java
public abstract class Activity{ 1. Field Declaration Activity parentActivity ; // Parent Activity including itself (Usually it becomes ComplexActivity) String name; String tracingTag; // It is distinguished among different activities by looking at unique tag value. int retryLimit; // No of times that it tried int retryDelay; // Amount of time used during retrying(second based) Role[] roles; // Role declaration ProcessVariable[] processVariableDescriptors; //Process variable declaration 1. Constructor Declaration public Activity(){} // An empty constructor for reflexion 2. Logic Declaration This part is implemented by developers or inherited. It is separately invoked when uEngine is executing. The working order follows createInstance, beforeExecute, executeActivity, onEvent (if done), afterExecute. protected ActivityInstance createInstance(ActivityInstance instanceInCreating) throws Exception{ return instanceInCreating; } protected void beforeExecute(ActivityInstance instance) throws Exception{} abstract protected void executeActivity(ActivityInstance instance) throws Exception; protected void afterExecute(ActivityInstance instance) throws Exception{} protected void onEvent(String command, ActivityInstance instance, Object payload) throws Exception{} 3. Callback Methods Additionally, besides the basic logic declaration, necessary methods are invoked by management tools during uEngine execution. protected synchronized String getProcessStatus(ActivityInstance inst, String roleName){} // Returns the status public void stop(ActivityInstance instance) throws Exception{} // Handle “Stop” request public void suspend(ActivityInstance instance) throws Exception{} // Handle ‘Suspend’ request public void resume(ActivityInstance instance) throws Exception{} // Handle ‘Resume’ request public void skip(ActivityInstance instance) throws Exception{} // Handle ‘Skip’ request public void compensate(ActivityInstance instance) throws Exception{} // Handle ‘Compensate’ request public ActivityDesigner createDesigner(){} // Returns GUI tool for current activity edition public Map getActivityDetails(ActivityInstance inst){// Provide detailed Activity status (Key-and-Value) return details; } public ValidationContext validate(){} // Validate Activity setup at design time 4. Utility methods Necessary methods needed when writing michellaneous activity logic public Activity getRootActivity(){ return root; } // get the Root Activity. public ProcessDefinition getProcessDefinition(){ //All process definitions that this Activity holds return (ProcessDefinition)getRootActivity(); } public void fireComplete(ActivityInstance instance) throws Exception{ //If it is executed successfully onEvent(ACTIVITY_DONE, instance, null); } public void fireFault(ActivityInstance instance, Exception fault) throws Exception{ //if it fails onEvent(ACTIVITY_FAULT, instance, fault); } }3.5.2 Activity Flow Control Class Reference Codes #1 - ComplexActivity.java
public class ComplexActivity extends Activity { 1. Field Declaration private Vector childActivities; // The Vector that contains Children 2. Constructor Declaration public ComplexActivity(){} 3. Invoked crateInstance method implementation when creating an instance – It initiates necessary current step(currentStep) for itself, invoking initialization routine for its children. public ActivityInstance createInstance(ActivityInstance instanceInCreating) throws Exception{ super.createInstance(instanceInCreating); //Sets current running state instanceInCreating.set(getTracingTag(), "currentStep", "0"); //Lets each child activity initialize process instance Vector childActivities = getChildActivities(); for(Enumeration enum = childActivities.elements(); enum.hasMoreElements(); ){ Activity child = (Activity)enum.nextElement(); child.createInstance(instanceInCreating); } return instanceInCreating; } 4. Conduct all steps of Activities, Conduct the total number of child activities, send a completion signal(fireDone). (Real source codes are being queued via JMS, but the following codes are written in a direct ways to conduct) protected void executeActivity(ActivityInstance instance) throws Exception{ int currStep = getCurrentStep(instance); if(currStep >= childActivities.size()){ instance.fireDone(); fireComplete(instance); return; } Activity childActivity = (Activity)getChildActivities().elementAt(currStep); childActivity.executeActivity(instance); // In real codes, JMS invocation is needed } 5. If a child Activity completes, The CHILD_DONE event is delivered to the parent Activity. The parent Activity receives the message, increments the value of currentStep, executes next Activity. protected void onEvent(String command, ActivityInstance instance, Object payload) throws Exception{ //dispatching leaf childs if(command.equals(CHILD_DONE)){ int currStep = getCurrentStep(instance); currStep++; setCurrentStep(instance, currStep); executeActivity(instance); //execute next }else super.onEvent(command, instance, null); } …. }3.5 Apply Main Class, Example #1
The following example describes a process definition with source codes.
Figure 26. Example Process
public class SimpleProcess extends ProcessDefinition{ public SimpleProcess(){ HumanActivity act1 = new HumanActivity(); act1.setName("Act1"); addChildActivity(act1); HumanActivity act2 = new HumanActivity(); act2.setName("Act2"); HumanActivity act3 = new HumanActivity(); act3.setName("Act3"); SwitchActivity sa = new SwitchActivity(); sa.setName("Switch"); sa.addChildActivity(act2); sa.addChildActivity(act3); addChildActivity(sa); } }We are able to see that Act1 and Switch are placing in the same level, and Act2 and Act3 are child activities of the Switch. [Note] In reality, these are initialized in XML format and managed as a file.
3.8.4 Transaction Usage example #1
JDBCExtWorklist
JDBCExtWorklist is a class that conducts assigning and managing WorkItem. As we learned from previous chapter, It is a good chance to understand how to make use of SynchronizedDAO. When assigning a task at first, addWorkItemImpl method is invoked and assigned WorkItem’s taskID is used as a key which helps create a WorkListDAO typed DAO, it eventually stores into sharedContext. This DAO separately creates and shares a WorkListDAO for each taskID.
/* * One part of addWorktemImpl method in JDBCExtWorklist.java * WorkListDAO type is already declared. *When reservedTaskId is generated, we need to use “findSynchronizedDAO”, because DAO is already created. *otherwise, create a new taskID, create a DAO via createSynchronizedDAO invocation. */ final WorkListDAO wl; Long taskId; if(reservedTaskId!=null){ taskId = new Long(reservedTaskId); wl = (WorkListDAO) tc.findSynchronizedDAO("BPM_WORKLIST", "taskId", taskId, WorkListDAO.class); }else{ taskId = UniqueKeyGenerator.issueWorkItemKey(tc); wl = (WorkListDAO) tc.createSynchronizedDAO("BPM_WORKLIST", "taskId", taskId, WorkListDAO.class); }When we need WorkListDAO created via addWorkItemImpl for a second time, findSynchronizedDAO method along with the taskID search criteria must be used.
// The method that cancels WorkItem public void cancelWorkItem(String taskID, KeyedParameter[] options, TransactionContext tc) throws RemoteException { try{ WorkListDAO wl = (WorkListDAO) tc.findSynchronizedDAO("BPM_WORKLIST", "taskId", new Long(taskID), WorkListDAO.class); wl.setStatus(DefaultWorkList.WORKITEM_STATUS_CANCELLED); }catch(Exception e){ throw new RemoteException("ExtWorkList", e); } } //The method that completes WorkItem public void completeWorkItem(String taskID, KeyedParameter[] options, TransactionContext tc) throws RemoteException { try{ DAOFactory daoFactory = DAOFactory.getInstance(tc); Calendar now = daoFactory.getNow(); WorkListDAO wl = (WorkListDAO) tc.findSynchronizedDAO("BPM_WORKLIST", "taskId", new Long(taskID), WorkListDAO.class); wl.setStatus(DefaultWorkList.WORKITEM_STATUS_COMPLETED); wl.setEndDate(new Timestamp(now.getTimeInMillis())); }catch(Exception e){ throw new RemoteException("ExtWorkList", e); } }
Figure 27. Example - JDBCWorkList's DAO caching
5.4.1 Type Declaration Example #1
Hypersonic DB is the default database installed under the uEngine. By using hypersonic DB, we will be able to execute the following Example. Before doing that, we should run runManager.bat file located in uengine_standalone\hsqldb\demo\runServer. And then, create AddressBook table, insert corresponding data to the table. Therefore, we finally execute the following codes.
//create a table. Think of database ‘create’ statement Type addressBook = new Type( " AddressBook ", // table name // column type size new FieldDescriptor[]{ new FieldDescriptor("PERSONNAME",”Name”), new FieldDescriptor("ADDRESS",”Address”), new FieldDescriptor("AGE",”Age”, Types.INTEGER), new FieldDescriptor("PHONENUMBER",”Phone Number”) }, con //database connection that this table is using );5.4.2 Automatic UI Creation Example #1
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@include file="../../wihDefaultTemplate/initialize.jsp"%> <%@page import="org.uengine.contexts.ComplexType"%> <form action=submit.jsp method=POST> <input type=hidden value='<%=decode(request.getParameter("instanceId"))%>' name=instanceId> <input type=hidden value='<%=request.getParameter("message")%>' name=message> <input type=hidden value='<%=decode(request.getParameter("processDefinition"))%>' name=processDefinition> <input type=hidden value='<%=request.getParameter("tracingTag")%>' name=tracingTag> <input type=hidden value='<%=request.getParameter("taskId")%>' name=taskId> <input type=hidden value='<%=request.getParameter("initiate")%>' name=initiate> <% //------------- show flow chart -------------------// Hashtable options = new Hashtable(); options.put("decorated", "yes"); options.put("nowrap", "yes"); options.put("locale", loggedUserLocale); options.put("imagePathRoot", "../../../processmanager/"); String chart; if(initiate) chart = pm.viewProcessDefinitionFlowChart(processDefinition, options); else chart = pm.viewProcessInstanceFlowChart(instanceId, options); %> <%=chart %> //Create web UI automatically <table cellspacing=1 border=1> <% ParameterContext[] parameterContexts = (ParameterContext[])pm.getActivityProperty(processDefinition, tracingTag, "parameters"); Properties scriptSet = new Properties(); HashMap inputterOptions = new HashMap(); inputterOptions.put("instanceId", instanceId); if(UEngineUtil.isNotEmpty(instanceId)) inputterOptions.put("instance", pm.getProcessInstance(instanceId)); inputterOptions.put("defVerId", processDefinition); inputterOptions.put("definitionRemote", pdr); inputterOptions.put("processManager", pm); if(parameterContexts !=null) for(int j=0; j<parameterContexts.length; j++){ ParameterContext parameterContext = parameterContexts[j]; %> <tr> <td align=right> <b><%=(parameterContext.getArgument()!=null ? parameterContext.getArgument().getText(loggedUserLocale): parameterContext.getVariable().getDisplayName().getText(loggedUserLocale))%> : </b> </td> <td> <% Object existingValue = (piRemote!=null ? parameterContext.getVariable().get(piRemote, "") : parameterContext.getVariable().getDefaultValue()); WebInputter defaultInputter = (WebInputter)parameterContext.getVariable().getInputter(); if(defaultInputter==null){ Class objType = parameterContext.getVariable().getType(); if(objType == ComplexType.class){ objType = ((ComplexType)existingValue).getTypeClass(pm); } ObjectType outputClsTable = new ObjectType(objType); FieldDescriptor[] arrayFieldDescriptors = outputClsTable.getFieldDescriptors(); String[] columns = new String[arrayFieldDescriptors.length]; for(int i=0; i<arrayFieldDescriptors.length; i++){ columns[i] = arrayFieldDescriptors[i].getName(); } for(int i=0; i<columns.length; i++){ FieldDescriptor fieldDescriptor = outputClsTable.getFieldDescriptor(columns[i]); %> <%=(fieldDescriptor.getDisplayName().equals("-") ? "":fieldDescriptor.getDisplayName()+":")%> <% WebInputter inputter = fieldDescriptor.getWebInputter(); inputter.addScriptTo(scriptSet, parameterContext.getVariable().getName(), fieldDescriptor, existingValue, inputterOptions); Object propertyValue = null; try{ propertyValue = objType.getMethod("get" + columns[i], new Class[]{}).invoke(existingValue, new Object[]{}); }catch(Exception e){ } String htmlFromInputter; if(isViewMode || ParameterContext.DIRECTION_IN.equals(parameterContext.getDirection())){ htmlFromInputter = inputter.getViewerHTML(parameterContext.getVariable().getName(), fieldDescriptor, propertyValue, inputterOptions); }else{ htmlFromInputter = inputter.getInputterHTML(parameterContext.getVariable().getName(), fieldDescriptor, propertyValue, inputterOptions); } %> <%=htmlFromInputter%> <% if(i<columns.length-1){%> <br> <%} } }else{ FieldDescriptor fieldDescriptor = new FieldDescriptor("value", "value"); defaultInputter.addScriptTo(scriptSet, parameterContext.getVariable().getName(), fieldDescriptor, existingValue, inputterOptions); String htmlFromInputter; if(isViewMode || ParameterContext.DIRECTION_IN.equals(parameterContext.getDirection())){ htmlFromInputter = defaultInputter.getViewerHTML(parameterContext.getVariable().getName(), fieldDescriptor, existingValue, inputterOptions); }else{ htmlFromInputter = defaultInputter.getInputterHTML(parameterContext.getVariable().getName(), fieldDescriptor, existingValue, inputterOptions); } %> <%=htmlFromInputter%> <% } %> </td></tr> <% } %> </table> <input type=hidden value='<%=request.getParameter("trouble_class") %>' name=trouble_class> <input type=hidden value='<%=request.getParameter("trouble_desc") %>' name=trouble_desc> <input type=submit value="Complete"> </form>5.4.3 Reference codes of consistent ways to Input data #1 – DateInput.java
The following example is the source codes of DataInput. (by using inputter.*, you can see a various examples.)
package org.metaworks.inputter; import java.awt.Component; import org.metaworks.FieldDescriptor; import org.metaworks.ui.*; import org.metaworks.web.HTML; import java.util.Calendar; import java.util.Date; import java.util.Map; import java.text.*; public class DateInput extends InputterAdapter{ public DateInput(){ super(); } /////////// implemetations ////////////// public Object getValue(){ Date srcDate = ((DateButton)getComponent()).getDate(); if(srcDate==null) return null; /* Date rtnDate = new Date(srcDate.getTime()){ public String toString(){ SimpleDateFormat displayFormatter = new SimpleDateFormat("yyyy-MM-dd"); String making = displayFormatter.format(this); return making; } }; return rtnDate;*/ return srcDate; } public void setValue(Object obj){ if(obj instanceof Date && obj!=null) ((DateButton)getComponent()).setDate((Date)obj); } public Component getNewComponent(){ DateButton dateButton = new DateButton(); //dateButton.setDisplayFormat("yyyy-MM-dd"); return dateButton; } public String getViewerHTML(String section, FieldDescriptor fd, Object defaultValue, Map options) { if(defaultValue!=null){ Calendar value; if(defaultValue instanceof Date){ value = Calendar.getInstance(); value.setTime((Date)defaultValue); }else value = (Calendar)defaultValue; // SimpleDateFormat displayFormatter = new SimpleDateFormat("dd-MM-yyyy"); // String making = displayFormatter.format(value.getTime()); // return value.getTime().toString(); //return ""+value; } return "-"; } public String getInputterHTML(String section, FieldDescriptor fd, Object defaultValue, Map options){ int date = 0, month =0, year=0; if(defaultValue == null) defaultValue = Calendar.getInstance(); if(defaultValue!=null && defaultValue instanceof Calendar){ Calendar cal = (Calendar)defaultValue; date = cal.get(Calendar.DATE); month = cal.get(Calendar.MONTH); year = cal.get(Calendar.YEAR); } StringBuffer html = new StringBuffer(); //day html.append("<select"); html.append(HTML.getAttrHTML("name", "_" + section + "_" + fd.getName() + "_day")); html.append(">"); for(int i=0; i<30; i++){ if(defaultValue!=null && i==date) html.append("<option value=" + i + " selected>" + (i+1)); else html.append("<option value=" + i + ">" + (i+1)); } html.append("</select> - "); //month html.append("<select"); html.append(HTML.getAttrHTML("name", "_" + section + "_" + fd.getName() + "_month")); html.append(">"); String [] monthNames = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; for(int i=0; i<11; i++){ if(defaultValue!=null && i==month) html.append("<option value=" + i + " selected>" + monthNames[i]); else html.append("<option value=" + i + ">" + monthNames[i]); } html.append("</select> - "); //year html.append("<input"); html.append(HTML.getAttrHTML("name", "_" + section + "_" + fd.getName() + "_year")); if(defaultValue!=null) html.append(" value=" + year); html.append(" size=5>"); return html.toString(); } public Object createValueFromHTTPRequest(Map parameterValues, String section, String fieldName, Object oldValue){ try{ String strDay = ((String[])parameterValues.get("_" + section + "_" + fieldName + "_day"))[0]; String strMonth = ((String[])parameterValues.get("_" + section + "_" + fieldName + "_month"))[0]; String strYear = ((String[])parameterValues.get("_" + section + "_" + fieldName + "_year"))[0]; Calendar cal = Calendar.getInstance(); cal.set(Calendar.DATE, Integer.parseInt(strDay)); cal.set(Calendar.MONTH, Integer.parseInt(strMonth)); cal.set(Calendar.YEAR, Integer.parseInt(strYear)); return cal; }catch(Exception e){ return null; } } }5.5.3 Role Object Extension Example #1 - organizationChartXML.jsp
<?xml version="1.0" encoding="UTF-8"?> <% response.setContentType("text/xml; charset=UTF-8"); response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 response.setHeader("Pragma","no-cache"); //HTTP 1.0 response.setDateHeader ("Expires", 0); //prevents caching at the proxy server %><%@page pageEncoding="KSC5601" import="javax.naming.Context, javax.naming.InitialContext, javax.naming.NamingException, javax.rmi.PortableRemoteObject, org.uengine.kernel.*, org.uengine.util.dao.DefaultConnectionFactory, java.util.*, java.sql.*, javax.sql.*, java.io.*, org.uengine.processmanager.*" %> <resources> <% Connection conn; conn = DefaultConnectionFactory.create().getConnection(); Statement stmt = conn.createStatement(); try { //Get necessary user information that database needs. StringBuffer sql = new StringBuffer(); sql.append(" select E.EMPCODE, "); sql.append(" E.EMPNAME, "); sql.append(" E.PARTCODE, "); sql.append(" E.EMAIL, "); sql.append(" E.GLobalCom, "); sql.append(" P.PARTNAME "); sql.append(" from PArtTable P, "); sql.append(" EMPTABLE E "); sql.append(" where P.PARTCODE = E.PARTCODE "); sql.append(" and P.GlobalCom = E.GLobalCom "); sql.append(" order by P.PARTCODE,E.EMPNAME "); ResultSet rs = stmt.executeQuery(sql.toString()); String curDivCode = ""; String curPartCode = ""; //Construct XML elements while (rs.next()) { %><resource value="<%=rs.getString("EMPCODE")%>" name="<%= rs.getString("EMPNAME") %>"/><% } } finally { if ( stmt != null ) try { stmt.close(); } catch (Exception e) {} if ( conn != null ) try { conn.close(); } catch (Exception e) {} } %></resources>5.5.3 Role Object Extension Example #2 – Multiple Role Mapping Example
The following submit.jsp shows the second stage, ‘setTheRightPerson’ of troubleticket workitem handler which is responsible for rolemapping.
<%@include file="../../wihDefaultTemplate/header.jsp"%> <%@page import="javax.transaction.*"%> <jsp:useBean id="processManagerFactory" scope="application" class="org.uengine.processmanager.ProcessManagerFactoryBean" /> <% ProcessManagerRemote pm = processManagerFactory.getProcessManager(); String definitionId = request.getParameter("processDefinition"); String instanceId = request.getParameter("instanceId"); String tracingTag = request.getParameter("tracingTag"); String taskId = request.getParameter("taskId"); String troubleClass = request.getParameter("trouble_class"); String troubleDesc = request.getParameter("trouble_desc"); String rightPerson = request.getParameter("_rightPerson_rightPerson"); InitialContext context = new InitialContext(); UserTransaction tx = (GlobalContext.useManagedTransaction ? (UserTransaction)context.lookup(GlobalContext.USERTRANSACTION_JNDI_NAME) : null); try{ if(tx!=null) tx.begin(); instanceId = pm.initialize(definitionId, instanceId, loggedRoleMapping); pm.setProcessVariable(instanceId, "", "trouble_class", troubleClass); pm.setProcessVariable(instanceId, "", "trouble_desc", troubleDesc); '''pm.putRoleMapping(instanceId, "rightPerson", rightPerson); // rightPerson Role Mapping''' pm.completeWorkitem(instanceId, tracingTag, taskId, null); pm.applyChanges(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.commit(); %> <h1><font color=green> Workitem has been successfully completed <% }catch(Exception e){ e.printStackTrace(); if(tx!=null && tx.getStatus() != Status.STATUS_NO_TRANSACTION ) tx.rollback(); throw e; }finally{ try{ pm.remove(); }catch(Exception e){} } %>In troubleTicket process scenario, the second step is selecting people in charge for the role by manager. At here, we assign more than 1 person for the role. Especially, let us make changes on the source codes in bold face above with the way in bold face shown below.
RoleMapping rm = RoleMapping.create(); rm.setName(“'''rightPerson'''”); String ids = {“JB”,”JJY”}; for(int i=0; i< ids.length;i++ ){ rm.setEndpoint(ids[i]); rm.fill(instance); // Retrieve corresponding user (id) information id). '''rm.moveToAdd();''' //Move role mapping cursor to the next. } pm.putRoleMapping(instanceId, rm);There are 2 APIs that conduct role mapping
//The API that assigns one person to corresponding roleName's role
putRoleMapping(String instanceId, String roleName, String endpoint);
//The API that creates a Role Mapping class and conducts role mapping.putRoleMapping(String instanceid, RoleMapping rm);
When we create a Role Mapping class, we must keep the same name as role mapping has. Fill() method is responsible for filling user information from the organization chart. When we need other information besides id, database connection is required, so it is better being invoked when it is necessary because of database performance. moveToAdd() method is simply explained that it conducts when moving the cursor for role mapping. Therefore, it is useful for multiple role mapping. Without moveToAdd() method invocation, only the last user gets mapped. Basically, multiple role mapping becomes a competition. A competition means that a task is assigned to multiple associates, however, the task is accepted by the only one person and completes the task.





































