Table of contents
Introduction
Once a portlet is placed on a portal page, its data is not directly shared with other portlets. IPC (Inter Portlet Communication) defines the ways that a Portlet can interact and communicate with another Portlet. There are four ways to make inter portlet communication :
- Using Portlet Session
- Using Public Render Parameters
- Using Events
- Using AJAX
This post will show how to operate a Portlet communication using Portlet session.
Portlet session
Inter Portlet Communication using Portlet session was introduced in Portlet 1.0 (JSR 168) and carried in Portlet 2.0 (JSR 268).
Portlets have two kinds of session:
- PORTLET_SCOPE session: Objects stored in the session are available to the portlet during requests for the same portlet window that the objects where stored from.
- APPLICATION_SCOPE session: Objects stored are visible to all other portlets that are packaged as part of the same portlet application (same war), this is the default behavior. Liferay provides a way to share the data even with portlets that are not located in the same war.
How to communicate using Portlet session?
To communicate with other portlets, use the Portlet APPLICATION_SCOPE session. Let’s consider that we want to make a communication between two portlets, Portlet S (Portlet Sender: which will send data) and Portlet R (Portlet Receiver : Portlet which will receive data). Below steps to follow :
-
Defining the private-session-attributes in Liferay-portlet.xml
First step is to define the “private-session-attributes” property in the Liferay-portlet.xml file of each portlet. Add the following line within the “<portlet>” tag :
1 |
<private-session-attributes>false</private-session-attributes> |
-
Storing Data in the sender portlet
In your sender portlet, store the object you want to send in the session. To do so, get the portlet session from the action request or render request and set an attribute with the APPLICATION_SCOPE option. Below how to do :
1 2 |
PortletSession portletSession = renderRequest.getPortletSession(); portletSession.setAttribute("key", value ,PortletSession.APPLICATION_SCOPE); |
-
Retrieving the stored data in the receiver portlet
In your receiver portlet, retrieve the stored data from the session. To do so, get the portlet session from the render request and get the stored object using the APPLICATION_SCOPE option. Below how to do :
1 2 |
PortletSession portletSession = renderRequest.getPortletSession(); String value = (String) portletSession.getAttribute("key ",PortletSession.APPLICATION_SCOPE); |
You can store object bean in the session. The stored object must be Serializable.
Concrete example
Let’s see a full example of using the IPC with Portlet session.
The code source is available on Github. Download the source
Let’s consider two portlets :
- CarList (Portlet 1): This portlet shows a list of cars. The user can select a car from the list. When the user select a car, the car’s id is stored in the session. The car information will be displayed in the second portlet.
- CarInformation (Portlet 2): If a car is selected (Id stored in the session), this portlet will display the car information.
In this example, I used JSF as portlet framework. You can choose whatever you want. The logic remains the same.
Portlet 1 : CarList
- Portlet.xml
Defining the CarList portlet in the portlet.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<portlet> <portlet-name>CarList</portlet-name> <display-name>CarList</display-name> <portlet-class> javax.portlet.faces.GenericFacesPortlet </portlet-class> <init-param> <name>javax.portlet.faces.defaultViewId.view</name> <value>/views/carlist/view.xhtml</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>CarList</title> <short-title>CarList</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> </portlet> |
- Liferay-portlet.xml
Registring the Liferay portlet in the liferay-portlet.xml file with the private-session-attributes set to false.
1 2 3 4 5 6 7 8 9 |
<portlet> <portlet-name>CarList</portlet-name> <icon>/icon.png</icon> <private-session-attributes>false</private-session-attributes> <requires-namespaced-parameters>false</requires-namespaced-parameters> <header-portlet-css>/css/main.css</header-portlet-css> <footer-portlet-javascript>/js/main.js</footer-portlet-javascript> <css-class-wrapper>carlist-portlet</css-class-wrapper> </portlet> |
- Selecting the car
Storing the data in the session.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** * Store the car's identifier in the session. * @param carId Car's identifier. */ public void selectCar(final String carId) { System.out.println("Selected car id = " + carId); // Getting the faces context. FacesContext fc = FacesContext.getCurrentInstance(); // Getting the portlet request. PortletRequest request = (PortletRequest) fc.getExternalContext().getRequest(); // Getting the portlet session. PortletSession portletSession = request.getPortletSession(); // Setting the car identifier in the portlet session. portletSession.setAttribute("carId", carId, PortletSession.APPLICATION_SCOPE); } |
Portlet 2 : CarInformation
- Portlet.xml
Defining the CarInformation portlet in the portlet.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<portlet> <portlet-name>CarInformation</portlet-name> <display-name>CarInformation</display-name> <portlet-class> javax.portlet.faces.GenericFacesPortlet </portlet-class> <init-param> <name>javax.portlet.faces.defaultViewId.view</name> <value>/views/carinformation/view.xhtml</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>CarInformation</title> <short-title>CarInformation</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> </portlet> |
- Liferay-portlet.xml
Registring the Liferay portlet in the liferay-portlet.xml file with the private-session-attributes set to false.
1 2 3 4 5 6 7 8 9 |
<portlet> <portlet-name>CarInformation</portlet-name> <icon>/icon.png</icon> <private-session-attributes>false</private-session-attributes> <requires-namespaced-parameters>false</requires-namespaced-parameters> <header-portlet-css>/css/main.css</header-portlet-css> <footer-portlet-javascript>/js/main.js</footer-portlet-javascript> <css-class-wrapper>carinformation-portlet</css-class-wrapper> </portlet> |
- Getting the carId from the session :
Retrieving the data from the session and deleting it after use.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * Car service. */ @ManagedProperty("#{carService}") private CarService service; /** * Car. */ private Car car; /** * Initialize the managedBean. */ @PostConstruct public void init() { // Getting the portet session. FacesContext fc = FacesContext.getCurrentInstance(); PortletRequest request = (PortletRequest) fc.getExternalContext().getRequest(); PortletSession portletSession = request.getPortletSession(); // Getting the carId attribute. String carId = (String) portletSession.getAttribute("carId", PortletSession.APPLICATION_SCOPE); // Getting the car corresponding to the carId. car = service.getCarWithId(carId); // Removing the session attribute. portletSession.removeAttribute("carId", PortletSession.APPLICATION_SCOPE); } |
Rendering after deployment :
The CarList portlet is on the left. CarInformation portlet is on the right.
Below the result after selecting Ferrari car.
The code source is available on Github. Download the source