Thursday, April 16, 2015

Liferay Inter Portlet Communication with Events

Inter Portlet Communication shortly we can call IPC is the way of making communication among different Portlets which are in same page or reside in other pages.

In the IPC mechanism Portlet will share data among the Portlets and Portlet will work based on the other Portlet.

JSR 168/Portlet 1.0 there is no better Inter Portlet Communication  later in JSR 286/ Portlet 2.0 have added capability of better Inter Portlet Communication with different ways.

IPC Events is one of the ways to make Inter Portlet Communication among the Portlets and these Portlets may be in same page or different pages in the portal.

IPC Events we have two categories of Portlets Event Producer Portlet and Event Listener Portlets. Producer Portlet will send some data or push some data then Listener Portlet will receive the data and will process subsequent steps.

We can have one Producer and Multiple Consumer Portlet will listen the event and process subsequent steps.

Producer Portlet is responsible for generate event when action is performed in it and what are respective Listener Portlets will listen the events that generated by producer Portlet and all these will be configured in the Portlets development that is who is producer and who are the consumers to listen the producer events.

Implement IPC Events

Assume we have Producer Portlet and Listener Portlets from Producer Portlet we will send user email address and send it to Listener Portlet once receiver Portlet get email address then it will show full details of user in the receiver Portlet.

The following are implementation steps

Step: 1

To make Inter Portlet Communication among all Portlets which are reside in same page or across the all the pages we need to update following portal property in portal-ext.properties file.


portlet.event.distribution=layout-set


Default value for portlet.event.distribution is layout and if we not updated this property then IPC will work among Portlets and which are in the same page

Previous versions of Liferay you may use following property


portlet.event.distribution=ALL_PORTLETS


Note:

As we know that portal-ext.properties file was in Liferay Home directory or we can Application Server Parent Directory.

Step: 2

We need to define event definition in the event producer Portlet of portlet.xml file. Portlet container will identify the event producers from this configuration.

Assume we have two Portlets Event Producer and Event Listener and assume Producer is responsible to generate event so we need to define Event publishing configuration in Event Producer Portlet of Portlet.xml file.

The following is configuration should be in portlet.xml file


<portlet-app>
------
<portlet>
<supported-publishing-event xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
</supported-publishing-event>
</portlet>
-------
<event-definition xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
<value-type>java.lang.String</value-type>
</event-definition>
-----
</portlet-app>


Note:

Please place the xml tags in right position

Step: 3

Now we need to generate event from Event producer Portlet so we need to generate it from processAction(--) method or our Custom Action Method and this value will be received by the Listener Portlet.

The following is sample code snippet in the “Custom Action Method”


