Thursday, April 9, 2015

Interportlet Communication(Portlet to Portlet Communication)


Inter portlet communication is the way of setup communication between two portlets and sharing data with each other using IPC mechanism.
This concept is supported in Porlet 2.0 JSR-286 specification.

There are three ways to share data between two portlets:

1. Portlet session
2. IPC Mechanism
   i>Public Render Parameters
   ii>Event
   iii>Client-side IPC
3. Cookies


*In all three no. 2(IPC Mechanism) is the standard way of interacting/sharing data between portlets as
it is defined by JSR-286 specification.


I>PUBLIC RENDER PARAMETER

  -------------------------------------------


1>Create one portlet project with any name, in my case it is InterportletCommunication
2>Inside that project create two portlets with any name of your choice, in my case portets are i>Sender ii>Receiver

3>In portlet.xml define public render parameter after portlets definition and before </portlet-app> tag.

<public-render-parameter>
    <identifier>TestParamter</identifier>
    <qname xmlns:x="http://liferay.com">x:TestParamter</qname>
</public-render-parameter>

*Here in public render parameter definition we are defining one identifier, by using this identifier portlets are sharing data.
In our case identifier is  "TestParamter"

4> In portlet.xml define which will support this public render parameter before </portlet> tag of both portlets sender and receiver using

<supported-public-render-parameter>
    TestParamter
</supported-public-render-parameter>

For our reference below is complete 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>sender</portlet-name>
        <display-name>Sender</display-name>
        <portlet-class>com.test.Sender</portlet-class>
        <init-param>
            <name>view-template</name>
            <value>/html/sender/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>Sender</title>
            <short-title>Sender</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-public-render-parameter>
          TestParamter
       </supported-public-render-parameter>
    </portlet>
    <portlet>
        <portlet-name>receiver</portlet-name>
        <display-name>Receiver</display-name>
        <portlet-class>com.test.Receiver</portlet-class>
        <init-param>
            <name>view-template</name>
            <value>/html/receiver/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>Receiver</title>
            <short-title>Receiver</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-public-render-parameter>
          TestParamter
       </supported-public-render-parameter>
    </portlet>
   
<public-render-parameter>
    <identifier>TestParamter</identifier>
    <qname xmlns:x="http://liferay.com">x:TestParamter</qname>
</public-render-parameter>

</portlet-app>



5> For setting value for the render parameter, In sender portlet view.jsp use below code.

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">This is Sender portlet, this will send/share parameter value with Receiver Portlet.</p>


<portlet:actionURL var="actionURL" name="setRenderParameter"/>

<aui:form action="<%=actionURL.toString() %>" method="post">
    <aui:input name="name" value=""/>
    <aui:button type="submit" value="Set"/>
</aui:form>

6> In sender portlet java class, Sender.java paste below code.

package com.test;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;

import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;

/**
 * Portlet implementation class Sender
 */
public class Sender extends MVCPortlet {

   
    public void processAction(ActionRequest actionRequest,
            ActionResponse actionResponse) throws IOException, PortletException {
   
         String sendingParameter = ParamUtil.getString(actionRequest, "sendingParameter");
            /**
             * sendingParameter is same as like normal parameter. But it is configured
             * as public portlet.xml file
             * Any other portlet can read this parameter
             *
             * To read this parameter in your portlet you
             * should tell your portlet that you are going to
             * use public render parameter. That configuration is done again in
             * portlet.xml
             */
            actionResponse.setRenderParameter("TestParamter", sendingParameter);
    }

}

7>For reading public render parameter, In receiver portlet view.jsp paste below code.

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">This is Receiver Portlet, this will receive parameter value send/share by sender portlet.</p>


<%
String receivedParameter = ParamUtil.getString(request, "TestParamter");
%>

<p style="color:green;">Public parameter received is 'TestParamter'</p>
Its value is
<%=receivedParameter %>

8> i. For testing public render parameter between two portlets, portlets placed on same page.

   ii>For testing public render parameter between two portlets, portlets placed on different pages.

      *For different pages we have to use below property in portal-ext.properties with given value.
    
      portlet.public.render.parameter.distribution=layout-set
      layout.default.p_l_reset=false



----------------------*****************-------------------******************------------------********************-------------------------     


II> EVENT BASED IPC(Inter portlet communication using Event)

    --------------------------------------------------------

Create one liferay plugin project with any name as per your requirement naming convention, in my case i have given
InterportletCommunication after this create two portlet, in my case i have given name as follows sender and receiver.


1> Define Event definition in portlet.xml before </portlet-app> tag ends.

 <event-definition xmlns:x='http://liferay.com'>
  <qname>x:sharingValues</qname>
  <value-type>java.lang.String</value-type>
 </event-definition>

