-
Notifications
You must be signed in to change notification settings - Fork 38
Getting Started
- 1 Minute Guide
- Components
- Usage Scenarios
- Anatomy of a Workflow
- Interacting with nFlow
- Setting Up Your nFlow
For a super quick 1 minute guide, checkout the frontpage of nFlow repository.
nFlow consist of the following main components:
- nflow-engine contains a multithreaded workflow dispatcher, Java API for managing workflows and the persistance layer implementation.
- nflow-rest-api contains a JAX-RS compliant REST service implementation for exposing workflow management and query APIs.
- nflow-metrics provides integration with the Metrics library.
- nflow-jetty contains an embeddable Jetty server for running nFlow with your custom workflows.
In addition, nflow-tests component contains integration tests over demo workflows.
The following example scenarios illustrate how you can use nFlow with your applications.
Use embedded nflow-engine to run your own workflows inside your own application.
Same as the previous scenario except you've exposed nFlow services through REST services implemented in nflow-rest-api. You can use any REST stack (e.g. Jersey, Apache CXF, etc) that supports JAX-RS specification.
Full blown nFlow running on embedded Jetty (nflow-jetty -module).
In nFlow terminology, you have workflow definitions and instances. A workflow definition is Java class that contains the implementation of a business process (e.g. credit application process). A workflow instance is a runtime instance of the business process (e.g. credit application from a certain customer). As a developer, you need to implement the workflow definition after which the workflow instances can be submitted through nflow-engine API or nflow-rest-api services.
A workflow can be composed of human tasks (e.g. accept application), technical tasks (e.g. call REST service) or both of these tasks. A simple workflow that involves creating a credit application, the credit decision, possible money transfer and finally closing the credit application is illustrated below. The Java code for CreditApplicationWorkflow
can be found from nflow-tests -module.
CreditApplicationWorkflow
begins by extending WorkflowDefinition
, which is the base class of all workflow definitions in nFlow. The state space of the workflow is configured with several ways:
- Defining public static fields implementing
WorkflowState
. For example one could useio.nflow.engine.workflow.curated.State
or create own implementation - Giving
initialState
orerrorState
toWorkflowDefinition
constructor - Use states in
permit
methods will register them also - Pass the states to
WorkflowDefinition
constructor viastates
parameter - Register the states via
registerState
method
In this example, the states are also given a type and documentation. The following state types are supported (WorkflowStateType
-enumeration):
- start: Initial state of a workflow that is executed and retried automatically by nFlow. The workflow processing continues to the next state based on business logic implemented in the state method.
- normal: A state of a workflow that is executed and retried automatically by nFlow. The workflow processing continues to the next state based on business logic implemented in the state method.
- wait: A state for waiting something outside this instance to happen, including (but not limited to) child workflow instances to go to end state.
- manual: A state that requires external action, usually a human task. nFlow executes the state method (if it exists) and then waits for the state to be update externally.
- end: A final state of a workflow, failed or successful. nFlow executes the state method (if it exists) and then stops processing the workflow.
The state types are also used for visualizing the state diagram of a workflow.
public class CreditApplicationWorkflow extends WorkflowDefinition {
...
private static final WorkflowState CREATE_CREDIT_APPLICATION = new State("createCreditApplication", WorkflowStateType.start,
"Credit application is persisted to database");
public static final WorkflowState PREVIEW_CREDIT_APPLICATION = new State("previewCreditApplication", start,
"Check if credit application would be accepted (ie. simulate)");
private static final WorkflowState ACCEPT_CREDIT_APPLICATION = new State("acceptCreditApplication", manual,
"Manual credit decision is made");
private static final WorkflowState GRANT_LOAN = new State("grantLoan", "Loan is created to loan system");
private static final WorkflowState FINISH_CREDIT_APPLICATION = new State("finishCreditApplication",
"Credit application status is set");
private static final WorkflowState DONE = new State("done", end, "Credit application process finished");
private static final WorkflowState ERROR = new State("error", manual, "Manual processing of failed applications");
...
Each workflow implementation must have the following properties set through base class constructor:
- name: defines the name that is used when submitting new instances (creditApplicationProcess)
- default start state: state from which new instances start by default (createCreditApplication)
- generic error state: error state for generic failures (error)
Optionally you can also override default timing related settings through custom subclass of WorkflowSettings
(CreditApplicationWorkflowSettings). Next you can define allowed state transitions through permit()
which checks that the corresponding state handler methods exist.
public CreditApplicationWorkflow() {
super("creditApplicationProcess", createCreditApplication, error,
new CreditApplicationWorkflowSettings());
permit(CREATE_CREDIT_APPLICATION, ACCEPT_CREDIT_APPLICATION);
permit(ACCEPT_CREDIT_APPLICATION, GRANT_LOAN);
permit(ACCEPT_CREDIT_APPLICATION, FINISH_CREDIT_APPLICATION);
permit(FINISH_CREDIT_APPLICATION, DONE);
}
For each start and normal state there must exist a state handler method with the same name. For manual and end states the state handler method is optional. The state handler method must be a public
method that returns NextAction
(start and normal states) or void (manual and end states) and takes StateExecution
as an argument. NextAction
class contains static methods for creating return values that control nFlow execution, like NextAction.moveToState(...)
, NextAction.retryAfter(...)
etc. StateExecution
contains the main interface through which workflow implementation can interact with nFlow (see next section). StateExecution
can be followed by optional state variable definitions (see state variables).
Each start and normal state handler method must define and schedule the next state execution by returning a valid NextAction
value. For instance, CreditApplicationWorkflow.createCreditApplication()
defines that the next state, acceptCreditApplication, is executed immediately. Manual and final state handler methods (e.g. acceptCreditApplication and error) are optional. These methods do not need to return any value because nFlow will stop processing the workflow after the state method is executed.
public NextAction createCreditApplication(StateExecution execution,
@StateVar(instantiateNull=true, value=VAR_KEY) WorkflowInfo info) {
...
info.applicationId = "abc";
return NextAction.moveToState(ACCEPT_CREDIT_APPLICATION, "Credit application created");
}
public void acceptCreditApplication(StateExecution execution,
@StateVar(value=VAR_KEY) WorkflowInfo info) {
...
}
public NextAction grantLoan(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public NextAction finishCreditApplication(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public void done(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public void error(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
The mechanisms described in this section should be sufficient to implement the interaction between your workflows and nFlow.
Each start and normal state handler method must return a valid NextAction
value that controls the execution of the workflow instance. Returning null will put the workflow instance in error state. To create a valid NextAction
return value, use one of the following static methods:
-
retryAfter(DateTime activation, String reason)
: Execute the current state handler method after given activation time. -
moveToStateAfter(WorkflowState nextState, DateTime activation, String reason)
: Execute thenextState
handler method after given activation time. -
moveToState(WorkflowState nextState, String reason)
: Execute thenextState
handler method immediately. -
stopInState(WorkflowState finalState, String reason)
: Move tofinalState
but do not execute thefinalState
handler method.
StateExecution
is the access point for all the workflow instance-specific information in state handler methods.
- businessKey: optional business identifier (e.g. application specific id) for the workflow instance
- variables: business process variables
State variables are persistent objects/values that are workflow instance specific. State variables are stored after state handler method execution and are available in subsequent states of the process.
Optionally you can define @StateVar
-annotated POJOs (must have zero argument constructor) or Java primitive types as additional arguments after StateExecution
argument. The additional arguments are automatically persisted by nFlow after state execution. In CreditApplicationWorkflow
class WorkflowInfo
is instantiated automatically (instantiateNull=true
) before createCreditApplication
-method is entered.
WorkflowSettings
can be accessed through WorkflowDefinition.getSettings()
-method. Currently it contains timing and retry related parameters.
Spring is the preferred way of integrating nFlow with your own application. You need to import/declare a Spring configuration bean in your Spring application context. The configuration bean type depends on the usage scenario (see section Usage Scenarios) that you selected.
-
io.nflow.engine.config.EngineConfiguration
(Embedded Engine Only) -
io.nflow.rest.config.RestConfiguration
(Inside Your Application Server) -
io.nflow.jetty.config.NflowJettyConfiguration
(Full nFlow Stack)
nFlow will autodetect your WorkflowDefinitions
that are defined as Spring beans in the same Spring application context.
If you don't want to learn Spring, you can only use Full nFlow Stack-scenario.
Define a start class for nFlow like in 1 Minute Guide. Then add the fully qualified class names of your WorkflowDefinitions in a text file. Package the text file with nFlow and define the name of the text in nFlow property called nflow.non_spring_workflows_filename
.
See nflow-tests
-module for an example.