A Developer Introduction Tutorial to ProcessMaker.IO

Hi everyone. I’m Taylor Dondich and I am the CTO here at ProcessMaker. ProcessMaker.IO is our performant workflow engine in the cloud and I am excited to show you how to get started. The best way to show you how is with actual code.
 
This first post is the first in a series of tutorials that will first introduce you to ProcessMaker.IO. Each new post will introduce you to new concepts and how to use them. You’ll start with a simple workflow and then work your way to using more complex scenarios. These scenarios will show some of the exciting features that ProcessMaker.IO has.
 
ProcessMaker.IO is free to sign up and get started. Once you have your account, you can grab code for these tutorials in our GitHub repository.
For our example, let’s assume we’re a developer at Widget Co. Our boss wants us to build a form that allows our customers to contact us for any reason. If they fill out the form, we should receive an email with the details the customer provided.
 
It’s a simple example and perfect to get our feet wet.

Signing up and Starting Your First Workflow Engine

First, visit the ProcessMaker.IO registration page to create your account.

Once you’ve filled out your details, you’ll receive an email that has a link to verify your account. Once verified, you can create your first workflow engine.

You’ll see the ProcessMaker.IO dashboard. This dashboard shows the list of your workflow engines. Since you don’t have any, click on the “Create Instance” button to create your own engine.
 

About Workflow Engines

Each workflow engine is an isolated environment that has it’s own API endpoint and data. This level of isolation allows you to have many engines for different scenarios. You could have an engine for a staging environment and one for production. You can have separate engines for different business units. How you organize your engines is up to you. Each engine has it’s own data and cannot see the data from another engine in your account.

Creating Your First Workflow

For our example, we will be creating a simple workflow, also known as a process, that will send an email. If we were to visualize this workflow, it would look like the following:

If you are familiar with business processes, the above diagram will look familiar. It’s a BPMN diagram that visually represents what we want to do.  ProcessMaker.IO is a BPMN compliant workflow engine. If you are familiar with BPMN, you’ll feel comfortable using the engine. If you are not familiar with BPMN, don’t worry, it’s not necessary knowledge. We’ll walk through the concepts.

When creating a workflow in ProcessMaker.IO, you have a choice on how to do so. If you are familiar with BPMN diagramming tools, you can create a BPMN diagram and import it into the engine. We’ll show an example of this in a later tutorial. You can also create a process programatically, which is what we’ll do in this example.  ProcessMaker.IO has SDKs available in many languages. For this example, we’ll use the ProcessMaker.IO PHP SDK.

First, we want to initialize our SDK client. To do this, you’ll need your engine’s API endpoint and your first user’s API access token. These can be found in your dashboard.

Be sure to download the code from our GitHub repository. We’ll use this as a starting ground. You’ll want to run PHP’s composer install command to install the SDK.  Once done, create a .env file at the root of your code directory. This will contain your API endpoint, access token and other configuration options.

PMIO_ENDPOINT=https://fds23zz.api.processmaker.io/api/v1
PMIO_ACCESS_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjkwMTBmZGI5YWMxYTZiNGI2ZGMyZjNiODZmZDg5OTJhYWRlODI0MGU5MWI3NWRkNDhjNTA4MzRlYjQzZjUzNmFjMDkxNTg4MDY5MDZiM2MxIn0.eyJhdWQiOiIxIiwianRpIjoiOTAxMGZkYjlhYzFhNmI0YjZkYzJmM2I4NmZkODk5MmFhZGU4MjQwZTkxYjc1ZGQ0OGM1MDgzNGViNDNmNTM2YWMwOTE1ODgwNjkwNmIzYzEiLCJpYXQiOjE1MDY1NDM5MTMsIm5iZiI6MTUwNjU0MzkxMywiZXhwIjoxNTM4MDc5OTEzLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.PTFaPvddgKqB51trFAV2Ka_8W2npZ9jbc2uGAoYdFKfMNNvvNl07DWTDXxK90B0OwLAA08husWmfkVomWlm6W44hXuJEa8zG3SfRGwpzPQiA4NZ706YkbWqjLfY5QH41MwpJlkgKeQv6Q6nvZluyXrzQlvZVkSfSb9GvNe4h6arLLn1KQp3xQnnK-Jk8Q109uEnhmkOs4mfUKj5rd0E_DKJUTc-CmXoJZ8zsvuDv-irv7PtQlpQRmVdlOJD2mTO2NNwQpLjdl4d3D4a7zKpMcrkeLmqz_Cums4uk5069Ju2TRmAbyGfWUgL7aTg-o80xWPnwY9AY7xC__mZvW1ydlpLKX18-bIpj_5acCyqQmnA921KAoO99YV3rT19I_VKF9dglzMOPWrcLzb44qK4ONXjx8Za3zyFJZpBa_SrCkhYiOhY1GNNk5EpqqMCAT_D8nCnrR7fmLrXtFJsP9yPDYwMZxYuppCH6rcqLIeB0VlmEiNTJu_1RlYgcmG02boSNPXHmzrEd9eJKRksSWVfkE90quuDMNoEFYaL1A_yU0yn2iW0T--lh_kPOGEth2WrShoYEZ667FSrSmsRYoLe8BiqGbiSquYrtDhHYhcidOeWyZLtUDMnVNi00v3i3hrIp7KIvIM9zAQxzk3OwAxXFrKV6Ut3-cqyvpMhWo9NPyZI
# Set to true if you want to log every HTTP api call
TARGET_EMAIL_ADDRESS=myaddress@mydomain.com
PMIO_DEBUG=false
PMIO_DEBUG_FILE=debug.log

 