*qname represents qualified name and in value-type tag we are giving what type of object it is, in this case it is String object.

2> Define supported publishing event in portlet.xml for sender portlet before </portlet>

<supported-publishing-event xmlns:x='http://liferay.com'>
            <qname>x:sharingValues</qname>
</supported-publishing-event>

3> Define supported processing event in portlet.xml for receiver portlet before </portlet>
 
<supported-processing-event xmlns:x='http://liferay.com'>
              <qname>x:sharingValues</qname>
</supported-processing-event>

4> Paste below code in sender portlet view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">This is Sender portlet, this will send/share parameter value with Receiver Portlet.</p>


<portlet:actionURL var="publishEventUrl" name="publishEvent"/>

<aui:form method="post" action="<%=publishEventUrl.toString() %>">
    <aui:input name="publishText" value="" label="Publish Text"/>
    <aui:button type="submit" value="Send"/>
</aui:form>

5>  paste below code in sender portlet java class  Sender.java

package com.test;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.xml.namespace.QName;

import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;

/**
 * Portlet implementation class Sender
 */
public class Sender extends MVCPortlet {

   
    public void publishEvent(ActionRequest actionRequest,
            ActionResponse actionResponse) throws IOException, PortletException {
   
         String publishText = ParamUtil.getString(actionRequest, "publishText");
        
         System.out.println("value got from sender jsp:::"+publishText);
         //NOTE: creating qname object please keep in my mind to import  "import javax.xml.namespace.QName;"
            QName qName = new QName("http://liferay.com", "sharingValues");
            actionResponse.setEvent(qName, publishText);
    }

}

6> paste below code in receiver portlet java class Receiver.java
package com.test;

import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.ProcessEvent;

import com.liferay.util.bridges.mvc.MVCPortlet;

/**
 * Portlet implementation class Receiver
 */
public class Receiver extends MVCPortlet {


       @ProcessEvent(qname = "{http://liferay.com}sharingValues")
        public void myEvent(EventRequest request, EventResponse response) {
          
           //NOTE: Creating Event object please keep in mind importing  "javax.portlet.Event;"
            Event event = request.getEvent();
            //Get data from the event
            String valueReceived = (String) event.getValue();
           
            System.out.println("value got in receiver portlet:::"+valueReceived);
        
            response.setRenderParameter("sharingValues", valueReceived);
        }
   
}


7>Paste below code in receiver portlet view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">This is Receiver Portlet, this will receive parameter value send/share by sender portlet.</p>


<%
    String finalValueReceived = (String) renderRequest.getParameter("sharingValues");
%>

<p style="color:green;">Value received from sender portlet:</p><%=finalValueReceived%>


------------------------------**************-----------------------------****************-----------------***********------------------------

III> Inter-portlet communication using Portlet Session

     -------------------------------------------------

By default each WAR has it's own session and will not shared with other WARs.

Inside any JSP of a Portlet, the “portletSession” is available as an implicit object and is injected by the tag
“<portlet:defineObjects/>”. Inside the Portlet class the object is retrieved from the portletRequest object


The PortletSession interface defines two scopes for storing objects:
*APPLICATION_SCOPE
*PORTLET_SCOPE
By default it is set with “PORTLET_SCOPE”


For sharing between two portlets in two different WAR's

-------------------------------------------------------

Create two different liferay plugin project name as per your requirement, in our case it's Ipc1 and Ipc2, and the portlets are PortletSessionTesting1 inside Ipc1 plugin
project and PortletSessionTesting2 inside Ipc2 plugin project.

Steps:

1> Add below property in the liferay-portlet.xml of both portlet who will share and receive, in our case add in  PortletSessionTesting1  and
PortletSessionTesting2 liferay-portlet.xml after <icon> tag.

    <private-session-attributes>false</private-session-attributes>

     *Use APPLICATION_SCOPE for different WAR.


2> Paste below code in PortletSessionTesting1  view.jsp of Ipc1 WAR.



<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />

<p style="border:1px solid green;">Sender Portlet</p>


<%
portletSession = renderRequest.getPortletSession();
portletSession.setAttribute("attribute-name", "Md Azharuddin", portletSession.APPLICATION_SCOPE);

// or

 /* PortletSession sessions = renderRequest.getPortletSession();
sessions.setAttribute("attribute-name","Md. Azharuddin", PortletSession.APPLICATION_SCOPE);  */

%>

3> Paste below code in PortletSessionTesting2 view.jsp of Ipc2 WAR.

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />


<p style="border:1px solid green;">Receiver Portlet</p>

