Introduction
A complex integration may require that data is sent to several different applications with strict rules on the sequence and control involved. For instance building an integration to process a purchase order may require both logistics and financial applications to be updated. webMethods workflow is a great way to manage this complexity visually and simply without having to worry about the low level details.
However, until now there was one very common use case that could not covered and that is the problem of long running actions. Let's take our example above for purchase orders and imagine a requirement where any order over 100 euros must be verified before continuing. Also this step will be carried out by a real breathing human being, and as we can all appreciate they like to eat, sleep and not respond to work actions 24 hours, 7 days a week. In which case this action may take several days before completion. In which case we don't want our workflow to be blocked waiting.
Suspend and resume later
That's why we have introduced a new feature to workflow called "Suspend and resume later", available from the connectors palette.
Using this step will make your workflow go to sleep and importantly pause the transaction counter. Your workflow can sleep up to 25 days maximum, which should be more than enough for most requirements.
Let's go through an example to see how it works. I have attached a zip file of the following workflow to this article that you can import into a project of your own. From your project -> Integrations -> Workflow, click on "import" and select the zip file from this article. You should see the following.
It starts with a web hook, from there you can see that the payload is a simple json order as below
One important caveat here, if you look at the example above, you will see that we send back a response to the caller before waiting. In fact this is mandatory if you want to use a synchronous workflow as it will not allow you to insert a wait step before a reply step. This make sense because there is no point suspending the workflow if an inbound http connection is still waiting a reply. Therefore wait steps can only be used in what we term the asynchronous part of your workflow i.e. the bit that occurs after the inbound http request has been dealt with.
Approve the Order
Our wait step is only required if the order amount is over 100, as per the first switch statement. However, before we can suspend the workflow we must first initiate the action to ask for approval.
Async action and wait steps
The request for approval could be via an intermediary application ranging from a dedicated ticketing system and task manager such as ServiceNow or a dedicated phone app. Critically you must first share the callback url for your workflow engine, along with the unique id of the workflow instance with the approver app. The app will then eventually when ready call the url with the included unique id to resume your workflow instance. The callback url is provided directly in the wait step, and you will need to copy it from the wait step and either encode it directly into your third party app or get the app to call it dynamically by including it in the approval request.

In this example I simply send an email with the callback links formatted directly in the body. Your will need to replace the tenant address in the callback url with your own. For simplicity sake you can obtain the full callback url directly from the wait step, but only as far as the last slash '/', do not remove the end part '/{{$meta.execution_id}}?isok=true'. Also don't forget to replace the "To" attribute with your own email address, otherwise I will get your approval instead ;-)
Hi,
Please confirm that the following order for {{$request.body.from}} is allowed.
Amount is {{$request.body.amount}} in {{$request.body.currency}} and was received on {{$request.body.date}}
Click this link to accept
https://wmintanywhere.int-aw-au.webmethods.io/runflow/resume/a2/{{$meta.execution_id}}?isok=true
Click this link to reject
https://wmintanywhere.int-aw-au.webmethods.io/runflow/resume/a2/{{$meta.execution_id}}?isok=false
This step will allow you to make your choice directly from the received email by simply clicking on one of the links.
Workflow metadata
We have added a new section to the transformation step of workflow called Metadata that includes one new attribute named 'execution_id'. This is a unique id generated for each workflow transaction when it starts and allow the callback to specify which instances to resume when invoked. That's why it was important to not remove this from the urls that you modified above. Without this the generated urls will be missing the unique execution id to allow the workflow engine to resume the correct instance.
Providing data via the callback
The last part of the callback url is a query parameter to ensure that the callback can provide the additional information that is required for the workflow to continue. You can specify any number of query params as you wish or you could also provide more complex data via http headers or a body if the callback uses the POST method.
{{$meta.execution_id}}?isok=true
For our purposes we only need a single boolean response to indicate that yes we will accept the order or no we won't, but the callback data must be specified in the wait step just as with the start step when making it into a webhook. You can edit the callback payload by clicking on the edit button in the wait step and filling out either the header, query or body sections.
Successive steps can be wired from the wait step to successive steps just like normal. In our example we use a switch to evaluate the 'isok' response to determine if accept or reject the order.
You can run the workflow directly from the canvas and you will see it pause at the wait step. Wait a few moment and you should get an email from your tenant, albeit it might get lost in your spam/junk folder. From the email simply click on the accept or reject link depending on how you feel about the order. You will need to authenticate using your credentials to allow the callback to do its thing. Go back to the workflow and you will see that it will have either accepted or rejected your order based on your choice. As said earlier you could have waited up to 25 days to respond to the email before the workflow would have timed out.
Monitoring long running Workflows
We have also added a new suspended status to workflow monitoring to ensure that you can identify workflows that have been suspended due to a wait step. The status will show as suspended and the details page will identify the wait step that is active.

Suspended workflows can be terminated if required and the wait timeout can be adjusted down from 25 days, in which case if is it exceeded then the workflow will have the status "timed out" and terminate.
Transactions counter
I mentioned this above but it is worth repeating. Whilst a workflow is suspended the transaction counter is paused and only resumed once the workflow restarts. So even if you have a suspended workflow for 2 days but it is only active for 2 seconds, then you will pay for only a single transaction. Obviously if you have multiple streams in your workflow, one stream may be waiting whilst another is still running. In which case the transaction counter continues to tick until that stream joins with the waiting one.
Grab bag
You can have more than one wait step in a workflow and even have wait steps running in parallel streams. However, they must all join before a workflow can terminate and all wait steps must be respected. Also the callback url could be invoked internally from another workflow, API or service. In which case I would recommend that you mark it as private to avoid exposing it over the public internet.
Future Plans
This is just the first iteration of what we plan to do with Suspend and resume and will be adding many features to it over the next few months, such as
- configurable timeout for each wait step.
- dedicated error handler for each wait step.
- Alternative correlation id to avoid external applications having to know the 'execution_id'.
- token based authentication for callback.
- message based callback as alternative to http.
This last one is especially important to us as it will make the implementation of an event driven integration much simpler.