Rutvij's Odyssey

Life of a Developer and Technologies he plays with

Liferay Session Sharing : Made Easy

with 5 comments


Inter portlet coummunication is made easy with JSR 286. But all IPC (Inter-Portlet Communications)  mechanisms (public render parameters,Events ) is about ACTION-to-VIEW.
  • What I mean by ACTION-to-VIEW is on “action phase” of one portlet information is shared and made available to specific/all portlet’s “view phase”.
  • There are use cases  where we need a IPC mechanism to share information between portlets of different WARs  in VIEW-to-VIEW .It means One portlet will share information from its VIEW phase and will be available to other Portlet in VIEW phase.
By default Each WAR has its own session and will not be shared with other WARs.
Liferay provides a mechanism by which Portlets can share session attributes across WARs.
How to Setup :

1.liferay-portlet.xml
For Portlets who will share (i.e setAttribute() ) session attributes(s) need to add following entry in liferay-portlet.xml

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

2. Use Namespace prefix to Share/Get shared session attribute:

By default “LIFERAY_SHARED_”  prefix is used for sharing session attribute to other WARs.  It can be customized with in portal.properties ‘s session.shared.attributes value.
portletSession.setAttribute( "LIFERAY_SHARED_mySpecialVar",value,PortletSession.APPLICATION_SCOPE);
Other portlet(s)  in different WAR  can access it :
portletSession.getAttribute( "LIFERAY_SHARED_mySpecialVar",PortletSession.APPLICATION_SCOPE);
3. Caveat :

Using Liferay’s custom Session Sharing mechanism Portlet can share session with other Portlet in Different WAR but not with the Servlet in Different WAR.
It can be shared with Servlet ( of Different WAR) via Portlet of that WAR.

How to Share with Servlet of Other WAR :-
Portlet One :
portletSession.setAttribute( "LIFERAY_SHARED_mySpecialVar",value,
PortletSession.APPLICATION_SCOPE);
Portlet Two:

Object value=  portletSession.getAttribute
( "LIFERAY_SHARED_mySpecialVar",PortletSession.APPLICATION_SCOPE);//getting shared value
portletSession.setAttribute
( "mySpecialVar",value,PortletSession.APPLICATION_SCOPE);//setting to 'local' session

Servlet Two:

request.getSession().getAttribute("mySpecialVar");

Developer has to be aware while sharing/accessing “shared” session attributes, also note that if prefix is customized need to change the source code.
I have developed a Utility which can make Liferay Session sharing easier for developers.
Its taking care of customized prefix also and provides neat way to set/access shared session attributes.
/*****
<pre>* RUTVIJ SHAH MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. RUTVIJ SHAH SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
* THIS SOFTWARE IS IN AS-IS FORM, YOU ARE FREE TO RE-DISTRIBUTE/CHANGE WITHOUT ANY NOTIFICATION TO AUTHOR.
******/

package myapp.liferayImpl.session.util;

import com.liferay.portal.kernel.util.PropsUtil;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;