<%
portletSession = renderRequest.getPortletSession();
String attributeValue = (String) portletSession.getAttribute("attribute-name", portletSession.APPLICATION_SCOPE);

// or

/*
PortletSession sessions = renderRequest.getPortletSession();
String attributeValue = (String) sessions.getAttribute("attribute-name", PortletSession.APPLICATION_SCOPE);
 */
%>
My Name: <%=attributeValue%>



For sharing between two portlets in same  WAR's(Liferay plugin project)

-----------------------------------------------------------------------

Create one liferay plugin project name as per your requirement, in our case it's Ipc, and the portlets are Sender and Receiver in Ipc plugin
project.


1>Paste  below code in Sender portlet jsp view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />

<p style="border:1px solid green;">Sender Portlet</p>


<%
portletSession = renderRequest.getPortletSession();
portletSession.setAttribute("attribute-name", "Md Azharuddin", portletSession.APPLICATION_SCOPE);

// or

 /* PortletSession sessions = renderRequest.getPortletSession();
sessions.setAttribute("attribute-name","Md. Azharuddin", PortletSession.APPLICATION_SCOPE);  */

%>


3> Paste below code in Receiver portlet jsp   view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />


<p style="border:1px solid green;">Receiver Portlet</p>

<%
portletSession = renderRequest.getPortletSession();
String attributeValue = (String) portletSession.getAttribute("attribute-name", portletSession.APPLICATION_SCOPE);

// or

/*
PortletSession sessions = renderRequest.getPortletSession();
String attributeValue = (String) sessions.getAttribute("attribute-name", PortletSession.APPLICATION_SCOPE);
 */
%>
My Name: <%=attributeValue%>


For sharing between one portlet in same  WAR's(Liferay plugin project)
-----------------------------------------------------------------------
*In same war with inside one portlet sharing we can use  PORTLET_SCOPE as well as APPLICATION_SCOPE.

Create one liferay plugin project name as per your requirement, in our case it's Ipc, and the portlet is SenderReceiver in Ipc plugin
project.

1>Paste below code SenderReceiver portlet view.jsp

<%@page import="javax.portlet.PortletURL"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />

<p style="border:1px solid green;">SenderReceiver Portlet</p>

<%
PortletURL renderToReceiverPage = renderResponse.createRenderURL();
renderToReceiverPage.setParameter("jspPage", "/html/senderreceiver/Receiver.jsp");


portletSession = renderRequest.getPortletSession();
portletSession.setAttribute("attribute-name", "Rehan hayat", portletSession.PORTLET_SCOPE);

// or

 /* PortletSession sessions = renderRequest.getPortletSession();
sessions.setAttribute("attribute-name","Md. Azharuddin", PortletSession.PORTLET_SCOPE);  */

%>

<a href="<%=renderToReceiverPage.toString()%>">Redirect To Receiver Page</a>

2> paste below code in SenderReceiver portlet Receiver.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />

<p style="border:1px solid green;">SenderReceiver Portlet</p>

<p style="border:1px solid green;">Receiver page</p>


<%
portletSession = renderRequest.getPortletSession();
String attributeValue = (String) portletSession.getAttribute("attribute-name", portletSession.PORTLET_SCOPE);

// or

/*
PortletSession sessions = renderRequest.getPortletSession();
String attributeValue = (String) sessions.getAttribute("attribute-name", PortletSession.PORTLET_SCOPE);
 */
%>
My Name: <%=attributeValue%>

-----------------******************----------------------********************-----------------*******************----------------------------

 IV> Client Side InterportletCommunication (IPC)

     -------------------------------------------

Steps:

1>Create one portlet project with any name, in my case it is InterportletCommunication
2>Inside that project create two portlets with any name of your choice, in my case portets are i>Sender ii>Receiver

3>Paste below code in Sender portlet view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">Sender Portlet.</p>


<aui:form name="sendingDataForm">
  <aui:input label="Name" name="name"/>
  <aui:button value="Send Data" onClick="javascript:sendingDataFromSenderPortlet();"/>
</aui:form>

 <script>
 function sendingDataFromSenderPortlet() {
   var frm = document.<portlet:namespace/>sendingDataForm;
   var data = frm.<portlet:namespace/>name.value;
   var payload = {receivedData : data}; Liferay.fire("sendingDataFromSenderPortletEvent", payload);
}
</script>

4>  paste below code in Receiver portlet view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<portlet:defineObjects />

<p style="color: green; border: 1px solid green;">Receiver portlet.</p>


<aui:script>
AUI().ready(function(A){
    Liferay.on("sendingDataFromSenderPortletEvent", function(payload){
        alert('Receiving Portlet:' + payload.receivedData);
        });
    });
</aui:script>




0 comments:

Post a Comment