Skip to content
efonsell edited this page Feb 3, 2015 · 27 revisions

Table of Contents

1 Minute Guide

For a super quick 1 minute guide, checkout the frontpage of nFlow repository.

Components

nFlow consist of the following main components, each having the previous component as a dependency.

  1. nflow-engine contains a multithreaded workflow dispatcher, Java API for managing workflows and the persistance layer implementation.
  2. nflow-rest-api contains a JAX-RS compliant REST service implementation for exposing workflow management and query APIs.
  3. 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.

Usage Scenarios

The following example scenarios illustrate how you can use nFlow with your applications.

Scenario 1: Embedded Engine Only

Use embedded nflow-engine to run your own workflows inside your own application.

Scenario 1 picture

Scenario 2: Inside Your Application Server

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.

Scenario 2 picture

Scenario 3: Full nFlow Stack

Full blown nFlow running on embedded Jetty (nflow-jetty -module).

Scenario 3 picture

Anatomy of a Workflow

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.

Implementation Class and States Declarations

CreditApplicationWorkflow begins by extending WorkflowDefinition which is the base class for all workflow implementations in nFlow. The state space of the workflow is enumerated after the class declaration. In this example, the states are also given a type and documentation. The following state types are supported (WorkflowStateType-enumeration):

  • start: an entry point to the workflow
  • manual: requires external state update (usually a human task required)
  • normal: state is executed and retried automatically by nFlow
  • end: final state to which workflow instance has finished

Currently the state types are informational only and useful for visualization.

public class CreditApplicationWorkflow extends WorkflowDefinition<State> {
...
  public static enum State implements WorkflowState {
    createCreditApplication(start, "Credit application is persisted to database"),
    acceptCreditApplication(manual, "Manual credit decision is made"),
    grantLoan(normal, "Loan is created to loan system"),
    finishCreditApplication(normal, "Credit application status is set"),
    done(end, "Credit application process finished"),
    error(manual, "Manual processing of failed applications");
...

Settings and State Transitions

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(createCreditApplication, acceptCreditApplication);
  permit(acceptCreditApplication, grantLoan);
  permit(acceptCreditApplication, finishCreditApplication);
  permit(grantLoan, finishCreditApplication);
  permit(finishCreditApplication, done);
}

State Handler Methods

For each state there must exist a state handler method with the same name. The state handler method must be a public method that returns NextAction 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 state handler method must define and schedule the next state execution by returning a valid NextActionvalue. For instance, CreditApplicationWorkflow.createCreditApplication() defines that acceptCreditApplication-state is executed immediately next. Manual and final states (e.g. acceptCreditApplication and error) must unschedule themself. If a manual or final state does not have a state handler method, they are automatically unscheduled. Unscheduling can also be done by returning NextAction.stopInState(...).

public NextAction createCreditApplication(StateExecution execution, 
        @StateVar(instantiateNull=true, value=VAR_KEY) WorkflowInfo info) {
  ...
  info.applicationId = "abc";
  return NextAction.moveToState(acceptCreditApplication, "Credit application created");
}

public NextAction acceptCreditApplication(StateExecution execution, 
        @StateVar(value=VAR_KEY) WorkflowInfo info) {
  ...
  return NextAction.stopInState(acceptCreditApplication, "Expecting manual credit decision");
}

public NextAction grantLoan(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public NextAction finishCreditApplication(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public NextAction done(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info)
public NextAction error(StateExecution execution, @StateVar(value=VAR_KEY) WorkflowInfo info) {
  ...
  return NextAction.stopInState(error, "Stopped in error state");
}

Interacting with nFlow

The mechanisms described in this section should be sufficient to implement the interaction between your workflows and nFlow.

NextAction -class

Each 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 the nextState handler method after given activation time.
  • moveToState(WorkflowState nextState, String reason): Execute the nextState handler method immediately.
  • stopInState(WorkflowState finalState, String reason): Move to finalState but do not execute the finalState handler method.

StateExecution -interface

StateExecution is the access point for all the workflow instance-specific information in state handler methods.

  • businessKey: optional business identifier (e.g. application id) for the workflow instance (read-only)
  • requestData: initial workflow instance business parameters (read-only)
  • variables: business process variables

State 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 -interface

WorkflowSettings can be accessed through WorkflowDefinition.getSettings()-method. Currently it contains timing and retry related parameters.

Setting Up Your nFlow

Using Spring Framework

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.

nFlow will autodetect your WorkflowDefinitions that are defined as Spring beans in the same Spring application context.

Without Spring Framework

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.