Sharing Data Between Portlets

UPDATE: 2019/01/11: Please refer to Kyle Stiemann's blog titled How can I share session data across portlets in Liferay? which discusses the various benefits and drawbacks of data sharing approaches that are now available.

If you want to share data between portlets, a common way to do that is by storing data in the user's session. Liferay Portal has some nice features for sharing session data like <shared-session-attributes> in the liferay-portlet.xml file, and shared.session.attributes in the portal-ext.properties file.

But what if you're trying to go session-less? Or what if you want to share data globally for all users across sessions?

One way to do share data like this is to store the data in the portal's ROOT context. The first step is to create a GlobalStartupAction in the Liferay EXT environment, like this:

package com.foo.liferay.startup;

public class GlobalStartupAction extends SimpleAction {

	private static List<String> fooList; 
 	public List<String> getFooList() {
		return fooList;
	}

	public static void 
	@Override public void run(String[] ids) throws ActionException {
		// Cache all the data
		fooList = new ArrayList<String>();
		fooList.add(new String("red"));
		fooList.add(new String("green"));
		fooList.add(new String("blue"));
	}
}

Then, the GlobalStartupAction needs to be registered in the portal-ext.properties file. There is already a global startup action specified there for Liferay's own startup purposes, but thankfully this value can be a comma-delimited list, so we can just add the GlobalStartupAction after the Liferay one:

global.startup.events=com.liferay.portal.events.GlobalStartupAction,com.foo.liferay.startup.GlobalStartupAction

And then inside each portlet, use the magic Liferay PortalClassInvoker to call the static getFooList() method. The PortalClassInvoker utility figures out the classloader for the Liferay Portal context before calling the specified method:

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

public class ApplicationScopeBean {

    private static final List fooList;

    public ApplicationScopeBean() {
        List<String> fooList = (List<String>) PortalClassInvoker.invoke("com.foo.liferay.startup.GlobalStartupAction", "getFooList"));
    }

}

 

Blogs
Ray Auge' said you wrote this blog entry just for me :-)
Thanks!

PortalClassInvoker... hm... Never heard of that class before, but cool! That brings be back to think: Why don't I use a class with static methods to retrieve and save my data...
Wonderful ! I've been searching how to share some data among sessions for at least one month ! I've got to implement a 2 levels cache (caching business data to share all of them among all sessions=first level / in their session, users can access only business data on which they have permission).

Thanks a lot !
Ok, so here I can add my own portal wide data. But what is the parameter ids for? And what when I want to store the portalURL via that way?
Thanx
Could you clarify your question a little more? I didn't mention any parameter ids in the post. Are you referring to the Portlet 2.0 public-render-parameters feature for inter-portlet communication?
I created myself a global class as described here:
http://www.icefaces.org/JForum/posts/list/16321.page#61421

Is there a benefit to use this Liferay mechanism or has I just the same functionality than my solution?

Best regards,

Gaston
Could this be used to trigger an LDAP import? how would i use it to do pass multiple parameters? for example

boolean returnMe = PortalLDAPImporter.importLDAPUser(ldapServerID, companyId, ldapContext, attributes, StringPool.BLANK, true);
I have a requirement of initializing something in my portlet. This solution here works in ext, but what is better solution for a simple portlet. ? thanks you