Function enhancement method based on activiti workflow engine

By enhancing the listening and command mechanisms of the Activiti workflow engine, a pluggable form building factory is constructed to handle BPMN flowcharts, thereby achieving flexibility and controllability of the process. This solves the problems of complexity and high maintenance costs in process control, form function expansion, and multi-instance task control of the Activiti workflow engine, and provides real-time support for future path prediction and countersigning judgment.

CN121680801APending Publication Date: 2026-03-17LONGYING ZHIDA (BEIJING) TECH CO LTD
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202511760192.0
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2025-11-27
Publication Date
2026-03-17

AI Technical Summary

Technical Problem

The Activiti workflow engine suffers from poor flexibility, high complexity, high maintenance costs, high front-end and back-end coupling, and difficulty in understanding and maintaining in terms of process control flexibility, process form function extensibility, business personnel process visualization and prediction, and fine-grained control of multi-instance tasks.

Method used

By inheriting the DefaultActivityBehaviorFactoryMappingConfigurer class, we enhance global monitoring of Activiti, rewrite Activiti's core command mechanism, and implement arbitrary process rollback and jump functionality; we build a pluggable form builder factory mechanism to dynamically parse form fields; we process BPMN flowcharts through algorithms, transform them into linked list views, and provide future path predictions; and we add real-time statistics on the number of approvals and rejections for countersigning nodes.

Benefits of technology

It achieves flexibility and controllability of the process, improves the understanding and maintainability of the process, reduces development and maintenance costs, provides real-time support for future path prediction and countersigning judgment, and enhances the decision-making ability of business personnel.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN121680801A_ABST
    Figure CN121680801A_ABST
Patent Text Reader

Abstract

The invention discloses a function enhancement method based on an activiti workflow engine, and the function enhancement method comprises the following steps: inheriting a DeFaultActivityBehaviorFactoryMappingConfiguer class, and carrying out the monitoring enhancement on the overall situation of the activiti; a core command mechanism of the Activiti is rewritten, so that the functions of randomly returning and randomly skipping the process which is not supported by the original are realized; a set of pluggable form construction factory mechanism is constructed; through an algorithm and data processing, a complex BPMN flow chart is converted into a linked list view which is easy to understand by business personnel, and future path prediction is provided; by customizing a multi-instance behavior of Activiti, real-time statistics of a passing number and a rejection number is added for a countersigning node, and countersigning judgment logic is realized. A future approval path prediction function based on an approval history linked list view and a recursive algorithm is realized, and understanding and decision support of business personnel on a process are remarkably improved.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of workflow engines and external business systems, and in particular to a method for enhancing functionality based on the Activiti workflow engine. Background Technology

[0002] 1. Integration of processes and business systems (dynamic resolution of candidate groups, injection of process variables)

[0003] Activiti's native implementation: Activiti supports assigning tasks to fixed users, user groups, or dynamically specifying them through process variables. For user groups, static user group IDs typically need to be predefined or entered via a form when the process starts. Process variables also need to be manually injected or explicitly injected via a startup form when the process is created.

[0004] Existing solutions:

[0005] Hard-coded or static configuration: Developers often hard-code candidate group IDs in the BPMN model or read them from a fixed configuration through a simple service task.

[0006] Custom Service Task: By writing Java delegates as service tasks, external interfaces can be called at process nodes to query dynamic candidate groups or inject complex business variables.

[0007] 2. Flexibility in process control (arbitrary rollback, arbitrary jump)

[0008] Activiti's native implementation: Activiti processes primarily flow according to the sequence defined by the BPMN 2.0 standard, supporting process control through mechanisms such as conditional branches, sub-processes, and multiple instances. For rollback operations, they are typically simulated by designing rollback lines in the BPMN model or using local sub-processes.

[0009] Existing solutions:

[0010] Complex BPMN modeling: Developers attempt to simulate fallback logic by designing a large number of conditional branches and gateways in the BPMN model, and even create multiple paths to simulate jumps.

[0011] Activiti API forcibly modifies process state: Some advanced developers may directly call Activiti's RuntimeService or HistoryService API to attempt to modify the execution path or history of a process instance.

[0012] 3. Expandability of process form functionality

[0013] Activiti native implementation: Activiti provides the activiti:formProperty mechanism for defining simple form fields, or for integrating with external UIs through embedded forms and external forms.

[0014] Existing solutions:

[0015] Custom UI and data transfer: Developers typically use independent front-end frameworks (such as Vue and React) to build complex form UIs and submit form data to the workflow engine via API.

[0016] Hard-coded form logic: Write Java code in the Service Task to handle the complex logic of the form.

[0017] 4. Visualization and prediction of business personnel processes

[0018] Activiti's native implementation: Activiti provides flowchart (BPMN diagram) rendering capabilities to display the current state of a process. However, this diagram is geared towards technical personnel and includes all BPMN elements.

[0019] Existing solutions and their drawbacks:

[0020] Custom flowchart rendering: Developers typically develop their own customized flowchart rendering components or reports based on historical data and process definitions provided by Activiti.

[0021] Manual tracking and speculation: Business personnel need to manually review historical records and speculate on future trends based on flowcharts and experience.

[0022] 5. Fine-grained control of multi-instance tasks (countersigning)

[0023] Activiti's native implementation: Activiti's multi-instance task provides `completionCondition` to determine the completion condition of multiple instances. This can be determined using built-in variables such as `nrOfInstances` (total number of instances), `nrOfCompletedInstances` (number of completed instances), and `nrOfActiveInstances` (number of active instances). For example, `nrOfCompletedInstances == nrOfInstances` means that all instances have completed.

[0024] Existing solutions:

[0025] Complex completion condition expressions: Developers write complex JUEL expressions in `completionCondition`, combining them with process variables to simulate pass / reject counts. For example, after each countersigning task is completed, a custom "pass count" or "reject count" process variable is updated via `TaskListener`, and then these variables are checked in `completionCondition`.

[0026] Existing solutions and their drawbacks:

[0027] Hard-coded or statically configured processes require modification and redeployment when organizational structure or departmental relationships change, resulting in high maintenance costs.

[0028] Disadvantages of using custom Service Tasks: This approach increases the complexity of the BPMN model, distributing business logic across Java code and reducing the visibility and understandability of the process. Every requirement change necessitates modifying the Java code, recompiling, and deploying, resulting in poor flexibility. The limited ability to inject default variables at process startup causes subsequent process branch decisions and organizational structure queries to rely on additional Service Tasks, increasing the number of execution paths.

