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
Post a Comment