The WSO2 Gadget Server supports inter-gadget communication with the help of publisher and subscriber gadgets allowing gadgets to communicate with each other while running in the Portal. Let's investigate the messaging paradigm known as Publisher/Subscriber (pub/sub) and how the WSO2 Gadget Server uses it to facilitate communication between Gadgets originating from any source.
To follow this tutorial, you are advised to be familiar with the WSO2 Gadget Server and writing Google Gadgets using the Gadgets API. You can find relevant tutorials in the Gadget Server Knowledge Base.
Google Gadgets are a nice way to develop user interfaces for distributed services. The fact that they can be hosted anywhere over a network, not necessarily in the very portal server they eventually run in makes them re-usable and allows users to quickly assemble sets of Gadgets as and when required to create a unified view. This is especially useful in enterprise scenarios where the IT department maintains a central Gadget Repository using the WSO2 Gadget Server and end-users use these Gadgets in a layout most productive for their tasks. They can also supplement these enterprise Gadgets with other useful ones found in public Gadget Containers such as iGoogle.
A common requirement encountered by Gadget developers, especially when trying to satisfy Business Intelligence needs of an enterprise, is the ability for a set of Gadgets to work as a team. For instance, when the user changes an input parameter in one Gadget, a set of others should respond to the change by displaying matching data or graphs. To implement such requirements, Gadgets should be able to communicate with each other.
This tutorial explains the pub/sub based communication mechanism exposed by the WSO2 Gadget Server to Gadget developers.
What is pub/sub?
Publisher/Subscriber (or pub/sub) is a messaging paradigm where a sender (or a Publisher) sends messages without specifically targeting one receiver. A receiver (or a Subscriber) declares interest in one or more messages published by a publisher or a set of publishers. Keeping track of publishers, subscribers and their subscriptions is done by a Message Broker. In addition to keeping track of publishers and their subscribers, the Message Broker will also take responsibility of routing messages, commonly by utilising a store-and-forward mechanism. In the context of the WSO2 Gadget Server these roles are as follows:
- Publisher - Any Gadget importing the "pubsub" feature and publishing to a one or more named Channels
- Subscriber - Any Gadget importing the "pubsub" feature and subscribing to one or more named Channels
- Message Broker - The WSO2 Gadget Server
How Does it work?
The way Gadgets communicate their interest to either publish or subscribe to a Channel is via the gadgets.pubsub.* API. In order to load the necessary API fragments for the Gadget to function you need to import the feature titled "pubsub". This can be declared in the ModulePrefs section of your Gadget.
Adding <Require feature="pubsub"/> will work for both Publisher and Subscriber scenarios.
A Publisher Gadget
Here, "random-number" is the name of the Channel to publish what is contained in the variable "message".
A Subscriber Gadget
A sample Subscriber Gadget is given below.
As you can see in the above code, a Subscriber can unsubscribe using the method call gadgets.pubsub.unsubscribe("random-number");
A real world scenario with code
Let's have a look at a simple, real world use case for this technology. We ship two search Gadgets with the WSO2 Gadget Server downloadable distribution, which search e-bay and Amazon for a given query respectively. What if we can provide a third Gadget that takes the query from a user and publishes that query so that both e-bay and Amazon gadgets can simultaneously do searches? Instead of entering the search query twice, the user will now enter it in a single "data gatherer" Gadget.
The same pattern can be used in Gadgets displaying graphs and charts, where one Gadget acts as the input gatherer for others displaying data. So when a user changes data in the input gathering Gadget, the whole view changes to match the new inputs.
Our Query Publisher Gadget
The code for the Publisher is given below. It's a slight modification to the sample Publisher Gadget we've looked at earlier. This Gadget takes the user input via a text box and publishes the value to the channel named "search-query".
Our Subscriber Gadgets
These Gadgets are the one already shipped with WSO2 Gadget Server, slightly modified to handle channel messages as well. The first change I did was to add a callback function to be invoked when a message is received as listed below.
The above callback function uses the message string to populate the text box in the search Form found in e-bay and Amazon Gadgets and then calls the "search(form);" method, which does its usual task.
The next change is to add a "subscribe" function and register it to be executed at Gadget load. This will ensure that the Gadget is subscribed automatically to the "search-query" channel when it's loaded in the portal.
Registering as an on-load handler to our "subscrib" can be done as follows.
Adding and Testing the Gadgets
Now we can add these three Gadgets to the portal. As usual you can either store them in the Registry of WSO2 Gadget Server or in any HTTP server in your network. Once you have added these to your portal page, type a query to the Publisher Gadget and you will see both e-bay and Amazon Gadgets pick your input up and display their respective results as shown below.
Best Practices and Security
Several best practices need to be noted. First, since Channel names are not restricted by the container and are not tracked, it's better to stick follow a naming convention. For instance, the above "search-query" Channel name can be renamed to "org.wso2.gadgets.channels.searchquery". This will prevent Gadgets from accidentally publishing or subscribing Channels, which brings us to the second best practice considering security.
Since these Channels are public and easily discoverable by looking at the code inside a gadget.xml, sensitive data should not be published using the pub/sub mechanism. Sharing such information should happen in the back end with proper authentication and authorisation procedures in place. It's also possible to have a back end service generate a random channel name for each session and allow the gadgets to retrieve this name for that session. Although this may seem like an extreme scenario, if channel privacy is of utmost importance, this can be considered as a workaround.
In this tutorial we had a brief look at the inner workings of a typical publisher/subscriber mechanism and how it's used in the WSO2 Gadget Server to facilitate inter Gadget communication. We had a look at how the gadget.pubsub.* API is used to establish a channel in order to pass messages. The functionality is used to implement a simple, practical scenario where a set of search Gadgets provid a user a single point of entry for a search query. Best practices and security are discussed to ensure safe usage of this feature in development.