[0029] 2. Flexibility in process control (arbitrary rollback, arbitrary jump)

[0030] Activiti's native implementation: It cannot "revert" to a non-direct upstream node, nor can it "jump" to any node in the process.

[0031] The drawbacks of complex BPMN modeling include: the resulting flowcharts are exceptionally complex, difficult to understand and maintain; the cost of model reconstruction is extremely high; and it cannot handle dynamic requirements such as arbitrary backtracking / jumping.

[0032] The disadvantages of ActivitiAPI forcibly modifying process state: This approach is extremely risky, easily leading to inconsistent process instance data, chaotic historical records, and even damaging the internal state of the process engine, potentially causing unpredictable consequences. Furthermore, ActivitiAPI does not directly provide a safe interface for arbitrary jumps / returns, often requiring developers to manually determine and handle complex process contexts.

[0033] 3. Expandability of process form functionality

[0034] Activiti's native implementation has limited support for form field types, rendering methods, and dynamism. For example, options for enum type fields are typically statically configured. Regarding expression parsing, Activiti primarily supports a few specific locations in the process definition (such as conditional expressions), but offers less support for default values ​​in form fields.

[0035] Disadvantages of custom UI and data transfer: This approach separates form logic from the workflow engine, increasing the complexity of front-end and back-end data synchronization. Dynamic form rendering, business validation of fields, and real-time interaction with process variables all require extensive manual coding. When the form structure or logic changes, both the front-end and back-end need to be modified synchronously, resulting in high maintenance costs.

[0036] Disadvantages of hard-coded form logic: It reduces the transparency of the process, couples UI-related logic to the backend, and is not conducive to the separation of responsibilities between the frontend and backend.

[0037] 4. Visualization and prediction of business personnel processes

[0038] Activiti's native implementation: For multi-instance tasks, it displays them as a single task with a cycle flag, rather than a merged "large node". Activiti natively only supports querying the immediate next node of the current node and does not provide full "future approval path" prediction functionality.

[0039] Disadvantages of custom flowchart rendering: It requires a lot of front-end development work, is difficult to handle complex BPMN elements (such as multiple instance sub-processes), and cannot provide a view of "merging major nodes through multi-signature".

[0040] The drawbacks of manual tracing and prediction are: inefficiency, error-proneness, and lack of forward-looking support. For processes with conditional branches, manually predicting future paths is virtually impossible.

[0041] 5. Fine-grained control of multi-instance tasks (countersigning)

[0042] The drawbacks of complex completion condition expressions: This approach results in verbose and difficult-to-maintain completionCondition expressions. Manually managing the counter variable in TaskListener increases code coupling and is prone to inaccurate counting due to logical errors. Furthermore, this decentralized implementation is not conducive to unified management and reusability of countersigning logic. Summary of the Invention

[0043] In view of the above problems, the present invention is proposed to provide a method for enhancing the functionality of the Activiti workflow engine to overcome or at least partially solve the above problems.

[0044] According to one aspect of the present invention, a method for enhancing functionality based on the Activiti workflow engine is provided, the method comprising:

[0045] Inherit from the DefaultActivityBehaviorFactoryMappingConfigurer class to enhance global monitoring of Activity;

[0046] The core command mechanism of Activiti was rewritten, enabling arbitrary process rollback and arbitrary jump functionality that is not natively supported;

[0047] Build a pluggable form builder mechanism;

[0048] Through algorithms and data processing, complex BPMN flowcharts are transformed into linked list views that are easy for business personnel to understand, and future path predictions are provided.

[0049] By customizing the multi-instance behavior of Activiti, real-time statistics of the number of approved and rejected entries were added to the countersigning nodes, thus realizing the countersigning judgment logic.

[0050] Optionally, the enhancement of global monitoring of the activity by inheriting the DefaultActivityBehaviorFactoryMappingConfigurer class specifically includes:

[0051] Arbitrary rollback function technical solution: Delete the current task and its related execution path, then move the process execution pointer to the target rollback node, and recreate the task of that node;

[0052] Arbitrary jump function technical solution: end the current task and its associated execution, then create a new execution path and directly enter the target jump node.

[0053] Optionally, the rewriting of Activiti's core command mechanism, which implements the natively unsupported functions of arbitrary process rollback and arbitrary jump, specifically includes:

