Inventory Logic

In this section, you will expand the workflow logic to manage a first stage of fictional use case.

The use case

As any other tutorial use case, the situation we are going to consider is somewhat realistic, but for sake of simplicity we are going to oversee many real aspects. The primary goal is to show the key capabilities of the Serverless Workflow specification, please, apologise for the many naiveties that domain experts can easily point out.

An e-commerce company has to implement the following order management workflow:

  • When a new order come in, they need to check the inventory for the availability of the items. If the items are available the order will be prepared for shipping (picking, packaging, printing label, etc), when the shipping is completed, the shipping department send an event back to the workflow and the customer is notified about the shipping status with usual tracking information.

  • If the item is out of stock, the order will be forwarded to a external supplier who will take care of the shipping procedure, when the supplier ships the order, it also send an event back to the workflow, in such a way the workflow can continue and send the notification to the customer.

  • As long as the order is not shipped, the customer has the option of cancelling the order by also cancelling the shipping.

The following picture shows an high level design:

high level flow

The final use case will be implemented going through a set consecutive sprints[1], in every sprint you are going to experience a new feature of the Serverless Workflow specification.

The Inventory Sprint

In this sprint we are going to add the check inventory operation and based on the outcome call a prepare for shipping or forward to external supplier.

Switch back to the Serverless Logic Web Tools to edit the order workflow:

  1. Rename the first state from Order Received to Check Inventory updating the following places:

    • the start value

    • state name

    • the message content

    To change all occurrences in one shot: select Order Received, press twice CTRL-D, perform the rename, then press ESC
  2. In the Check Inventory state, add the following definition just after the functionRef object (at the same level):

            actionDataFilter:
              fromStateData: .
              results: '{inventory: .item | test("0+") }'

    This code mocks up the check inventory logic: actionDataFilter is a feature to manipulate the workflow data (state scoped), in practical terms it gets the item value and create a new data inventory which value can be true or false if the item contains one or more 0

    The previous logic is an example of the JQ expression language which plays a key role in Serverless Workflow. To evaluate and manipulate data is crucial to gaining some familiarity with this language Understanding JQ expressions
  3. Introduce a new switch state after the previous state:

    1. Move the cursor to the end of yaml file at state level and type - (a dash followed by a space) and you should get the suggestion pop up, hit Enter to confirm the suggestion.

      new switch state
    2. Update the template keys name and condition as in the following snippet:

        - name: 'Item Available?'
          type: switch
          dataConditions:
            - condition: '.inventory'
              transition: 'Transition to another state if condition is true'
          defaultCondition:
            transition: 'Default transition of the workflow'
    3. Go back to Check Inventory state and replace the end declaration with transition to point to the switch state:

      transition: Item Available?
  4. After the switch, you have to add other two states:

    1. Add a new operation state for Prepare for Shipping:

        - name: 'Prepare for Shipping'
          type: operation
          actions:
            - name: printAction
              functionRef:
                refName: printMessage
                arguments:
                  message: Prepare for Shipping
          end: true
    2. Add an new operation state for Forward to External Supplier:

        - name: 'Forward to External Supplier'
          type: operation
          actions:
            - name: printAction
              functionRef:
                refName: printMessage
                arguments:
                  message: Forward to External Supplier
          end: true
  5. Update the switch state to point to the correct operation states:

    1. for the conditional branch set the transition to Prepare for Shipping

      03 condition
    2. for the default condition set the transition to Forward to External Supplier

The workflow diagram should now resemble the following:

03 wf switch

You can compare your resulting workflow with the expected solution at this stage in solution/01-inventory

Test the workflow logic