/**
* @author Rutvij Shah ( rutvij.shah@yahoo.com )
* LiferaySessionUtil provides helper methods to share your Session attributes
* across WARs.
*
*/
public class LiferaySessionUtil {
/***
* This prefix is used by Liferay Portal to detect Session Attributes
* for sharing betweeen WARs.
*/

private static final String LIFERAY_SHARED_SESSION_PREFIX=getSharedSessionPrefix();
private static final String LIFERAY_SHARED_SESSION_PREFIX_DEFAULT="LIFERAY_SHARED_";
/****
* It stores attribute as 'Shared' Attribute and will be available to other
* portlets in different WARs.
*
* Attributes shared by this method will be available to only Portlets,
* not other Web components i.e Servlet.
*
* @param key session Key to store value
* @param value
* @param request PortletRequest
*/
public static final void setGlobalSessionAttribute(String key,Object value,PortletRequest request){
if(key!=null){
String globalKey=getGlobalKey(key);
PortletSession portletSession=request.getPortletSession();
portletSession.setAttribute(globalKey,value,PortletSession.APPLICATION_SCOPE);
}
}
/****
*
* It provides access to get shared session attributes from other portles
* from diffrent WARs.
*
* @param key
* @param request
* @return
*/
public static final Object getGlobalSessionAttribute(String key,PortletRequest request){
Object value=null;
if(key!=null){
String globalKey=getGlobalKey(key);
PortletSession portletSession=request.getPortletSession();
value=portletSession.getAttribute(globalKey,PortletSession.APPLICATION_SCOPE);
}
return value;
}

/******
*
* It provides a way to further share 'Shared'Session Attributes from
* Portlet to other Web Components i.e Servlets .
*
* @param key
* @param request
*/
public static final void shareGlobalSessionAttribute(String key,PortletRequest request){
if(key!=null){
Object value=getGlobalSessionAttribute(key, request);
PortletSession portletSession=request.getPortletSession();
portletSession.setAttribute(key,value,PortletSession.APPLICATION_SCOPE);
}
}

/***
* Helper method to generate Global key using Liferay shared prefix
* @param key
* @return
*/
private static final String getGlobalKey(String key){
return LIFERAY_SHARED_SESSION_PREFIX+key;
}

/********
* Helper method to get Liferay's Session Sharing prefix
* Useful when Liferay is customized to use different prefix other than Default
*
* @return
*/
private static final String getSharedSessionPrefix(){
String value=null;
try {
/**
* Getting value from portal.properties
*/
value = PropsUtil.get("session.shared.attributes");
} catch (Exception ex) {
Logger.getLogger(LiferaySessionUtil.class.getName()).log(Level.SEVERE, null, ex);
}

if(value !=null){
if(value.contains(LIFERAY_SHARED_SESSION_PREFIX_DEFAULT)){
//if default prefix is configured use it
value=LIFERAY_SHARED_SESSION_PREFIX_DEFAULT;
}else{
//use first one from the list of prefix configured
value=value.split(",")[0];
}
}else{
/**
* If none of the value configured use default one
* Note: Session Sharing may not work as none of the value configured.
*/
value=LIFERAY_SHARED_SESSION_PREFIX_DEFAULT;
}
return value;
}

}
Using this Util class  for same use case :
Portlet One :
LiferaySessionUtil.setGlobalSessionAttribute
("mySpecialVar",value, portletRequest); //adding 'proper' prefix will be taken care by Utility
PortletTwo:

Object value=  LiferaySessionUtil.getGlobalSessionAttribute
("mySpecialVar", portletRequest); //to get value for portlet
LiferaySessionUtil.shareGlobalSessionAttribute
("mySpecialVar", portletRequest);//to share value to servlets

As you can see if Portlet Two only need to share it with servlet no need of first line.

Servlet Two:
 request.getSession().getAttribute("mySpecialVar");

Feel free to share your comments on this. You can download LiferaySessionUtil.java  from here :  LiferaySessionUtil


Written by rutvijshah

December 13, 2009 at 7:54 pm

5 Responses

Subscribe to comments with RSS.

  1. Hey shah, your post really helped me and my team.Thanks and keep up the good work

    Mike

    January 9, 2010 at 10:00 pm

  2. HI

    I am facing one issue in our spring portlet.I have Three portlet and deployed in three war.See one login portlet, one is registration port and one is claim portet. I am using spring security logout mechanism for logout . In claim portlet i have one portlet session and some values are set. While logout i want to to remove all session values (portlet session values).
    I uses session.invalidate for invalidate the session but it is not invalidating. Dou you have any idea? . I am using 286 portlet…please replay..

    mejat

    June 12, 2012 at 10:18 am

  3. such a nice post keep it up….good job dudeee

    Suresh Ranga

    July 18, 2012 at 7:06 pm

  4. Reallly helped me to get touch base with the IPC communication using the first type portlet session.. i came to know about the liferay custom session sharing through this post. great work shah

    Suresh Ranga

    July 18, 2012 at 7:07 pm

  5. Thanks for sharing these post very useful to liferay developers.

    But i have doubt i.e
    1.) i want to share only one session with attributes across portal.is it possible? if so how?

    i meant for this example.
    ex: suppose a testvalue 10 can be share across portal through only session (servletsportlets(action&jsp classes)) with in the same war different wars.
    ———————————————————————————————
    2.) servletportlet(samewar) && servletportlets(different wars) with one session only.

    Thank you

    Venkateswara Raju V

    Venkateswara Raju V

    February 15, 2013 at 7:18 am


Leave a comment