Initializing the PHP SDK

We want to first initialize our API Client with our credentials. In our code examples, the file is bootstrap.php file. This file is included in all examples. Let’s see how the client gets initialized.

// Create our API configuration object and pass in it's configuration
$config = new Configuration();
$config->setHost(getenv('PMIO_ENDPOINT'));
$config->setAccessToken(getenv('PMIO_ACCESS_TOKEN'));
$config->setDebug(getenv('PMIO_DEBUG'));
$config->setDebugFile(__DIR__ . '/' . getenv('PMIO_DEBUG_FILE'));

// Initialize our API client which will be referenced by client scripts
$pmio = new Client(new ApiClient($config));

 

Creating the Process Object

The process object is what stores the definition of our workflow. It will contain the mapping of events, to tasks and how each element flows to the next. Don’t worry about those terms, we’ll cover them soon. In the introduction/create.php file, we start by creating the process object via our API.

$response = $pmio->addProcess(new ProcessCreateItem([
    'data' => new Process([
        'attributes' => new ProcessAttributes([
            'name' => 'Introduction Process'
        ])
    ])
]));
// Get the underlying data object that really represents our process
$process = $response->getData();

 

Creating the Start and End Events

In the workflow world, events describe what happens in your workflow at various times. For our simple case, we are using a Start Event and an End Event. A Start Event is what begins the execution of our process. Our Start Event triggers when a customer submits the contact form.  The End Event signals that our workflow is complete. The goal of the workflow is to get from the Start Event to the End Event.  In the file, introduction/create.php, you’ll see how we create them.

$response = $pmio->addEvent($process->getId(), new EventCreateItem([
    'data' => new Event([
        'attributes' => new EventAttributes([
            'name' => 'Start',
            'type' => 'START',
            'definition' => EventAttributes::DEFINITION_MESSAGE
        ])
    ])
]));
$startEvent = $response->getData();

$response = $pmio->addEvent($process->getId(), new EventCreateItem([
    'data' => new Event([
        'attributes' => new EventAttributes([
            'name' => 'End',
            'type' => 'END',
            'definition' => EventAttributes::DEFINITION_NONE
        ])
    ])
]));
$endEvent = $response->getData();

Creating the Task to Send an Email

In our workflow, we want to send an email when the customer submits the contact form. To do so, we need to use a Service Task. A task represents something actionable in a workflow and who should it involve. A Service Task runs in the background and does not need human intervention. This is exactly what we want for having our workflow send an email.

$response = $pmio->addTask($process->getId(), new TaskCreateItem([
    'data' => new Task([
        'attributes' => new TaskAttributes([
            'name' => 'Send Contact Form Email',
            'type' => 'SERVICE-TASK'
        ])
    ])
]));
$serviceTask = $response->getData();

We have to tell our ServiceTask it’s implementation details. We’ll use one of ProcessMaker.IO’s connectors to provide the ability to send mail. ProcessMaker.IO has many connectors which allows interactions with 3rd party services. Connectors for Slack, Mailchimp and Google Apps and more are available.

Let’s first create our email template so we can tell our connector to use it.

$template = <<<EOM
Hi there!  It looks like someone submitted a contact form!  Here's their information:<br>
<br>
Name: {name}<br>
Email: {email}<br>
Subject: {subject}<br>
Message: {message}<br>

EOM;
This is an HTML email template. You can see some fields surrounded by curly braces. ProcessMaker.IO can inject values into these placeholders. The Data Model of the running process holds these values. In our example, the submission of the HTML form represents the Data Model.
 
Let’s create our connector and tell it to associate with our ServiceTask.
$pmio->addTaskConnector($process->getId(), $serviceTask->getId(), new TaskConnectorCreateItem([
    'data' => new TaskConnector([
        'attributes' => new TaskConnectorAttributes([
            'connector_class' => 'SendMailConnector',
            'input_parameters' => [
                'to' => getenv('TARGET_EMAIL_ADDRESS'),
                'name' => 'Introduction Form Submission',
                'subj' => 'Contact Form Submission from {name}',
                'body' => $template
            ]
        ])
    ])
]));