[0054] Form Builder Factory Mechanism: Define an abstract factory: Create a FormBuilderFactory interface or abstract class, and define renderForm(FormType type, String formId, Map...)<String,Object> context) and parseForm(FormType type,String formId,Map<String,Object> formData,Map<String,Object> Two core abstract methods (context);

[0055] Form type definition: Define the FormType enumeration or constant to distinguish the business logic of different forms;

[0056] Approval Opinion Fields and Linked Return Technology Solution: ApprovalOpinionFormBuilder Implementation: Rendering: When the renderForm method is called and formType is APPROVAL_OPINION, ApprovalOpinionFormBuilder constructs a JSON object containing field types and default option values;

[0057] Based on the current process instance ID and task ID, call Activiti's HistoryService or RepositoryService to obtain a list of valid historical nodes that can be rolled back to the current task node, and add the list as additional data to the returned JSON for the front end to render as optional rollback targets;

[0058] Technical solution for dynamically selecting the next approver: Enhanced EnumFormBuilder:

[0059] Dynamic expression configuration: When configuring form fields in the process definition, set their type to enum, but their default value is no longer a static value, but a custom expression;

[0060] Rendering: EnumFormBuilder recognizes custom expressions when rendering the form;

[0061] Analysis: After the front-end selects the approver and submits the form, EnumFormBuilder saves the selected approver ID as a process variable when parsing the form. The Activiti engine uses this variable when assigning tasks in the future.

[0062] Countersigning / Multiple selection support: For countersigning or multiple approvals, metadata of the multiple selection component can be returned in renderForm by creating different EnumFormBuilder implementation classes, and multiple approval IDs can be saved to the process variable collection in parseForm;

[0063] EL Expression Parsing Extension Solution: Unified EL Expression Parser: Introducing a unified EL expression parser;

[0064] Extensible CustomType form technology solution: Custom CustomTypeFormBuilder: Create a FileFormBuilder class, implement the FormBuilderFactory interface, and register it as a FILE type. Rendering: When renderingForm, FileFormBuilder constructs a JSON object, instructing the front end to render a file upload component.

[0065] Optionally, the mechanism for constructing a pluggable form construction factory specifically includes:

[0066] Form Builder Factory Mechanism: Define an abstract factory: Create a FormBuilderFactory interface or abstract class, and define two core abstract methods, renderForm and parseForm;

[0067] Approval Opinion Field and Linked Return Technology Solution: Implementation using ApprovalOpinionFormBuilder: Rendering:

[0068] When the renderForm method is called and formType is APPROVAL_OPINION, ApprovalOpinionFormBuilder constructs a JSON object containing field types and default option values;

[0069] Dynamically select the next approver: EnumFormBuilder enhancement: Dynamic expression configuration: When configuring form fields in the process definition, set their type to enum, but their default value is no longer a static value, but a custom expression;

[0070] EL Expression Parsing Extension Solution: Unified EL Expression Parser: Introducing a unified EL expression parser;

[0071] Form field attribute parsing: In the renderForm and parseForm methods of FormBuilderFactory, the EL expressions contained in the configuration items such as default values, validation rules, and dynamic attributes of form fields are parsed;

[0072] Context provided: When the parser is executed, it can access current process variables, task variables, system environment variables, and registered SpringBeans as the context of the expression;

[0073] Extensible CustomType form technology solution: Custom CustomTypeFormBuilder: Create a FileFormBuilder class, implement the FormBuilderFactory interface, and register it as the FILE type;

[0074] Optionally, the process of transforming the complex BPMN flowchart into a linked list view that is easy for business personnel to understand through algorithms and data processing, and providing future path prediction, specifically includes:

[0075] Historical list display optimization: Query historical data: Query all HistoricTaskInstance and HistoricActivityInstance of a specified process instance through Activiti's HistoryService.

[0076] Construct a preliminary linked list: Sort these historical instances according to the endTime field to construct a preliminary historical linked list arranged in chronological order;

[0077] Countersigning node identification: Traverse the initial linked list to identify the start and end activities of multi-instance tasks or multi-instance sub-processes;

[0078] Future linked list prediction technology: recursively simulates the branching of the process, combines process variables and rule judgments to predict a possible path from the current node to the end node, and handles the case of cycles.

[0079] Get the current process status:

[0080] Get all process variables of the current process instance through RuntimeService;

[0081] Obtain all outgoing connections of the currently active node through RepositoryService;

[0082] The recursive prediction function predictNextPath:

[0083] When entering the predictNextPath function, currentActivity.getId() is added to the visitedPath queue;

[0084] Before selecting the next node, check if there is a duplicate element in visitedPath that is accessed using currentActivity.getId().

[0085] If duplicates exist, it is considered a cycle; remove the subsequence from the first duplicate element to the current element from the queue to ensure that visitedPath is always an acyclic sequence;

[0086] Introducing pathOffset: When currentActivity has multiple outgoing flows and there are still multiple valid paths after the loop formation judgment, pathOffset can be used to select different branches to try to predict different future paths;

[0087] Get outgoing transitions and simulated judgment: Get all outgoing transitions of currentActivity.

[0088] Optionally, by customizing the multi-instance behavior of Activiti, real-time statistics of the number of approved and rejected entries are added to the co-signing nodes, and the co-signing judgment logic specifically includes:

[0089] Custom ActivityBehaviorFactory replacement solution:

[0090] Custom ActivityBehaviorFactory: Create a Custom ActivityBehaviorFactory class that inherits from Activiti's Default ActivityBehaviorFactory;

[0091] Override the `createActivityBehavior` method: When it detects that an activity object has a multi-instance cycle characteristic, instead of returning the default multi-instance behavior of ActivityBehavior, return a custom one.

[0092] CustomParallelMultiInstanceBehavior instance;

[0093] Configuration injection: In Activiti's processEngineConfiguration, replace the default ActivityBehaviorFactory with CustomActivityBehaviorFactory;

[0094] Custom MultiInstanceBehavior implementation solution:

[0095] Customize the CustomParallelMultiInstanceBehavior class:

[0096] Create a class called CustomParallelMultiInstanceBehavior, which inherits from Activiti.

[0097] ParallelMultiInstanceBehavior;

[0098] Override the createInstances method: When called, obtain the process variables of the current process instance through RuntimeService;

[0099] Initialize two new process variables: approvedCount and rejectedCount, and set their values ​​to 0. These variables should be stored in the execution scope consistent with the multi-instance task scope.

[0100] Override the leave method:

[0101] When a method is invoked, the process variables of the current child instance execution are obtained through RuntimeService;

[0102] Read the preset "approval comments" process variables;

[0103] Based on the value of approvalResult, atomically increment the approvedCount or rejectedCount process variable;

[0104] Modify BPMN completion conditions: In the BPMN process definition, the completionCondition of the countersigning task is judged in combination with approvedCount and rejectedCount.

[0105] This invention provides a method for enhancing the functionality of the Activiti workflow engine. The enhancement method includes: inheriting the `DefaultActivityBehaviorFactoryMappingConfigurer` class to enhance global monitoring of Activiti; rewriting Activiti's core command mechanism to implement functions such as arbitrary process rollback and arbitrary jump, which are not natively supported; constructing a pluggable form building factory mechanism; transforming complex BPMN flowcharts into a linked list view easily understood by business personnel through algorithms and data processing, and providing future path prediction; and customizing Activiti's multi-instance behavior to add real-time statistics of the number of approvals and rejections for the co-signing nodes, implementing co-signing judgment logic. It implements an approval history linked list view and a future approval path prediction function based on a recursive algorithm, significantly improving business personnel's understanding of the process and decision support.

[0106] The above description is merely an overview of the technical solution of the present invention. In order to better understand the technical means of the present invention and to implement it in accordance with the contents of the specification, and in order to make the above and other objects, features and advantages of the present invention more apparent and understandable, specific embodiments of the present invention are described below. Attached Figure Description

[0107] To more clearly illustrate the technical solutions of the embodiments of the present invention, the drawings used in the following description of the embodiments will be briefly introduced. Obviously, the drawings described below are only some embodiments of the present invention. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.

[0108] Figure 1 A flowchart illustrating a method for enhancing functionality based on the Activiti workflow engine, as provided in an embodiment of the present invention. Detailed Implementation

[0109] Exemplary embodiments of the present disclosure will now be described in more detail with reference to the accompanying drawings. While exemplary embodiments of the present disclosure are shown in the drawings, it should be understood that the present disclosure may be implemented in various forms and should not be limited to the embodiments set forth herein. Rather, these embodiments are provided so that this disclosure will be thorough and complete, and will fully convey the scope of the disclosure to those skilled in the art.

[0110] The terms "comprising" and "having," and any variations thereof, in the specification, embodiments, claims, and drawings of this invention are intended to cover non-exclusive inclusion, such as including a series of steps or units.

[0111] The technical solution of the present invention will be further described in detail below with reference to the accompanying drawings and embodiments.

[0112] like Figure 1 As shown, a method for enhancing the functionality of the Activiti workflow engine includes: inheriting the DefaultActivityBehaviorFactoryMappingConfigurer class to enhance global monitoring of Activiti; rewriting the core command mechanism of Activiti to implement the natively unsupported functions of arbitrary process rollback and arbitrary jump; building a pluggable form building factory mechanism; transforming complex BPMN flowcharts into linked list views that are easy for business personnel to understand through algorithms and data processing, and providing future path prediction; and adding real-time statistics of the number of approvals and rejections for the signing nodes by customizing the multi-instance behavior of Activiti, thus realizing the signing judgment logic.

[0113] Detailed steps include:

[0114] 1. First, by inheriting the `DefaultActivityBehaviorFactoryMappingConfigurer` class, global monitoring enhancements were implemented for Activiti. These include: 1. When a candidate group is entered, a custom expression is parsed to dynamically resolve the entered candidate group, allowing for integration with the system's organizational and departmental management system; 2. Monitoring process creation events, filling in default process variables (initiator, initiating organization, organizational level, etc., expandable) upon each process creation to facilitate branching in subsequent approval processes and finding superiors and subordinates based on the initiating organization; 3. Monitoring the start of task nodes or the end of processes, and sending notification messages to the corresponding assignees via the messaging system; 4. Monitoring task node creation events, determining if the current node handler is in a sub-authorization state, and if so, automatically transferring the task to a proxy if the handler cannot receive the task.

[0115] 2. Technical solution for arbitrary process rollback and redirection

[0116] This invention rewrites Activiti's core command mechanism to enable arbitrary process rollback and jump, which are not natively supported, while ensuring minimal impact on process status and history.

[0117] 2.1 Technical solution for arbitrary rollback function:

[0118] The core idea is to delete the current task and its associated execution path, then move the execution pointer to the target rollback node and recreate the task at that node.

[0119] Implementation steps:

[0120] Custom delete command class: Create a CustomDeleteTaskAndActivityCommand class that inherits from Activiti's NeedActiveTaskCmd. <void>Or implement Command <void>interface.

[0121] Obtain the process context: In the execute() method, obtain the current task ID, process instance ID, and target back node ID through CommandContext.

[0122] Delete current task and history:

[0123] Obtain the TaskEntityManager through CommandContext, and find and delete the TaskEntity based on the current task ID.

[0124] Based on the current activity's Execution flow and its corresponding ActivityInstance, delete the related HistoricTaskInstance and HistoricActivityInstance to ensure the clarity of the history.

[0125] Move execution pointer:

[0126] Get the ExecutionEntity of the current activity.

[0127] Obtain the ProcessDefinitionEntity through CommandContext and find the ActivityImpl corresponding to the target fallback node.

[0128] Set the current activity (currentActivity or activityId) of the ExecutionEntity to the target back node.

[0129] You may need to clean up the event source using ExecutionEntity's setEventSource(null) and setEventName(null).

[0130] Process variable handling: Depending on business needs, it may be necessary to roll back or adjust certain process variables.

[0131] Start the target node: call

[0132] The `ExecutionEntity.performOperation(org.activiti.engine.impl.pvm.runtime.Atomic Operation.ACTIVITY_START)` (or a similar operation) is used to activate the target fallback node, causing it to recreate the task and enter the execution state.

[0133] Risk control: During implementation, special attention needs to be paid to issues such as concurrent operations, data consistency, and historical record integrity to ensure that deletion and relocation operations are atomic.

[0134] Technical advantages: It enables flexible process rollback, allowing users to roll back tasks to any legal node in the process, greatly enhancing the process's error correction capabilities and user experience, while minimizing the impact on actual process data and historical records.

[0135] 2.2 Technical solution for arbitrary jump function:

[0136] The core idea is to terminate the current task and its associated execution, then create a new execution path and directly enter the target jump node.

[0137] Implementation steps:

[0138] Custom Jump Command Class: Create a CustomJumpActivityCommand class that inherits from Activiti's Command class. <void>interface.

[0139] Obtain the process context: In the execute() method, obtain the current task ID, process instance ID, and target jump node ID.

[0140] End current task:

[0141] Obtain the TaskEntityManager through CommandContext, and find and delete the TaskEntity based on the current task ID.

[0142] Get the ExecutionEntity associated with the current task and terminate its current active instance.

[0143] Find the incoming transitions of the target node:

[0144] Obtain the ProcessDefinitionEntity through CommandContext and find all in-degree connections (incomingTransitions) of the target node (ActivityImpl).

[0145] Choose a suitable in-degree connection as the entry point for the "simulation". Typically, this selection needs to be combined with business logic or user specifications.

[0146] Create or reuse execution paths:

[0147] Get the root ExecutionEntity of the current process instance.

[0148] If needed, a new ExecutionEntity can be created as a sub-execution flow.

[0149] Set the current activity of the ExecutionEntity as the target jump node.

[0150] Set the transition of the ExecutionEntity to the source connection selected in step 4, and the simulation process will enter the target node from this connection.

[0151] Activate target node: call

[0152] The `ExecutionEntity.performOperation(org.activiti.engine.impl.pvm.runtime.Atomic Operation.ACTIVITY_START_BEHAVIOR)` or similar methods cause the process to start execution from the target node, thereby creating a new task.

[0153] Process variable handling: Ensure that process variables are correctly passed before and after jumps, or adjust them as needed.

[0154] Technical advantages: It provides flexible process jump capabilities, allowing the process to jump directly from the current position to a specified target node, which is suitable for scenarios such as process adjustment and emergency intervention, and improves the adaptability and controllability of the process.

[0155] 3. Technical Solution for Enhancing Workflow Form Functionality

[0156] This invention greatly enhances the scalability, dynamism, and display capabilities of Activiti process forms by constructing a pluggable form building factory mechanism.

[0157] 3.1 Form Builder Mechanism:

[0158] Define an abstract factory: Create a FormBuilderFactory interface or abstract class, and define renderForm(FormType type, String formId, Map...).<String,Object> context) and parseForm(FormTypetype, String formId, Map<String,Object> formData,Map<String,Object> The two core abstract methods are context and context.

[0159] Form type definition: Define the FormType enumeration or constant, such as APPROVAL_OPINION, ENUM, FILE, CUSTOM_EXPRESSION, etc., to distinguish the business logic of different forms.

[0160] Specific implementation classes: For each FormType, create specific implementation classes, such as ApprovalOpinionFormBuilder, EnumFormBuilder, FileFormBuilder, etc., and register them in FormBuilderFactory.

[0161] 3.2 "Approval Comments" field and linked return technical solution:

[0162] Implementation using ApprovalOpinionFormBuilder:

[0163] Rendering (renderForm):

[0164] When the renderForm method is called and formType is APPROVAL_OPINION, ApprovalOpinionFormBuilder constructs a JSON object containing field types (such as dropdown) and default option values ​​(such as "Agree", "Disagree", "Return").

[0165] To support linked rollbacks, this method also calls Activiti's HistoryService or RepositoryService based on the current process instance ID and task ID to obtain a list of valid historical nodes that can be rolled back to the current task node (using the logic of the previously implemented arbitrary rollback function), and adds this list as additional data (such as backNodes) to the returned JSON for the front end to render as optional rollback targets.

[0166] Parse (parseForm):

[0167] When the parseForm method is called, ApprovalOpinionFormBuilder receives the approval comments submitted by the front end and possible return node IDs.

[0168] If the approval opinion is "return", the previously implemented command (CustomDeleteTaskAndActivityCommand) will be invoked to return the process to the node specified on the front end.

[0169] Otherwise, the approval opinion is saved as a process variable (such as approvalResult) in Activiti, and the process is triggered to continue.

[0170] 3.3 Technical solution for dynamically selecting the next approver:

[0171] EnumFormBuilder Enhancements:

[0172] Dynamic expression configuration: When configuring form fields in the process definition, set their type to enum, but their default value is no longer a static value, but a custom expression, such as #{userService.getDynamicApprovers('deptId')} or #{ruleService.getApproversByRole('manager')}.

[0173] Rendering (renderForm): EnumFormBuilder recognizes the custom expression during renderForm. By introducing an EL expression parser (same as Section 1.1), the expression is parsed, and an external business service (such as UserService or RuleService) is called to dynamically retrieve the list of approvers. This list (containing approver IDs and names) will be returned to the front end as an option value of the enum.

[0174] Parsing (parseForm): After the front-end selects the approver and submits the form, EnumFormBuilder saves the selected approver ID as a process variable (such as nextApprover) during the parseForm process. The Activiti engine can then use this variable when assigning tasks in the future.

[0175] Countersigning / Multiple Selection Support: For countersigning or multiple selectors, you can create different EnumFormBuilder implementation classes or return the metadata of the multiple selection component in renderForm, and save multiple approver IDs to the process variable collection in parseForm to support the collection property of multi-instance tasks.

[0176] 3.4 EL Expression Parsing Extension Technology Solution:

[0177] Unified EL Expression Parser: Introduce a unified EL expression parser, such as extending Activiti's ActivitiElContextFactory or using StandardExpressionFactory (such as Spring's SpelExpressionParser), and register it with a custom ActivityBehaviorFactory.