public void getData(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException, SystemException {
String userEmailAddress = ParamUtil.getString(actionRequest,"userEmailAddress");
javax.xml.namespace.QName qName = new javax.xml.namespace.QName("http://www.liferaysavvy.com", "userEmailAddress", "event");
actionResponse.setEvent(qName,userEmailAddress);
}


Step: 4

We also need to define Event Processing configuration in Event Listener Portlet. The Definition we already done in the Event Producer Portlet same configurations need to be replicate in the Event Listener Portlet of portlet.xml file. All listener Portlets should have Event Processing configuration to listen events from event producer.

The following is configuration should be in portlet.xml file


<portlet-app>
------
<portlet>
<supported-processing-event xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
</supported-processing-event>
</portlet>
-------
<event-definition xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</event-definition>
-----
</portlet-app>


Note:

 Please place the xml tags in right position

Step: 5

Finally we need to listen the event in the Event Listener Portlet and here we will receive the values that were set in the Event Producer Portlet.

JSR 286 added new lifecycle method in the Portlet lifecycle that is processEvent(--) method which is used in IPC events implementation and this will  invoke only when IPC implemented among Portlets. We will use simple annotation to process event in the Portlet action class. We can use custom method name for process Event by simply use the @javax.portlet.ProcessEvent annotation.

The following is sample code to listen event in  Event Listent Portlet Action Class


@javax.portlet.ProcessEvent(qname = "{http://www.liferaysavvy.com}userEmailAddress")
public void handleProcesseuserEmailAddressEvent(javax.portlet.EventRequest request, javax.portlet.EventResponse response)
throws javax.portlet.PortletException, java.io.IOException {
javax.portlet.Event event = request.getEvent();
String userEmailAddress = (String)event.getValue();
response.setRenderParameter("userEmailAddress",userEmailAddress);

}


Finally we will render the value in the Portlet JSP page to display data .

Download IPC Event Portlets


Sender Portlet Screen


Receiver Portlet Screen


Inter Portlet Communication between Portlets in the page


Complete Code Example

Event Producer Portlet

Portlet.xml file (/IPCEventProducer-portlet/docroot/WEB-INF/portlet.xml)


<?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">

<portlet>
<portlet-name>IPCEventProducerPortlet</portlet-name>
<display-name>IPCEventProducerPortlet</display-name>
<portlet-class>
com.meera.liferay.ipc.events.IPCEventProducerPortletAction
</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/ipcevents/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>IPCEventProducerPortlet</title>
<short-title>IPCEventProducerPortlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
<supported-publishing-event xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
</supported-publishing-event>
</portlet>
<event-definition xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>


View.jsp (/IPCEventProducer-portlet/docroot/html/ipcevents/view.jsp)


<%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet"%>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme"%>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui"%>
<portlet:defineObjects />
<liferay-theme:defineObjects />
<portlet:actionURL var="sendDataActionURL" windowState="normal"
     name="getData">
</portlet:actionURL>
<h1>IPC Events Producer Portlet</h1>
<aui:form action="<%=sendDataActionURL%>" method="post" name="smsForm">
<aui:input name="userEmailAddress" id="userEmailAddress" label="User Email Address">
     <aui:validator name="required" />
     <aui:validator name="email"></aui:validator>
</aui:input>
<aui:button type="submit" value="Submit"></aui:button>
</aui:form>


Portlet Action Class (IPCEventProducerPortletAction.java)


package com.meera.liferay.ipc.events;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletSession;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class IPCEventProducerPortletAction extends MVCPortlet {

public void getData(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException, SystemException {
String userEmailAddress = ParamUtil.getString(actionRequest,"userEmailAddress");
javax.xml.namespace.QName qName = new javax.xml.namespace.QName("http://www.liferaysavvy.com", "userEmailAddress", "event");
actionResponse.setEvent(qName,userEmailAddress);
}
}


Event Listener Portlet

Portlet.xml (/IPCEventListener-portlet/docroot/WEB-INF/portlet.xml)


<?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<portlet>
<portlet-name>IPCEventListenerPortlet</portlet-name>
<display-name>IPCEventListenerPortlet</display-name>
<portlet-class>
com.meera.liferay.ipc.events.IPCEventListenerPortletAction</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/ipcevents/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>IPCEventListenerPortlet</title>
<short-title>IPCEventListenerPortlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
<supported-processing-event xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
</supported-processing-event>
</portlet>
<event-definition xmlns:event="http://www.liferaysavvy.com">
<qname>event:userEmailAddress</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>


View.jsp (/IPCEventListener-portlet/docroot/html/ipcevents/view.jsp)


<%@page import="javax.portlet.PortletSession"%>
<%@page import="com.liferay.portal.NoSuchUserException"%>
<%@page import="com.liferay.portal.service.UserLocalServiceUtil"%>
<%@page import="com.liferay.portal.model.User"%>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet"%>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme"%>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui"%>
<portlet:defineObjects />
<liferay-theme:defineObjects />
<h1>Receive User Data from Events Producer in Listener Portlet</h1>

<%
String message=null;
String userEmailAddress=ParamUtil.getString(renderRequest,
"userEmailAddress",null);
User senderPortletUserOject=null;
try{
if(userEmailAddress!=null){
senderPortletUserOject=
UserLocalServiceUtil.getUserByEmailAddress(themeDisplay.getCompanyId(), userEmailAddress);
}
}catch(NoSuchUserException e){
message="No User exists with the given Email Address.";
}catch(Exception e){
message="There is problem in view the user details.";
}

if(senderPortletUserOject!=null){
%>
<table border="1">
<tr>
<td>User Id</td>
<td><%=senderPortletUserOject.getUserId()%></td>
</tr>
<tr>
<td>First Name</td>
<td><%=senderPortletUserOject.getFirstName()%></td>
</tr>
<tr>
<td>Last Name</td>
<td><%=senderPortletUserOject.getLastName()%></td>
</tr>
<tr>
<td>Email Address</td>
<td><%=senderPortletUserOject.getEmailAddress()%></td>
</tr>
<tr>
<td>Screen Name</td>
<td><%=senderPortletUserOject.getScreenName()%></td>
</tr>
</table>

<%}else{%>
<%=message%>
<%}%>


Portlet Action Class (IPCEventListenerPortletAction.java)


package com.meera.liferay.ipc.events;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class IPCEventListenerPortletAction extends MVCPortlet {
@javax.portlet.ProcessEvent(qname = "{http://www.liferaysavvy.com}userEmailAddress")
public void handleProcesseuserEmailAddressEvent(javax.portlet.EventRequest request, javax.portlet.EventResponse response)
throws javax.portlet.PortletException, java.io.IOException {
javax.portlet.Event event = request.getEvent();
String userEmailAddress = (String)event.getValue();
response.setRenderParameter("userEmailAddress",userEmailAddress);

}
}



Popular Posts

Recent Posts

Recent Posts Widget