Vaadin IPC for Liferay

    The Vaadin IPC for Liferay Add-on takes another approach by communicating between the portlets through the client-side. Events (messages) are sent through the LiferayIPC component and the client-side widget relays them to the other portlets, as illustrated in Vaadin IPC for Liferay Architecture.

    Vaadin IPC for Liferay Architecture

    Vaadin IPC for Liferay uses the Liferay JavaScript event API for client-side inter-portlet communication, so you can communicate just as easily with other Liferay portlets.

    Notice that you can use this communication only between portlets on the same page.

    shows Vaadin IPC for Liferay in action. Entering a new item in one portlet is updated interactively in the other.

    liferay ipc demo annotated lo

    Vaadin IPC Add-on Demo with Two Portlets

    The Vaadin IPC for Liferay add-on is available from the Vaadin Directory as well as from a Maven repository. To download the installation package or find out the Maven or Ivy dependency, see the add-on page at Vaadin Directory, and install the add-on as described in .

    The contents of the installation package are as follows:

    vaadin-ipc-for-liferay-x.x.x.jar

    The add-on JAR in the installation package must be installed in the WEB-INF/lib directory under the root context. The location depends on the server - for example in Liferay running in Tomcat it is located under the webapps/ROOT folder of the server.

    The documentation folder includes a README.TXT file that describes the contents of the installation package briefly, and licensing.txt and license-asl-2.0.txt, which describe the licensing under the Apache License 2.0. Under the doc/api folder is included the complete JavaDoc API documentation for the add-on.

    vaadin-ipc-for-liferay-x.x.x-demo.war

    A WAR containing demo portlets. After installing the add-on library and compiling the widget set, as described below, you can deploy the WAR to Liferay and add the two demo portlets to a page, as shown in Vaadin IPC Add-on Demo with Two Portlets. The source of the demo is available at .

    The add-on contains a widget set, which you must compile into the Vaadin widget set installed in the portal.

    Basic Communication

    LiferayIPC is an invisible user interface component that can be used to send messages between two or more Vaadin portlets. You add it to an application layout as you would any regular user interface component.

    You should be careful not to remove the invisible component from the portlet later if you modify the layout of the portlet.

    The component can be used both for sending and receiving messages, as described next.

    You can send an event (a message) with the sendEvent() method, which takes an event ID and the message data as parameters. The event is broadcast to all listening portlets. The event ID is a string that can be used to identify the recipient of an event or the event type.

    If you need to send more complex data, you need to format or serialize it to a string representation as described in .

    A portlet wishing to receive events (messages) from other portlets needs to register a listener in the component with addListener(). The listener receives the messages in a LiferayIPCEvent object. Filtering events by the ID is built in into the listener handler, you give the listened event ID as the first parameter for the addListener(). The actual message data is held in the data property, which you can read with getData().

    1. liferayipc.addListener("hello", new LiferayIPCEventListener() {
    2. public void eventReceived(LiferayIPCEvent event) {
    3. // Do something with the message data
    4. String data = event.getData();
    5. Notification.show("Received hello: " + data);
    6. }
    7. });

    A listener added to a LiferayIPC can be removed with removeListener().

    Both security and efficiency should be considered with inter-portlet communications when using the Vaadin IPC for Liferay.

    Sending data through the browser requires loading and sending it in HTTP requests. The data is held in the memory space of the browser, and handling large data in the client-side JavaScript code can take time. Noticeably large message data can therefore reduce the responsiveness of the application and could, in extreme cases, go over browser limits for memory consumption or JavaScript execution time.

    Communication Through Session Attributes

    In many cases, such as when considering security or efficiency, it is better to pass the bulk data on the server-side and use the client-side IPC only for notifying the other portlet(s) that the data is available. Session attributes are a conveninent way of sharing data on the server-side. You can also share objects through them, not just strings.

    The session variables have a scope, which should be APPLICATION_SCOPE. The “application” refers to the scope of the Java web application (WAR) that contains the portlets.

    If the communicating portlets are in the same Java web application (WAR), no special configuration is needed. You can also communicate between portlets in different WARs, in which case you need to disable the private-session-attributes parameter in liferay-portlet.xml by setting it to false. Please see Liferay documentation for more information regarding the configuration.

    You can also share Java objects between the portlets in the same WAR, not just strings. If the portlets are in different WARs, they normally have different class loaders, which could cause incompatibilities, so you can only communicate with strings and any object data needs to be serialized.

    Session attributes are accessible through the PortletSession object, which you can access through the portlet context from the Vaadin Application class.

    You can then receive the attribute in a LiferayIPCEventListener as follows:

    1. public void eventReceived(LiferayIPCEvent event) {
    2. String key = event.getData();
    3. PortletSession session =
    4. ((PortletApplicationContext2)getContext()).
    5. // Get the object reference
    6. Person person = (Person) session.getAttribute(key);
    7. // We can now use the object in our application
    8. BeanItem<Person> item = new BeanItem<Person> (person);
    9. }

    Notice that changes to a shared object bound to a user interface component are not updated automatically if it is changed in another portlet. The issue is the same as with double-binding in general.

    The IPC events support transmitting only plain strings, so if you have object or other non-string data, you need to format or serialize it to a string representation. For example, the demo application formats the trivial data model as a semicolon-separated list as follows:

    1. private void sendPersonViaClient(String firstName,
    2. String lastName, int age) {
    3. liferayIPC_1.sendEvent("newPerson", firstName + ";" +
    4. lastName + ";" + age);
    5. }

    You can use standard Java serialization for any classes that implement the Serializable interface. The transmitted data may not include any control characters, so you also need to encode the string, for example by using Base64 encoding.

    You can then deserialize such a message at the receiving end as follows:

    1. public void eventReceived(LiferayIPCEvent event) {
    2. String encoded = event.getData();
    3. // Decode and deserialize it
    4. BASE64Decoder decoder = new BASE64Decoder();
    5. try {
    6. byte[] data = decoder.decodeBuffer(encoded);
    7. ObjectInputStream ois =
    8. new ObjectInputStream(
    9. new ByteArrayInputStream(data));
    10. // The deserialized bean
    11. MyBean deserialized = (MyBean) ois.readObject();
    12. ... do something with the bean ...
    13. } catch (IOException e) {
    14. e.printStackTrace(); // Handle somehow
    15. } catch (ClassNotFoundException e) {
    16. e.printStackTrace(); // Handle somehow
    17. }
    18. }

    Communicating with Non-Vaadin Portlets

    You can use the Vaadin IPC for Liferay to communicate also between a Vaadin application and other portlets, such as JSP portlets. The add-on passes the events as regular Liferay JavaScript events. The demo WAR includes two JSP portlets that demonstrate the communication.

    1. <%@ taglib uri="http://java.sun.com/portlet_2_0"
    2. prefix="portlet" %>
    3. <portlet:defineObjects />
    4. <script>
    5. function send_message() {
    6. Liferay.fire('hello', "Hello, I'm here!");
    7. }
    8. </script>

    You can receive events using a Liferay JavaScript event handler. You define the handler with the on() method in the Liferay object. It takes the event ID and a callback function as its parameters. Again in JSP you could have: