Protocol Thread Triggers
Another form of instant triggers are Protocol Threads.
A Protocol Thread trigger maintains an always-running thread on the server that will typically use an SDK that maintains a socket connection.
Protocol Thread triggers come in two variations:
- Unary Protocol Threads, where a given app will have a single thread that handles all inbound and outbound data for all automations. It is also possible for Unary Protocol Threads to respond to payloads delivered to a single webhook URL.
- Per-Trigger Protocol Threads, where each trigger will have its own thread. If 5 active automations use the trigger, 5 threads will be running on the server.
Two types of Unary Protocol Threads can be built:
- Freeform threads that send/receive data in any manner possible
- Webhook listeners that receive payloads delivered to a single URL
Jabber is an example of a freeform Unary Protocol Thread, where a SDK that wraps the XMPP protocol is used to send/receive messages to/from the server’s bot account.
Search for “Jabber” in the Assembly Editor catalog and load its Protocol Thread assembly:
Account information for the Jabber bot is stored in the keyvault. The Utility - Keyvault Value modules load the needed credentials from the keyvault and supply the value to the Java JSP code within the Unary Protocol Thread module.
The bottom section of Java JSP code within the Unary Protocol Thread module validates that the required server address and account are not empty in the keyvault.
If the supplied server address and username/password are not empty then the protocol thread is started in lines 187-192 above.
Note that this code imports the Smack Java library which handles XMPP communication for Jabber. Java libraries needed by protocol threads must be installed on the server in order to be used.
The protocol thread’s run() method should have an outer infinite loop with an inner try block:
Here the code is signing into the Jabber server and setting the bot’s presence to “available”.
The thread’s run() method is the listening for inbound messages. This section of code implements the callback receiver of messages:
After receiving the message, appJSP.handleReceivedUnaryProtocolPayload() is invoked which is the heart of any Unary Protocol Thread. This method is what routes data to active automations.
The mechanism by which the system knows which automations to invoke is the 3rd and 4th parameters. In this case, “jabber_account” is used to identify connected accounts in the system.
Open the Jabber app assembly and find this at the bottom:
So when a user connects a Jabber account their Jabber account id (for Jabber it is like an email address) is saved in the system’s database with the name “jabber_account”.
When the user builds automations having a Jabber trigger the account they selected will be associated with the automation. This is how appJSP.handleReceivedUnaryProtocolPayload() knows which automation(s) to invoke and deliver the payload.
The last parameter to appJSP.handleReceivedUnaryProtocolPayload() must be an XML string value consisting of the payload to send. In the case of the Jabber implementation, lines 67 and 69 above create a simple XML document to use as the payload. The Jabber triggers will receive this XML payload from the protocol thread.
Search for the Jabber “new chat by you (instant)” trigger in the Assembly Editor’s catalog and open it.
The Receive Unary Protocol Thread Payload module receives the XML payload and extracts data fields from it.
To initially build the trigger, the “dynamic trigger fields XML” value at the bottom of the Receive Unary Protocol Thread Payload module will be empty. Run the assembly in the Assembly Editor and this message appears:
The Receive Unary Protocol Thread Payload module is waiting to receive a payload.
You would send your bot a Jabber message. The waiting message will disappear when the payload has been received ok and the Receive Unary Protocol Thread Payload module will emit the parsed data fields.
That XML is then pasted into the “dynamic trigger fields XML” field at the bottom of the module to use as the default payload when the trigger is configured in the automation editor.
Your protocol thread must be running in order for it to receive data and send a payload to the waiting module.
Protocol threads are started from the Admin Console.
If your protocol thread emits payloads of varying schema, then you would leave the “dynamic trigger fields XML” field empty, check the “requires test transaction in automation editor” checkbox and provide instructions on how to send a payload when configuring the trigger.
Back to the end of the run() method in the Java JSP code:
The try block should break the outer while(true) infinite loop when an InterruptedException is received, meaning the system is asking the thread to be terminated.
All other exceptions are being logged via System.out.println().
Finally the Jabber connection is being disconnected when the thread terminates.
To send data, protocol threads must implement the sendUnaryProtocolPayload() method:
The method receives a single argument which is an XML payload. That payload comes from an action.
Search for the Jabber “send a chat” action in the Assembly Editor’s catalog and open it.
See that an XML document is constructed with the input values. This is the XML payload that is being sent to the protocol thread via the Send Unary Protocol Thread Payload module.
Back to the above code, observe that this XML payload is parsed and the Smack library is used to send the message via Jabber XMPP. Any errors that occur must be returned as a string error message from the sendUnaryProtocolPayload() method. The error message gets logged into the automation’s logs and may also emailed to the automation’s owner and system admin, depending on settings.
Some apps such as MINDBODY and Clover use a single webhook to send all data for all customers. This type of webhook can be supported with a Unary Protocol Thread.
Search for “Clover” in the Assembly Editor catalog and open the “Protocol Thread” assembly:
The URL for Unary Protocol Thread webhooks has the following structure:
Where “tenant_uuid” is the uuid of the tenant system. The tenant uuid is empty for the master system.
And where “app_assembly_uuid” is the uuid of the app assembly.
For Clover on APIANT’s server, the webhook URL is:
The bottom section of Java JSP code within the Unary Protocol Thread module just starts the protocol thread. Webhook protocol threads generally don’t need any other data.
The thread’s run() method needs to just keep the thread running:
When the system receives payloads to the webhook URL, the system invokes the handleReceivedWebhook() method:
The received payload depends on the sending system and may be JSON, XML, or some other format. In this case for Clover, JSON is received and the appJSP.json_to_xml() method is used to convert it to XML.
As with a non-webhook Unary Protocol Thread, the appJSP.handleReceivedUnaryProtocolPayload() method is used to send an XML payload to all active automations:
It is imperative that the webhook payload contain a piece of data that uniquely identifies the connected account. For Clover, their webhook payload contains a merchant ID.
The Clover app assembly obtains the merchant ID value during the OAuth workflow and checks to make sure the value exists when validating the connected account:
Webhook trigger assemblies are built in the same manner as described for freeform Unary Protocol Thread triggers, using the Receive Unary Protocol Thread Payload module. Usually the triggers will have to do filtering so that the triggers only process payloads of a specific type.
See the previous section on how to use the Receive Unary Protocol Thread Payload module to build webhook trigger assemblies.
When you run a Unary Protocol Thread assembly in the Assembly Editor, it doesn’t keep the thread running. It just runs for a second and then terminates, just as a way for the thread developer to perform a compilation check of the Java JSP code.
Unary Protocol Threads are started/stopped from the Admin Console’s Protocol Threads screen:
See the Admin Console's documentation for how to use this screen.
Per-trigger Protocol Threads are suitable when individual automations need to keep a connection to a source of data. An example is a message queue. They are built using the Trigger - Protocol Thread module in a trigger assembly:
This module can be thought of as a combination of the Webhook module and the Unary Protocol Thread module. For each active automation, the system will execute the Java JSP thread on the server. So if 5 automations are active using protocol thread triggers, 5 threads will be running.
The Java JSP code implementation is essentially the same as a Unary Protocol Thread. See the previous section on Unary Protocol Thread development for information on developing the Java JSP code.