[0178] Form field attribute parsing: The `renderForm` and `parseForm` methods of `FormBuilderFactory` parse the EL expressions contained in the configuration items of form field default values, validation rules, dynamic attributes, etc. For example, the field's `defaultValue` can be configured as `#{currentDate()}`.

[0179] Context provided: When the parser is executed, it can access current process variables, task variables, system environment variables, and registered SpringBeans as the context of the expression.

[0180] 3.5 Extensible CustomType Form Technology Solution:

[0181] Customize CustomTypeFormBuilder: Create a FileFormBuilder class, implement the FormBuilderFactory interface, and register it as a FILE type.

[0182] Rendering (renderForm): When FileFormBuilder renders Form, it constructs a JSON object that instructs the front end to render a file upload component. This JSON can contain metadata such as the upload API address and file size limits.

[0183] Parsing (parseForm): After the front-end completes the file upload, it submits the URL or file ID returned by the file server to parseForm. FileFormBuilder saves the file address to a process variable or a business data table associated with the process instance.

[0184] Scalability: By defining a new FormType and the corresponding CustomTypeFormBuilder implementation class, it is easy to extend the form functionality to support more types of custom controls.

[0185] Technical advantages: Activiti forms possess high dynamism, scalability, and deep integration capabilities with business systems, reducing the development cost of complex forms and improving user experience.

