IN THIS ARTICLE
Stamplay is a service for chaining together and mashing up APIs, combining them into workflows to create new APIs or automate processes. Consider it the LEGO for APIs. So naturally, it was a perfect fit for our PubNub BLOCKS Catalog to run serverless functions in your realtime apps.
We’re pleased to announce our new Stamplay block for to trigger API workflow integration. What exactly is this “workflow integration” we speak of? In this case, Workflow Integration refers to creating a custom multi-step process that integrates two or more services triggered asynchronously.
In this blog post, we’ll build a sample workflow integration application that combines BLOCKS and Stamplay. But first, let’s dive into the Stamplay API a little deeper.
Stamplay API
Workflow services are quite challenging to build and operate on your own; they require substantial effort and engineering resources to create friendly user interfaces, maintain integration points, and operate asynchronous services at scale. In the meantime, the Stamplay APIs make it easy to enable your applications with custom workflows.
Looking closer at the APIs, simple workflow integration is just the beginning. There are a lot of API methods available for things like document processing, connected device integration, operational support and more. It really is a powerful tool for integrating actions across a wide range of services. In this article though, we’ll keep it simple and implement a basic workflow integration that saves a new user record to a Stamplay database and sends a welcome email.
Tutorial Overview
In this article, we dive into a simple example of how to enable workflow integration in a realtime Angular2 web application with a 24-line PubNub JavaScript BLOCK and 94 lines of HTML and JavaScript. Workflow services can be useful in a variety situations, such as connected car/home, customer service, new user registration, image/video media content uploads, e-commerce, or any application where you want the system to be able to respond asynchronously in a multi-step process.
About the PubNub JavaScript SDK
PubNub plays together really well with JavaScript because the PubNub JavaScript SDK is extremely robust and has been battle-tested over the years across a huge number of mobile and backend installations. The SDK is currently on its 4th major release, which features a number of improvements such as isomorphic JavaScript, new network components, unified message/presence/status notifiers, and much more.
NOTE: In this article, we use the PubNub Angular2 SDK, so our UI code can use the PubNub JavaScript v4 API syntax!
The PubNub JavaScript SDK is distributed via Bower or the PubNub CDN (for Web) and NPM (for Node), so it’s easy to integrate with your application using the native mechanism for your platform. In our case, it’s as easy as including the CDN link from a script
tag.
That note about API versions bears repeating: the user interfaces in this series of articles use the v4 API (since they use the new Angular2 API, which runs on v4). In the meantime, please stay alert when jumping between different versions of JS code!
Getting Started with Stamplay Workflow API
We’ll start with a couple steps to get going:
- Step 1: go to the Stamplay signup form and sign up for a free trial.
- Step 2: follow the wizards to create a new webhook integration including database record creation and email notification.
- Step 3: make note of the Webhook URL from the Webhooks section of the dashboard.
Setting up the BLOCK
To get started with PubNub, and get your code running in the network, a couple of steps:
- Step 1: go to the application instance on the PubNub Admin Dashboard.
- Step 2: create a new BLOCK.
- Step 3: paste in the BLOCK code from the next section and update the webhook URL with the Stamplay URL from the previous steps above.
- Step 4: Start the BLOCK, and test it using the “publish message” button and payload on the left-hand side of the screen.
We’re all good on the set up. Now let’s dive into the code.
Diving into the Code – the BLOCK
You’ll want to grab the 24 lines of BLOCK JavaScript and save them to a file called pubnub_stamplay_block.js
. It’s available as a Gist on GitHub for your convenience.
First up, we declare our dependency on xhr (for HTTP requests) and create a function to handle incoming messages.
export default (request) => { const xhr = require('xhr');
Next, we set up variables for accessing the service (the webhook url).
const STAMPLAY_HOOK = 'YOUR_STAMPLAY_WEBHOOK_URL';
Next, we set up the HTTP params for the workflow API request. We use a POST request to submit the data. We use the JSON content of the message as the POST body, and set the appropriate headers to send/receive JSON.
const reqBody = Object.assign({}, { type: 'block_event' }, request.message); const options = { method: 'POST', headers: { 'Accepts': 'application/json', 'Content-Type': 'application/json' }, body: reqBody };
Finally, we call the webhook endpoint with the given data, decorate the message with a stamplay_response
value containing the parsed JSON response data, and catch any errors and log to the BLOCKS console. Pretty easy!
return xhr.fetch(STAMPLAY_HOOK, options) .then((response) => { request.message.stamplay_response = JSON.parse(response.body); return request.ok(); }) .catch((err) => { console.log('error happened for XHR.fetch', err); return request.ok(); }); }
All in all, it doesn’t take a lot of code to add workflow integration to our application. Next is the UI.
Diving into the Code – the User Interface
You’ll want to grab these 94 lines of HTML & JavaScript and save them to a file called pubnub_stamplay_ui.html
.
The first thing you should do after saving the code is to replace two values in the JavaScript:
- YOUR_PUB_KEY: with the PubNub publish key mentioned above.
- YOUR_SUB_KEY: with the PubNub subscribe key mentioned above.
If you don’t, the UI will not be able to communicate with anything and probably clutter your console log with entirely too many errors.
For your convenience, this code is also available as a Gist on GitHub, and a Codepen as well.
Dependencies
First up, we have the JavaScript code & CSS dependencies of our application.
<!DOCTYPE html> <html> <head> <title>Angular 2</title> <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script> <script src="https://unpkg.com/zone.js@0.7.2/dist/zone.js"></script> <script src="https://unpkg.com/reflect-metadata@0.1.9/Reflect.js"></script> <script src="https://unpkg.com/rxjs@5.0.1/bundles/Rx.js"></script> <script src="https://unpkg.com/@angular/core/bundles/core.umd.js"></script> <script src="https://unpkg.com/@angular/common/bundles/common.umd.js"></script> <script src="https://unpkg.com/@angular/compiler/bundles/compiler.umd.js"></script> <script src="https://unpkg.com/@angular/platform-browser/bundles/platform-browser.umd.js"></script> <script src="https://unpkg.com/@angular/forms/bundles/forms.umd.js"></script> <script src="https://unpkg.com/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script> <script src="https://unpkg.com/pubnub@4.3.3/dist/web/pubnub.js"></script> <script src="https://unpkg.com/pubnub-angular2@1.0.0-beta.8/dist/pubnub-angular2.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" /> </head>
For folks who have done front-end implementation with Angular2 before, these should be the usual suspects:
- CoreJS ES6 Shim, Zone.JS, Metadata Reflection, and RxJS : Dependencies of Angular2.
- Angular2 : core, common, compiler, platform-browser, forms, and dynamic platform browser modules.
- PubNub JavaScript client: to connect to our data stream integration channel.
- PubNub Angular2 JavaScript client: provides PubNub services in Angular2 quite nicely indeed.
In addition, we bring in the CSS features:
- Bootstrap: in this app, we use it just for vanilla UI presentation.
Overall, we were pretty pleased that we could build a nifty UI with so few dependencies.
The User Interface
Here’s what we intend the UI to look like:
The UI is pretty straightforward – everything is inside a main-component
tag that is managed by a single component that we’ll set up in the Angular2 code.
<body> <main-component> Loading... </main-component>
Let’s skip forward and show that Angular2 component template. We provide a simple text input for a new user email to send to the PubNub channel as well as a button to perform the publish()
action.
<div class="container"> <pre> NOTE: make sure to update the PubNub keys below with your keys, and ensure that the BLOCK settings are configured properly! </pre> <h3>MyApp WorkFlow Integration</h3> <hr/> <p>Enter a new user email address:</p> <input type="text" [(ngModel)]="toSend" /> <button class="btn btn-primary" (click)="publish()">Go!</button> <br/> <br/> <ul> <li *ngFor="let item of messages.slice().reverse()"> {{item.message.stamplay_response.dt_create}} : NEW USER CREATED : {{item.message.email}} </li> </ul> </div>
The component UI consists of a simple list of messages. We iterate over the messages in the controller scope using a trusty ngFor
. Each message includes the original email attribute as well as the workflow webhook response.
And that’s it – a functioning realtime UI in just a handful of code (thanks, Angular2)!
The Angular2 Code
Now we’re ready to dive into the Angular2 code. It’s not a ton of JavaScript, so this should hopefully be pretty straightforward.
The first lines we encounter set up our application (with a necessary dependency on the PubNub AngularJS service) and a single component (which we dub main-component
).
<script> var app = window.app = {}; app.main_component = ng.core.Component({ selector: 'main-component', template: `...see previous...`
The component has a constructor that takes care of initializing the PubNub service, and configuring the channel name.
NOTE: make sure this matches the channel specified by your BLOCK configuration and the BLOCK itself!
}).Class({ constructor: [PubNubAngular, function(pubnubService){ var self = this; self.pubnubService = pubnubService; self.channelName = 'stamplay-event'; self.toSend = ''; pubnubService.init({ publishKey: 'YOUR_PUB_KEY', subscribeKey: 'YOUR_SUB_KEY', uuid: PubNub.generateUUID(), ssl:true });
We subscribe to the relevant channel and create a dynamic attribute for the messages collection.
pubnubService.subscribe({channels: [self.channelName], triggerEvents: true}); self.messages = pubnubService.getMessage(this.channelName,function(msg){ // no handler necessary, dynamic collection of msg objects }); }],
We also create a publish()
event handler that performs the action of publishing the new message to the PubNub channel and resetting the text input.
publish: function(){ if (this.toSend !== '') { this.pubnubService.publish({channel: this.channelName, message:{email:this.toSend}}); this.toSend = ''; } } });
Now that we have a new component, we can create a main module for the Angular2 app that uses it. This is pretty standard boilerplate that configures dependencies on the Browser and Forms modules and the PubNubAngular service.
app.main_module = ng.core.NgModule({ imports: [ng.platformBrowser.BrowserModule, ng.forms.FormsModule], declarations: [app.main_component], providers: [PubNubAngular], bootstrap: [app.main_component] }).Class({ constructor: function(){} });
Finally, we bind the application bootstrap initialization to the browser DOM content loaded event.
document.addEventListener('DOMContentLoaded', function(){ ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(app.main_module); });
We mustn’t forget close out the HTML tags accordingly.
}); </script> </body> </html>
Not too shabby for about 94 lines of HTML & JavaScript!
Additional Features
There are a couple other endpoints worth mentioning in the Stamplay API.
You can find detailed API documentation here.
- Users and Roles : additional use cases for privileged actions and access.
- Objects : detailed API bindings and data types.
- Custom Code : user-specified code for custom actions.
- Stripe : customer payments integration.
- And more!
All in all, we found it pretty easy to get started with workflow integration using the API, and we look forward to using more of the deeper integration features.