Be sure that you modified the TARGET_EMAIL_ADDRESS in your .env file. You can see it referenced in the code example.

Wiring It All Together with Flows

Now that we have our events and tasks, we need to define the path from the Start Event to the End Event. Flows define these paths. A Flow must have a source and target. For example, our first flow starts from our Start Event and ends with the ServiceTask. Another Flow moves from the ServiceTask to our End Event. Let’s create them now.

$pmio->addFlow($process->getId(), new FlowCreateItem([
    'data' => new Flow([
        'attributes' => new FlowAttributes([
            'name' => 'Start to Service Task',
            'from_object_id' => $startEvent->getId(),
            'from_object_type' => $startEvent->getType(),
            'to_object_id' => $serviceTask->getId(),
            'to_object_type' => $serviceTask->getType()
        ])
    ])
]));

$pmio->addFlow($process->getId(), new FlowCreateItem([
    'data' => new Flow([
        'attributes' => new FlowAttributes([
            'name' => 'Service Task to End',
            'from_object_id' => $serviceTask->getId(),
            'from_object_type' => $serviceTask->getType(),
            'to_object_id' => $endEvent->getId(),
            'to_object_type' => $endEvent->getType()
        ])
    ])
]));

Keeping our Process ID and Start Event ID for Future Use

Once we have defined our Process, we need to know the ID of the Process and the Start Event. We will use these values when calling our API with our HTML Form data.

print("Process ID: " . $process->getId() . "\n");
print("Start Event ID: " . $startEvent->getId() . "\n");

Executing Your Create Script

When executing your script, you’ll get your final Process ID and Start Event ID

$ php ./introduction/create.php
Process ID: b78fc897-91f8-4f38-b8e3-7d60267d9b67
Start Event ID: 271bf2f1-47bb-4616-9edb-3892b5696710

 

Preparing the HTML Form

Now that we have a workflow defined in our engine, we can prepare our HTML form. In our code examples, a form is already prepared in the introduction/form.html file.
 
We want to update the file to define a variable that represents an API endpoint from our engine. This endpoint is the webhook for our Start Event.
<script>
    var pmio_webook = 'http://core.pmio.local/api/v1/processes/b78fc897-91f8-4f38-b8e3-7d60267d9b67/events/271bf2f1-47bb-4616-9edb-3892b5696710/webhook';
</script>

Notice the URL contains both the Process ID and the Start Event ID. The webhook endpoint allows us to send an HTTP POST with form data. This form data represents the data model when the workflow executes.

For our example, we’re using jQuery to submit the form to our webhook. We use an AJAX call. If the call is successful, we show a nice message to the user and our workflow kicks off.

$('#contact-form').on('submit', function(e) {
     $.ajax({
         url: pmio_webook,
         type: 'POST',
         data: {
             name: $('#contactInputName').val(),
             email: $('#contactInputEmail').val(),
             subject: $('#contactInputSubject').val(),
             message: $('#contactInputMessage').val()
         }
     })
         // Our promise handler on success
         .done(function() {
             $('#contact-form button, #contact-form p.alert-danger').remove();
             $('#contact-form p.alert-success').removeClass('hide');
         })
         // And our promise handler on failure
         .fail(function(xhr, status, err) {
             $('#contact-form p.alert-danger').removeClass('hide');
         });
     return false;
 });

Submitting the Form

If you load the HTML file in your browser, you’ll be able to submit the form and see a success message. Behind the scenes, it called our workflow’s start event webhook. It’s alive!

The Workflow Instance Lifecycle

Start Events create new instances of a workflow. These instances have their own independent lifecycle as well as it’s own data model. The workflow instance creates a token that travels through the workflow.
 
Starting at the Start Event, it traverse the Flow of the workflow, executing Tasks along the way. The Tasks in the workflow may use the Data Model in their execution as well as change it after execution.
 
The Data Model is a JSON document which can hold complex data types. In our example, the Data Model is the collection of form field values included in the ajax submission.
 
Once the Token reaches the End Event, the instance lifecycle is over. The instance has a status of COMPLETED.
 
In our example, the workflow lifecycle had these steps:
  1. The Token started at the Start Event Webhook, populating the Data Model.
  2. The Token flowed to the ServiceTask, executing the SendMailConnector
  3. The Token flowed from the Service Task to the End Event, signaling the completion of the workflow.
This lifecycle occurs in the engine and is asynchronous to the ajax call.  If you followed along, you should have received an email in your inbox.

Next Steps

Our workflow is very simple but it gave us the opportunity to cover some core concepts. Most workflows are not going to be this simple. Like our example, all workflows will contain a mixture of Events, Tasks and Flows.
 
In our next tutorial, we’ll start to introduce logic into our workflow. We will use logic to send to different email recipients based on evaluating values in our data model.

Leave a Reply

Your email address will not be published. Required fields are marked *