[0186] 4. Technical solution for viewing approval diagrams converted to linked lists and predicting future linked lists.

[0187] This invention uses specific algorithms and data processing to transform complex BPMN flowcharts into linked list views that are easy for business personnel to understand, and provides forward-looking predictions of future paths.

[0188] 4.1 Optimized Historical Linked List Display (Viewing Merged Signature Nodes) Technical Solution:

[0189] Implementation steps:

[0190] Query historical data: Use Activiti's HistoryService to query all HistoricTaskInstances and HistoricActivityInstances for a specified process instance.

[0191] Construct a preliminary linked list: Sort these historical instances according to the endTime field to construct a preliminary historical linked list arranged in chronological order.

[0192] Countersignature node identification: Traverse the initial linked list to identify the start and end activities of multi-instance tasks (MultiInstanceActivity) or multi-instance subprocesses (MultiInstanceSubProcess). These activities typically have the loopCharacteristics attribute in the BPMN model.

[0193] Merge Algorithm:

[0194] Merge sub-processes based on execution ID: For HistoricActivityInstances belonging to the same multi-instance sub-process, they are aggregated together by their shared superExecutionId or callActivityInstanceId.

[0195] Merge large nodes based on node ID: For multiple HistoricTaskInstance or HistoricActivityInstance created by the same multi-instance task, group them by their activityId (which points to the multi-instance task itself in the BPMN).

