java.lang.Object
com.broadleafcommerce.orchestration.workflow.Workflow

public final class Workflow extends Object
Provides facilities for a SimpleWorkflowExecution to retrieve callable instances of SimpleActivity while recording the history and responses for posterity. This is especially useful when reconstituting workflows for operations like SimpleWorkflow.goToStep(String) where that same historical information is used to re-build the state of the workflow and then pick up execution at the point requested. This API should generally not be called by SimpleWorkflow implementations extending from AbstractSimpleWorkflowExecution, as that abstract superclass is intended to handle these execution requirements.
  • Method Details

    • newActivityStub

      public static <T> T newActivityStub(String beanName)
      Creates client stub to activities that have the provided bean name in Spring. This is a special Broadleaf-only case.
      Parameters:
      beanName - name of the Spring bean for the activity
    • sideEffect

      public static <R> R sideEffect(Class<?> resultClass, Functions.Func<R> func, @Nullable Object activity)
      Executes the provided function once, records its result into the workflow history. The recorded result on history will be returned without executing the provided function during replay. This guarantees the deterministic requirement for workflow as the exact same result will be returned in replay. Common use case is to run some short non-deterministic code in workflow, like getting random number.

      Caution: do not use sideEffect function to modify any workflow state. Only use the SideEffect's return value. For example this code is BROKEN:

       
        // Bad example:
        AtomicInteger random = new AtomicInteger();
        Workflow.sideEffect(() -> {
               random.set(random.nextInt(100));
               return null;
        });
        // random will always be 0 in replay, thus this code is non-deterministic
        if random.get() < 50 {
               ....
        } else {
               ....
        }
       
       
      On replay the provided function is not executed, the random will always be 0, and the workflow could takes a different path breaking the determinism.

      Here is the correct way to use sideEffect:

       
        // Good example:
        int random = Workflow.sideEffect(Integer.class, () -> random.nextInt(100));
        if random < 50 {
               ....
        } else {
               ....
        }
       
       
      If function throws any exception it is not delivered to the workflow code.
      Parameters:
      resultClass - type of the side effect
      func - function that returns side effect value
      Returns:
      value of the side effect