Reputation: 2089
I'm trying to use Liferay shared session attributes.
I would like to to use the same attribute on two different portlets in different WAR file-s on different URL-s using the following code based on:
Liferay 7 not able to set the global session attribute
Value I want to save: A single string
Setting in portlet 1:
String sharedKey = "LIFERAY_SHARED_" + key;
HttpSession session = PortalSessionThreadLocal.getHttpSession();
session.setAttribute(sharedKey, bean);
Portlet 1 is able to retain, reset and use attribute fine.
Reading in portlet 2:
key = "LIFERAY_SHARED_" + key;
HttpSession session = PortalSessionThreadLocal.getHttpSession();
Object bean = session.getAttribute(key);
This value is always null.
Both portlets are Spring MVC portlets.
Both portlets have:
<instanceable>false</instanceable>
<private-session-attributes>false</private-session-attributes>
<requires-namespaced-parameters>false</requires-namespaced-parameters>
In their liferay portlet XML-s.
Also both portlets extend org.springframework.web.portlet.DispatcherPortlet.
Liferay version:
Liferay DXP Digital Enterprise 7.0.10 GA1
Any help would be greatly appreciated. Let me know if anyone needs any clarification.
Thanks a lot, PeTer
Upvotes: 3
Views: 3716
Reputation: 48067
Kyle Stiemann has recently written a nice article on using sessions in portlets. TL;DR: You're using the HttpSession with an attribute prefixed "LIFERAY_SHARED_"
, but you should use the portlet session: That's what Liferay manages, the HttpSession might be "simulated", e.g. it might not be the object that tomcat manages.
To quote one of the options from his article:
Use Liferay session.shared.attributes prefixes (such as LIFERAY_SHARED_) to share one or more session attributes between portlets in different applications/WARs.
Liferay exposes certain session attributes to all portlets based on certain prefix values. Although these prefixes are configurable via portal-ext.properties, I recommend using one of the default prefixes: LIFERAY_SHARED_.
For example:
// Portlet A portletRequest.getPortletSession(true) .setAttribute("LIFERAY_SHARED_" + CONSTANTS.ATTR_NAME, "value", PortletSession.APPLICATION_SCOPE); // Portlet B (in a different WAR) String attrValue = portletRequest.getPortletSession(true) .getAttribute("LIFERAY_SHARED_" + CONSTANTS.ATTR_NAME, PortletSession.APPLICATION_SCOPE);
Pros:
- Only exposes the necessary attribute(s) to other portlets (instead of exposing the entire session).
Cons:
- Exposes session attribute(s) to all portlets.
- Tight coupling without indicating which other portlets might be utilizing this data.
- Non-standard method of sharing session data.
Note the strong recommendation to use only primitive types as session attributes. Eliminate the need for custom serialization and classloading problems. Also note that the variant of getPortletSession
with the additional scope parameter is required here.
But, as much as this technically provides an answer to your question, you also want to read "Session Storage is Evil".
TL;DR: Don't use the technique above. Rather eliminate the use of sessions.
Upvotes: 5