[0196] Create an aggregation node: This records the aggregated multi-instance tasks or sub-processes and displays them as a single "multi-signature node". This node can contain summary information such as the total number of sign-offs and the number of completed sign-offs.

[0197] Render the linked list: Render the optimized historical linked list (including merged large nodes) onto the front-end interface and display it to business users in a concise chain structure.

[0198] Technical advantages: It solves the complexity problem of displaying signing nodes in the native Activiti flowchart, providing business personnel with a clearer and more integrated view of historical approval paths, and improving the readability of the process.

[0199] 4.2 Technical Solution for Future Linked List Prediction Function:

[0200] Core idea: Recursively simulate the branching of the process, combine process variables and rule judgments to predict a possible path from the current node to the end node, and handle the case of loops.

[0201] Implementation steps:

[0202] Get the current process status:

[0203] Get all process variables of the current process instance through RuntimeService.

[0204] Obtain all outgoing transitions of the current active node (ActivityImpl) through RepositoryService.

[0205] The recursive prediction function `predictNextPath(currentActivity, currentProcessVariables, visitedPath, pathOffset)` is as follows:

[0206] parameter:

[0207] currentActivity: The node currently being predicted.

[0208] currentProcessVariables: The set of process variables currently being simulated.

[0209] visitedPath: A queue that records the sequence of visited node IDs, used for cycle detection.

[0210] pathOffset: An integer used to try different paths when a loop is formed, avoiding simple loops.

[0211] Circulation detection algorithm:

[0212] When entering the predictNextPath function, currentActivity.getId() is added to the visitedPath queue.

[0213] Before selecting the next node, check if there is a duplicate element in visitedPath that is currently the same as the one obtained by currentActivity.getId().

[0214] If duplicates exist, the sequence is considered circular. The subsequence from the first duplicate element to the current element is removed from the queue, ensuring that `visitedPath` is always an acyclic sequence. This effectively handles loops caused by "going back to previous nodes".

[0215] Introducing pathOffset processing: When currentActivity has multiple outgoing flows and there are still multiple valid paths after the loop formation judgment, pathOffset can be used to select (e.g., skip the first pathOffset paths) different branches to try to predict different future paths.

[0216] Obtaining outflow lines and simulating judgment:

[0217] Get all outgoing transitions of currentActivity.

[0218] Simulated rule variables: Based on business needs, some simulated process variables can be injected or modified in currentProcessVariables, such as simulating "approval result is agreed" or "all countersignatures agree", to force the process to move to a specific branch.

[0219] Expression Parsing Factory: Creates a custom ExpressionFactory to parse conditional expressions on outgoingTransitions.

[0220] Conditional judgment: Traverse all outgoing lines, use ExpressionFactory to parse the condition expression of each connection, and combine it with currentProcessVariables to determine which connection meets the condition.

[0221] Select the next node: Select the next node (targetActivity) that meets the conditions (or the first one if there are no conditions).

[0222] Termination condition: If targetActivity is the end event of the process (EndEvent), then add targetActivity to the prediction list and return.

[0223] Recursive call: Otherwise, add targetActivity to the prediction list and recursively call predictNextPath with targetActivity as the new currentActivity.

[0224] Build an expression parsing factory: Use Activiti's ActivitiElContextFactory or a custom ExpressionFactory to enable it to parse conditional expressions in BPMN process definitions.

[0225] Final output: Construct the node sequence returned by the recursive function into a clear "future linked list" and display it to business personnel.

[0226] Technical advantages: It provides a much-needed future approval path prediction function for business personnel, helping them understand the process flow in advance and supporting decision-making. Through loop judgment and offset mechanisms, it effectively solves the prediction difficulties caused by complex branches and process loops, improving the accuracy and practicality of predictions.

[0227] 5. Enhanced signing factory and refined signing control technology solutions

[0228] This invention adds real-time statistics on the number of approved and rejected entries to the countersigning node by customizing the multi-instance behavior of Activiti, thus realizing a more refined countersigning judgment logic.

[0229] 5.1 Technical solution for replacing custom ActivityBehaviorFactory:

[0230] Implementation steps:

[0231] Custom ActivityBehaviorFactory: Creation

[0232] The CustomActivityBehaviorFactory class inherits from ActivityBehaviorFactory.

[0233] DefaultActivityBehaviorFactory.

[0234] Override the createActivityBehavior(ActivityImpl activity) method: In this method, when it is detected that the activity object has multi-instance loop characteristics (i.e., activity.getBehavior() is an instance of MultiInstanceActivityBehavior and its loopCharacteristics is not null), instead of returning the default multi-instance behavior of ActivityImpl, a custom CustomParallelMultiInstanceBehavior instance is returned.

[0235] Configuration injection: In Activiti's processEngineConfiguration, replace the default ActivityBehaviorFactory with CustomActivityBehaviorFactory. This ensures that all multi-instance tasks in the deployed BPMN process will create their behavior instances through this custom factory at runtime.

[0236] Technical advantages: It achieves non-intrusive enhancements to the core behavior of Activiti, which only applies to multi-instance tasks and does not affect the behavior of other process nodes, thus ensuring the stability and compatibility of the system.

[0237] 5.2 Custom MultiInstanceBehavior Implementation Solution:

[0238] Implementation steps:

[0239] Customize the CustomParallelMultiInstanceBehavior class: Create

[0240] The CustomParallelMultiInstanceBehavior class inherits from Activiti.

[0241] ParallelMultiInstanceBehavior (or SequentialMultiInstanceBehavior, depending on the signature type).

[0242] Override the createInstances(ActivityExecution execution) method:

[0243] When this method is called (i.e., before the multi-instance task starts initialization and before the child instance is created), the process variables of the current process instance (or execution) are obtained through RuntimeService.

[0244] Initialize two new process variables: approvedCount and rejectedCount, and set their values ​​to 0. These variables should be stored in the execution scope consistent with the multi-instance task scope.

[0245] Example: execution.setVariableLocal("approvedCount",0);

[0246] Override the leave(ActivityExecution execution) method:

[0247] When this method is invoked (i.e., when each sub-instance of the multi-instance task completes and leaves its activity), the process variables of the current sub-instance execution are obtained through RuntimeService.

