Skip to main content

Creating OSGi Modules and Sharing Packages

  Overview This guide walks through creating two OSGi modules in Liferay 7.4 and sharing a Java package between them using the standard API + Implementation pattern. This is the most common and correct approach for exposing reusable services in a Liferay-based architecture. In OSGi, a bundle (module) does not expose its internal packages by default — everything is private unless explicitly exported. To share code between modules, the standard practice is to split functionality into: · An API module — contains interfaces/DTOs and exports the package · A Service (Implementation) module — implements the interface, imports the package, and registers the implementation as an OSGi component/service The consuming module then simply imports the API package and looks up the service using @Reference injection. Step 1: Create the API Module Using Liferay Workspace + Blade CLI, generate a new API module: blade create -t api -p com.sgc.greeting greeting-api This generates a Gradle module unde...

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

Popular posts from this blog

service builder with crud operation in liferay

   Crud and Search opration in Liferay:      ->  Liferay use service builder techniq for Crud opration.    ->  Service builder purform by  Service.xml file.    ->  Service.xml file create table in database and also create class and diffrent method.   1)      Create service.xml file.             ->Create service.xml file in WEB-INF and write below code.             ->CODE:        < service-builder package-path = "com.test" >         < namespace > qr </ namespace >           < entity name = "Searchclass" local-service = "true"                     ...

How to create new site programmaticly in liferay with validation

Create site in liferay <%@page import="javax.portlet.PortletPreferences"%> <%@page import="com.liferay.portal.kernel.util.ParamUtil"%> <%@page import="com.liferay.portal.kernel.util.HtmlUtil"%> <%@page import="com.liferay.portal.kernel.util.StringPool"%> <%@page import="com.liferay.portal.kernel.util.UnicodeProperties"%> <%@page import="com.liferay.portal.service.LayoutSetPrototypeServiceUtil"%> <%@page import="com.liferay.portal.model.LayoutSetPrototype"%> <%@page import="com.liferay.portal.service.GroupLocalServiceUtil"%> <%@page import="java.util.List"%> <%@page import="com.liferay.portal.kernel.bean.BeanParamUtil"%> <%@page import="com.liferay.portal.theme.ThemeDisplay"%> <%@page import="com.liferay.portal.model.Group"%> <%@page import="com.liferay.portal.kernel.util.WebK...

The Ultimate Guide to Liferay DXP Performance Tuning: Speed Up Your Portal

The Ultimate Guide to Liferay DXP Performance Tuning: Speed Up Your Portal In the enterprise web space, milliseconds equal millions. Whether you are running a B2B commerce storefront, a customer support portal, or an employee intranet on Liferay DXP, slow load times will devastate your user experience and destroy your SEO rankings. Out of the box, Liferay is configured to run on almost any machine. This means its default settings are highly conservative to ensure compatibility, not maximum performance. If you are launching a production environment without tuning your server, you are leaving massive amounts of speed and scalability on the table. In this comprehensive, deep-dive guide, we are going to explore the critical layers of Liferay performance tuning. We will cover backend Java Virtual Machine (JVM) configuration, Database Connection Pooling, Elasticsearch optimization, and Frontend caching strategies. By the end of this guide, you will have a blazing-fast, enterprise-grade...