Before connecting the workflow to an external service is a good idea to probe it in isolation (i.e. smoke test): in fact, the current actions only print messages in the console.

  1. Deploy the current workflow:

    1. Select Try on OpenShift button and then Upload "order" to Dev Mode.

      upload
    2. Wait for the confirmation message and select Go to Serverless Workflow Dev UI ↗ to open the Dev UI in a new browser tab.

      Dev UI
  2. Trigger a new workflow instance:

    1. Select Workflow Definitions

    2. Click on the arrow button in corresponding to the order row.

      Workflow definitions
    3. Fill in the Start Workflow Data edit box with the following JSON payload:

      {
          "orderId": "1000",
          "item": "1110"
      }
    4. Select the Start button below.

  3. Check the results and the workflow execution:

    1. Switch to the Workflow Instances page

    2. Click on the latest instance to show the Workflow Details page

  4. Trigger a new workflow instance with the following payload and make sure that the workflow execution follow the other branch (Forward to External Supplier)

    {
        "orderId": "1001",
        "item": "1111"
    }

Another tool for checking the workflow execution is the Console:

  1. At the bottom of the Dev UI, click on the Open toggle.

    open console
  2. Among other log lines, you should spot the output of printMessage:

    console

Call an external REST service

Serverless Workflow have a straightforward integration with OpenAPIs.

In order to experiment this capability, we’ll use a side application called order-swf-tut-svc that exposes two simple REST operations:

  • sendOrder to send order to a supplier

  • cancelOrder to send an order cancellation to a supplier

order-swf-tut-svc application should be already deployed in the swf-shared namespace. However, if it’s not the case, you’ll find direction on how to deploy it in the Setup chapter.

The link between the workflow and the rest service is the OpenAPIs spec file that should be located inside the specs folder.

For sake of simplicity, you will import a project that contains all the required files: the workflow yaml, the OpenAPI spec and the application.property file. The latter contains information about the REST service endpoint.

  1. Open the Serverless Logic Web Tools in your browser (if you already have it in your browser window, make sure to click on the top banner to open the home page).

  2. Locate the Import box in the page and copy the following address in the URL field: https://github.com/dmarrazzo/order-swf-tut.git

  3. Click the Clone button

The tool will take you to the Serverless Workflow designer, but you can switch to the other files in the project by clicking the arrow next the file name:

repository navigation

In the following steps, you’ll enhance the workflow design to call an external service:

  1. Add the OpenAPI references in the functions declaration section:

    - name: sendOrder
      operation: specs/supplier.yaml#sendOrder
      type: rest
    - name: cancelOrder
      operation: specs/supplier.yaml#cancelOrder
      type: rest
  2. Locate the Forward to External Supplier state declaration.

    You can click on state in the workflow diagram and the tool will take the cursor to the declaration line in the yaml editor.
  3. Replace printAction with sendOrder:

      actions:
      - name: sendOrder
        functionRef:
          refName: sendOrder
          arguments:
            supplier-id: sup-01
            content: '.orderId'
    The rest service is invoked with two arguments, a dummy supplier-id (sup-01) and the value of orderId.

Test the external REST service

Deploy the workflow latest updates:

  1. Select Try on OpenShift button and then Upload "order" to Dev Mode.

    upload
  2. Wait for the confirmation message and select Go to Serverless Workflow Dev UI ↗ to open the Dev UI in a new browser tab.

    Dev UI

In order to test the REST call you have to trigger a new workflow instance with the following payload:

{
    "orderId": "1002",
    "item": "1111"
}

In the log file you should notice a different output coming from the REST implementation:

Triggered node 'Forward to External Supplier' for process 'order' (0ce6279c-2e84-42d0-b651-5e7b5257ef74)
Triggered node 'sendOrder' for process 'order' (0ce6279c-2e84-42d0-b651-5e7b5257ef74)
Property 'workflowdata.response' changed value from: 'null', to: '"receipt-sup-01-1002"'

Finally, open the workflow instance details and pay attention to a new variable which is injected by the REST service response:

response variable

CONGRATULATION!!! Now your Serverless Workflow call a REST service!


1. A Sprint is an iteration in the Agile methodology, which aims to be time-boxed, self container and always executable.