Inter Portlet Subscription/Notification Mechanism (Client side)
How to make portlets in the same page use a Subscription/Notification Mechanism client side.
Contents
Pre-development Actions
Subscription/Notification Mechanism makes use of TIBCO PageBus™ (http://www.tibco.com/devnet/pagebus/default.jsp) which is an event and message bus implemented in JavaScript that enables disparate Ajax elements in a Web page to broadcast and listen for events and messages published on topic names.
For the ones developing portlets with GWT Wrapper exists for this Library, http://code.google.com/p/tibcopagebus4gwt/
How does PageBus work?
PageBus uses publish and subscribe APIs to send events and messages between components rather than get bogged down in point to point integrations between components that lead to unwieldy and less manageable code.
This diagram shows three Ajax widgets communicating with each other via the PageBus. Each widget has a file defining its visuals, a file controlling its behavior including the publish and subscribe calls to the PageBus, and a file that gets data from a service on the Web.
How to use PageBus GWT Wrapper with gCube Portlets
Step 1st: Download the latest jars from ETICS. The '.gwt-jsonmaker.jar' and the 'tibcopagebus4gwt.jar'
Step 2nd: add the two jar files in the build path of your GWT application
Once they two jar files are in the build path edit your GWT Application configuration file (file.gwt.xml). Add the following:
<module> ... <inherits name="net.eliasbalasis.tibcopagebus4gwt.tibcopagebus4gwt" /> <inherits name="org.jsonmaker.gwt.Gwt_jsonmaker" /> ... ... ... </module>
Set up your D4Science Portlet to use tibcopagebus4gwt GWT Wrapper
Copy the file pagebus.js, which can be downloaded from here here to your portlet war/js folder e.g. <myportletproject>/war/js/pagebus.js
Now you need now to add a little modification to the Liferay Portlet header, the file is located under: <myportletproject>/war/WEB-INF/liferay-portlet.xml
add the following under the portlet element
<portlet>
...... <header-portlet-javascript>/js/pagebus.js</header-portlet-javascript> .....
</portlet>
now you just need to copy the following into the <head> of your jsp page loading your portlet.
<script type="text/javascript"> if(window.parent.PageBus) { window.PageBus = window.parent.PageBus; } </script>
You are ready to use tibcopagebus4gwt.
How to use tibcopagebus4gwt GWT Wrapper with D4Science Portlets
The main class you are going to use is the PageBusAdapter class which is included in the 'tibcopagebus4gwt.jar'
Assume now that Portlets containing GWT modules desire to communicate with the rest of the Portlets on the page. This is a task for PageBusAdapter which exposes PageBus functions as a GWT widget. Assume that the information to be communicated is represented with the following Java classes:
package org.gcube.portltes...; ... // a Person bean class. class Person { ... public String getName(){...} public void setName(String name){...} ... public int getAge(){...} public void setAge(int age){...} ... } class SubscriberData { ... public String getHeader(){...} public void setHeader(String header){...} ... public String getBody(){...} public void setBody(String header){...} ... }
as part of the publish and subscribe calls to the PageBus. Not only Person beans must be translated to JavaScript objects before being passed around to PageBus but also JavaScripts objects passed through PageBus by other widgets must be translated to Person beans before the GWT module can use them.
PageBusAdapter makes uses marshaller implementations created using the the gwt-jsonizer library to perform the translation. Here is the gwt-jsonizer marshaller implementation for the Person bean.
interface PersonJsonizer extends Jsonizer{} interface SubscriberDataJsonizer extends Jsonizer{}
Now you may wonder where is the marshalling/unmarshalling code? It is automatically created by the gwt-jsonizer GWT compiler hook the first time a bean class is accessed. The requirements of the gwt-jsonizer marshaller are:
- The bean must be compliant with Java Beans specification (getters, setters, default constructors etc.)
- The bean marshaller definition must be named after the respective bean class name with the Jsonizer suffix
- Each and every bean property must contain a hint to the marshaller in the form of javadoc annotations.
- The following annotations are currently supported:
- jsonizer.transient The property in not translatable
- jsonizer.propName 'prop' This property is named 'prop' in JavaScript
- jsonizer.required If the property doesn't exist in respetive JavaScript version an exception will be thrown
- The following annotations are currently supported:
Here is how a GWT module using PageBus functions would send notification (publishing beans to subscribers)
package ...; import org.gcube.portlets......myapplication; ... public class MyGWTModule { final PageBusAdapter pageBusAdapter = new PageBusAdapter(); ... ... //create the Person bean data Person person = new Person(); person.setName("Mario Rossi"); person.setAge(29); ... // publish a message with Person bean data pageBusAdapter.PageBusPublish("net.eliasbalasis.tibcopagebus4gwt.testsubscriber.client.Person", person, (Jsonizer)GWT.create(PersonJsonizer.class)); ...
Here is how a GWT module using PageBus functions would Subscribe to message and associate subsequent receptions with custom subscriber data
package ...; import org.gcube.portlets......myapplication; ... public class MyGWTModule { final PageBusAdapter pageBusAdapter = new PageBusAdapter(); SubscriberData subscriberData = new SubscriberData(); subscriberData.setHeader("myHeader"); subscriberData.setBody("myHeader"); //Subscribe to message and associate subsequent receptions with custom subscriber data pageBusAdapter.PageBusSubscribe("net.eliasbalasis.tibcopagebus4gwt.testsubscriber.client.Person", null, null, subscriberData, (Jsonizer)GWT.create(SubscriberDataJsonizer.class)); // register listener pageBusAdapter.addPageBusSubscriptionCallbackListener( new PageBusListener() { public void onPageBusSubscriptionCallback(PageBusEvent event) { // translate JavaScript message contents and subscriber data to their Java equivalents Person message = (Person)event.getMessage((Jsonizer)GWT.create(PersonJsonizer.class)); SubscriberData subscriberData = (SubscriberData)event.getSubscriberData((Jsonizer)GWT.create(SubscriberDataJsonizer.class)); ... ... ... } } );
Here is how a GWT module using PageBus functions would UnSubscribe to message
... ... //unsubscribe from message. future publications of message will not trigger callback pageBusAdapter.PageBusUnsubscribe("net.eliasbalasis.tibcopagebus4gwt.testsubscriber.client.Person"); ... ...