Inter-Portlet Communication in Liferay 7.4

 

Inter-Portlet Communication lets one portlet on a page notify another portlet of something that happened — a selection, a form submission, a filter change — without a full page reload. In the JSR-286/JSR-362 portlet specification (which Liferay implements), the standard mechanism is Portlet Events, and each portlet is deployed as its own independent OSGi bundle/component.

1.1 Scenario

Two portlets on the same page:

  • Sender Portlet — a simple form where the user types a message and clicks "Send".

  • Receiver Portlet — displays the latest message it has received, with no page refresh needed.

The Sender publishes an event; the Receiver declares that it processes that event. Liferay's OSGi-based Portlet Container wires the two together at the page level — the portlets never reference each other directly, keeping them independently deployable OSGi bundles.

First create Sender Portlet: below command to create Sender Portlet

blade create -t mvc-portlet -p com.ipc.demo -c SenderPortlet Sender-Portlet


1.2 Sender Portlet (OSGi Component) Go to your send class and update based on below code which one is required

package com.ipc.demo.portlet;


import com.ipc.demo.constants.SenderPortletKeys;


import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;

import com.liferay.portal.kernel.util.ParamUtil;


import java.io.IOException;


import javax.portlet.ActionRequest;

import javax.portlet.ActionResponse;

import javax.portlet.Portlet;

import javax.portlet.PortletException;

import javax.portlet.ProcessAction;

import javax.xml.namespace.QName;



import org.osgi.service.component.annotations.Component;


/**

* @author Admin

*/

@Component(

property = {

"com.liferay.portlet.display-category=category.ipc-demo",

"com.liferay.portlet.header-portlet-css=/css/main.css",

"com.liferay.portlet.instanceable=true",

"javax.portlet.display-name=Sender",

"javax.portlet.init-param.template-path=/",

"javax.portlet.init-param.view-template=/view.jsp",

"javax.portlet.name=" + SenderPortletKeys.SENDER,

"javax.portlet.supported-publishing-event=messageEvent;http://ipc.events",

"javax.portlet.resource-bundle=content.Language",

"javax.portlet.security-role-ref=power-user,user",

},

service = Portlet.class

)

public class SenderPortlet extends MVCPortlet {

@ProcessAction(name = "sendMessage")

public void sendMessage(

ActionRequest actionRequest,

ActionResponse actionResponse)

throws IOException, PortletException {


String message = ParamUtil.getString(actionRequest, "message");


QName qName = new QName(

"http://ipc.events",

"messageEvent"

);


actionResponse.setEvent(qName, message);

}

}


1.43Receiver Portlet (OSGi Component)

Create Receiver Portlet


blade create -t mvc-portlet -p com.ipc.receiver -c ReceiverPortlet Receiver Portlet

package com.ipc.receiver.portlet;

import com.ipc.receiver.constants.ReceiverPortletKeys;

import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;

import java.io.IOException;

import javax.portlet.Event;

import javax.portlet.EventRequest;

import javax.portlet.EventResponse;

import javax.portlet.Portlet;

import javax.portlet.PortletException;

import javax.portlet.ProcessEvent;

import org.osgi.service.component.annotations.Component;

@Component(

property = {

"com.liferay.portlet.display-category=category.ipc-demo",

"com.liferay.portlet.header-portlet-css=/css/main.css",

"com.liferay.portlet.instanceable=true",

"javax.portlet.display-name=Receiver",

"javax.portlet.init-param.template-path=/",

"javax.portlet.init-param.view-template=/view.jsp",

"javax.portlet.supported-processing-event=messageEvent;http://ipc.events",

"javax.portlet.name=" + ReceiverPortletKeys.RECEIVER,

"javax.portlet.resource-bundle=content.Language",

"javax.portlet.security-role-ref=power-user,user"

},

service = Portlet.class

)

public class ReceiverPortlet extends MVCPortlet {

@ProcessEvent(qname = "{http://ipc.events}messageEvent")

public void processEvent(

EventRequest eventRequest, EventResponse eventResponse)

throws IOException, PortletException {

Event event = eventRequest.getEvent();

if (event.getName().equals("messageEvent")) {

String message = (String) event.getValue();

eventRequest.setAttribute("receivedMessage", message);

}

super.processEvent(eventRequest, eventResponse);

}

}

1.4 Update you Sender view.jsp page

<%@ include file="/init.jsp" %>


<p>

<b><liferay-ui:message key="sender.caption"/></b>

<portlet:actionURL name="sendMessage" var="sendMessageURL" />

<aui:form action="<%= sendMessageURL %>" method="post" name="fm">

<aui:input name="message" label="Message" />

<aui:button type="submit" value="Send" />

</aui:form>

</p>

</p>

1.5 Receiver view.jsp

<%@ include file="/init.jsp" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>


<p>

<b><liferay-ui:message key="receiver.caption"/></b>

<c:choose>

<c:when test="<%= request.getAttribute("receivedMessage") != null %>">

<div class="alert alert-info">

Latest message received: <%= request.getAttribute("receivedMessage") %>

</div>

</c:when>

<c:otherwise>

<div class="alert alert-secondary">No messages received yet.</div>

</c:otherwise>

</c:choose>


1.5: Deploy your send and receiver portlet using 

gradlew :mpdule:Sender-Portlet:deploy

gradlew :mpdule:Receiver-Portlet:deploy

2 How the Pieces Wire Together at Runtime

  • Both Sender and Receiver are deployed as independent OSGi bundles — each can be started, stopped, or updated without affecting the other.

  • When the user submits the Sender's form, processAction() fires and calls actionResponse.setEvent(...), publishing the event onto the render/action cycle for the current page.

  • Liferay's portlet container inspects every portlet on the page that declared javax.portlet.supported-processing-event for that QName, and Liferay's Whiteboard-based portlet lifecycle invokes processEvent() on each matching portlet — here, the Receiver.

  • The Receiver stores the value as a request attribute and its view.jsp renders it — no direct Java reference between the two portlet classes ever exists, and no page reload script is required beyond the portlet framework's own partial-refresh AJAX behavior.

Comments