[0248] Read the preset "approval comments" process variable (for example, after each countersigning task is completed, the task listener will store the approval comment "agree" or "reject" in the execution's approvalResult variable).

[0249] Based on the value of `approvalResult`, atomically increment the process variable `approvedCount` or `rejectedCount`. To ensure concurrency safety, Activiti's...

[0250] execution.setVariableLocal("approvedCount",(Integer)

[0251] You can perform the operation by using `execution.getVariableLocal("approvedCount")+1)` or by obtaining `VariableInstanceEntityManager` through `CommandContext`.

[0252] Modify BPMN completion conditions: In the BPMN process definition, the completionCondition of the countersigning task is no longer limited to native variables such as nrOfCompletedInstances, but can be combined with approvedCount and rejectedCount for more flexible judgment.

[0253] Example: completionCondition = "${approvedCount>=(nrOfInstances*0.7)||rejectedCount>=1}" (meaning 70% approval or at least 1 rejection).

[0254] Technical advantages: It enables fine-grained control over the countersigning logic. By real-time statistics of approved and rejected entries, combined with Activiti's native variables, the completion conditions for countersigning can be highly customized according to business rules, greatly enhancing the adaptability of the workflow engine in complex approval scenarios.

[0255] Beneficial effects:

[0256] 1. Achieves deep integration with business systems, resulting in a high level of process intelligence:

[0257] Advantages: This invention achieves dynamic expression parsing of task candidate groups through a custom Activiti global listener, enabling seamless integration with the enterprise's internal organizational and departmental management system for real-time task acquisition and allocation. Simultaneously, it automatically injects comprehensive process context variables (such as initiator, initiating organization, and organizational level) during process creation, providing rich dynamic data support for subsequent process judgments and business logic.

[0258] Compared with existing technologies, this technology solves the problems of low integration between processes and business systems and high maintenance costs caused by static configuration of candidate groups and manual variable injection in existing technologies, and avoids the inefficient method of data acquisition and injection through complex Service Tasks.

[0259] 2. Highly flexible process control, effectively handling complex business scenarios:

[0260] Advantages: This invention, by rewriting the Activiti core Command class, securely and stably implements the functionality of arbitrary process rollback and arbitrary jump, which is not natively supported. This gives business processes extremely high flexibility, enabling rapid and accurate adjustments to process flow in scenarios such as approval errors, business adjustments, or emergency interventions, avoiding the complexity of process interruptions or manual intervention.

[0261] Compared with existing technologies, it overcomes the limitations of Activiti's native process, which can only flow sequentially and cannot achieve arbitrary backtracking and jumps, and avoids the high risks and high complexity caused by redundant BPMN modeling or forced modification of engine state.

[0262] 3. The workflow forms are powerful and scalable, improving development and user experience:

[0263] Advantages: This invention introduces a form building factory mechanism, supporting dynamic rendering of form fields (such as dynamically selecting the next approver), custom form types (such as file uploads), and complex EL expression parsing in form field default values. These features greatly enhance the scalability and dynamism of workflow forms, enabling more complex interactive functions in front-end rendering. Furthermore, through deep integration with the front-end, it improves development efficiency and user experience.

[0264] Compared with existing technologies, it solves the shortcomings of Activiti's native forms, such as limited functionality, poor dynamism, and insufficient support for custom types. It avoids a lot of additional front-end development and back-end logic coupling, and simplifies the implementation of complex forms.

[0265] 4. The process is visualized, intuitive, and easy to understand, providing decision support:

[0266] Advantages: This invention transforms complex technical BPMN flowcharts into a linked list view that is easy for business personnel to understand, and specifically optimizes the display of historical linked lists, enabling the combined viewing of multiple instance signing nodes. More importantly, this invention provides a future approval path prediction function, using a recursive algorithm (including cycle detection) to show business personnel the complete possible path from the current node to the end, thereby assisting business decision-making and improving process transparency.

[0267] Compared with existing technologies, it overcomes the shortcomings of the native Activiti flowchart, such as being unfriendly to business users, having a complex display of signature nodes, and lacking the ability to predict future paths, and provides more forward-looking and practical visualization functions.

[0268] 5. Refined control over the countersigning logic to adapt to changing approval rules:

[0269] Advantages: This invention replaces Activiti's default multi-instance behavior with a customized co-signing factory, adding real-time statistics on the number of approved and rejected entries to co-signing nodes. This allows for more flexible and intelligent judgment of co-signing completion conditions by combining these refined counts with Activiti's native variables, thereby meeting diverse co-signing approval rules.

[0270] Compared to existing technologies, this approach solves the problem of complex conditional expressions for completing the original Activiti signature process, which makes it difficult to directly count the number of approved / rejected signatures. It also avoids the code coupling and complexity caused by manually managing the counting variables through TaskListener.

[0271] In summary, this invention has comprehensively enhanced and optimized the functionality of the Activiti workflow engine, making it far superior to existing technologies in terms of integration, flexibility, form functionality, visualization, and countersigning control, thus better meeting the automation needs of complex enterprise-level business processes.

[0272] The above specific embodiments further illustrate the purpose, technical solution, and beneficial effects of the present invention. It should be understood that the above are merely specific embodiments of the present invention and are not intended to limit the scope of protection of the present invention. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of the present invention should be included within the scope of protection of the present invention.< / void> < / void> < / void>

Claims

1. A method for enhancing the functionality of an activiti workflow engine, characterized in that, The function enhancement method comprises: Inheritance DefaultActivityBehaviorFactoryMappingConfiguer class, listen to the enhancement of the whole activiti; Rewrite the core command mechanism of Activiti to realize the function of arbitrary return and arbitrary jump of the process which is not supported by the original; Build a set of plug-in form building factory mechanism; Through algorithm and data processing, complex BPMN process diagram is converted into a chain table view which is easy for business personnel to understand, and future path prediction is provided; Through customizing the multi-instance behavior of Activiti, the number of passes and the number of refusals of the signing node are added in real time, and the signing judgment logic is realized.

2. The method for enhancing the function of the activiti workflow engine according to claim 1, characterized in that, The inheritance DefaultActivityBehaviorFactoryMappingConfiguer class, which listens to the enhancement of the whole activiti, specifically comprises: Arbitrary return function technical scheme: delete the current task and its related execution path, then move the process execution pointer to the target return node, and re-create the task of the node; Arbitrary jump function technical scheme: end the current task and its associated execution, then create a new execution path and directly enter the target jump node.

3. The method for enhancing the function of the activiti workflow engine according to claim 1, characterized in that, The rewriting of the core command mechanism of Activiti realizes the function of arbitrary return and arbitrary jump of the process which is not supported by the original, specifically comprising: Form building factory mechanism: define abstract factory: create FormBuilderFactory interface or abstract class, define renderForm(FormType type, String formId, Map<String, Object> context) and parseForm(FormType type, String formId, Map<String, Object> formData, Map<String, Object> context) two core abstract methods; Form type definition: define FormType enumeration or constant, which is used to distinguish the business logic of different forms; Approval opinion field and linkage return technical scheme: ApprovalOpinionFormBuilder implementation: rendering: when the renderForm method is called and the formType is APPROVAL_OPINION, ApprovalOpinionFormBuilder constructs a JSON object, which contains field type, default option value; According to the current process instance ID and task ID, call Activiti's HistoryService or RepositoryService to obtain the legal historical node list that can be returned for the current task node, and add the list as additional data to the returned JSON, which is used for front-end rendering as optional return target; Dynamic next approver selection: EnumFormBuilder enhancement Dynamic expression configuration: When configuring form fields in process definition, set its type as enum, but its default value is no longer static value, but custom expression Render: EnumFormBuilder identifies custom expression in renderForm Parse: After front-end selects approver and submits, EnumFormBuilder saves selected approver ID as a process variable in parseForm, and Activiti engine uses the variable in subsequent task assignment Co-signing / multi-selection support: For co-signing or multi-selection approvers, create different EnumFormBuilder implementation classes or return metadata of multi-selection component in renderForm, and save multiple approver IDs to process variable set in parseForm EL expression parsing extension: Unified EL expression parser: Introduce a unified EL expression parser Extensible Custom Type form: Custom CustomTypeFormBuilder: Create a FileFormBuilder class, implement FormBuilderFactory interface, and register it as FILE type 4. The method for enhancing the function of the activiti workflow engine according to claim 1, characterized in that, Render: FileFormBuilder builds a JSON object in renderForm, instructing front-end to render a file upload component The set of pluggable form builder factory mechanisms specifically includes: Form builder factory mechanism: Define abstract factory: Create FormBuilderFactory interface or abstract class, define renderForm and parseForm two core abstract methods Approval opinion field and linkage return technical solution: ApprovalOpinionFormBuilder implementation: Render: When renderForm method is called and formType is APPROVAL_OPINION, ApprovalOpinionFormBuilder builds a JSON object containing field type, default option value Dynamic selection of next approver: EnumFormBuilder enhancement: Dynamic expression configuration: When configuring form fields in process definition, set its type as enum, but its default value is no longer static value, but custom expression EL expression parsing extension: Unified EL expression parser: Introduce a unified EL expression parser Form field attribute parsing: In FormBuilderFactory's renderForm and parseForm methods, parse EL expressions contained in form field's default value, validation rules, dynamic properties, etc. Context provided: the parser can access the current process variables, task variables, system environment variables, and registered Spring Beans as the context of the expression when it is executed; Extensible Custom Type type form technical scheme: custom CustomTypeFormBuilder: create a FileFormBuilder class, implement the FormBuilderFactory interface, and register it as a FILE type.

5. The method for enhancing the functionality of an activiti workflow engine according to claim 1, wherein, The complex BPMN flowchart is converted into a linked list view that is easy for business personnel to understand, and future path prediction is provided, specifically including: History linked list display optimization: query historical data: query all HistoricTaskInstance and HistoricActivityInstance of the specified process instance through Activiti's HistoryService. Build a preliminary linked list: sort these historical instances according to the endTime field to build a preliminary historical linked list in chronological order; Concurrence node identification: traverse the preliminary linked list to identify the start and end activities of multi-instance tasks or multi-instance sub-processes; Future linked list prediction function technology: recursively simulate the flow branch direction, combine process variables and rule judgment, and predict a possible path from the current node to the end node, while handling loop cases; Get the current process state: Get all process variables of the current process instance through RuntimeService; Get all outgoing connections of the current activity node through RepositoryService; Recursive prediction function predictNextPath: When entering the predictNextPath function, add currentActivity.getId() to the visitedPath queue; Before selecting the next node each time, check if there is a duplicate element of currentActivity.getId() in visitedPath; If there is a duplicate, it is judged to be a loop; remove the subsequence from the first duplicate element to the current element from the queue to ensure that visitedPath is always a loop-free sequence; Introduce pathOffset processing: when currentActivity has multiple outgoing lines and still has multiple legal paths after loop judgment, pathOffset can be used to select different branches to try to predict different future paths; Get outgoing lines and simulation judgment: get all outgoingTransitions of currentActivity.

6. The method for enhancing the functionality of an activiti workflow engine according to claim 1, wherein, The multi-instance behavior of Activiti is customized to add real-time statistics of the number of passes and the number of rejections for concurrence nodes, and the concurrence judgment logic is implemented, specifically including: Custom ActivityBehaviorFactory replacement technical scheme: CustomActivityBehaviorFactory: Create a CustomActivityBehaviorFactory class that extends Activiti's DefaultActivityBehaviorFactory; Override the createActivityBehavior method: When detecting that an activity object has a multi-instance loop characteristic, instead of returning Activiti's default multi-instance behavior, return a custom CustomParallelMultiInstanceBehavior instance; Configuration injection: In Activiti's processEngineConfiguration, replace the default ActivityBehaviorFactory with CustomActivityBehaviorFactory; Custom MultiInstanceBehavior implementation technical solution: CustomParallelMultiInstanceBehavior class: Create a CustomParallelMultiInstanceBehavior class that extends Activiti's ParallelMultiInstanceBehavior; Override the createInstances method: When called, get the process variables of the current process instance through RuntimeService; Initialize two new process variables: approvedCount and rejectedCount, and set their values to 0. The variables should be stored in the execution consistent with the multi-instance task scope; Override the leave method: When the method is called, get the process variables of the current sub-instance execution through RuntimeService; Read the preset "approval opinion" process variable; According to the value of approvalResult, atomically add the approvedCount or rejectedCount process variable; Modify the BPMN completion condition: In the BPMN process definition, the completion condition of the signing task is combined with approvedCount and rejectedCount to determine the completion condition.