RE: Using Liferay + JSF + CDI across different plugins.

Javier Martin, modified 6 Years ago. New Member Posts: 2 Join Date: 8/3/12 Recent Posts

Hi all,

 

I am working in a project that have different plugins, all plugins works with JSF+CDI. When I work with injected beans inside the same plugin context, the system works fine. But I would like to extend this capabilities to use the same beans instances across different plugins as SessionScoped and ApplicationScoped.

I have declared a new module in Wildfly and declared in the jboss-deployment-structure.xml to be imported at the deploying time and to be reused by different plugins. In other words the same class loader definition is shared across all plugins.

But when my code in plugin 1 generate a new bean (Ej: SessionScoped bean) for an interface and class declared in the wildfly module, this bean is not injected in the plugin 2. Using the inspection of Weld Probe tool i saw that the beans are not vissible from each other from different plugins.

To solve this situation I have built two custom scopes (PortalSessionScoped and PortalRequestScoped) as Weld extension that works fine across different plugins, but I would like to use a more standard solution that custom scopes if possible.

Is there a specific configuration using the Liferay components to do that I need without coding my own CDI extension? ( I have discarded to use DeltaSpike)

My project configuration.

  1. Liferay 6.2.5 GA6 (Patched to work fine)
  2. CDI 1.2 (Weld 2.4.7)
  3. JSF 2.2 (Mojrarra 2.2.17)
  4. Wildfly 10.1
  5. JDK 8
  6. Liferay Faces Components (Bridges extension 3.0.1 , Liferay Faces Portal 2.0.1, Bridge Impl 4.1.1, Faces Alloy 2.0.1, Faces Util 3.1.0, cdi-portlet-bridge-shared .6.2.0.2)

Thanks and regards.

 

thumbnail
Kyle Joseph Stiemann, modified 6 Years ago. Liferay Master Posts: 760 Join Date: 1/14/13 Recent Posts

Hi Javier,
In order to share session data between two portlets (in the same WAR) in a standardized way, you can use PortletSession.APPLICATION_SCOPE:

PortletSession portletSession = (PortletSession) facesContext<span class="hljs-preprocessor">.getExternalContext</span>()<span class="hljs-preprocessor">.getSession</span>(true)<span class="hljs-comment">;</span>
portletSession<span class="hljs-preprocessor">.setAttribute</span>(“key”, “value”, PortletSession<span class="hljs-preprocessor">.APPLICATION</span>_SCOPE)<span class="hljs-comment">;</span>

If your portlets are not in the same WAR there is no standards-based way to share session attributes. Instead you should place the portlets into the same WAR. Or you can use Events or Public Render Paramaters to communicate between the portlets (IPC).

Liferay does have a non-standard feature that supports session sharing: &lt;private-session-attributes&gt;true&lt;/private-session-attributes&gt; (in liferay-portlet.xml). However this feature has not been tested with Liferay Faces and, as far as we’re aware, it does not work with Liferay Faces.

I recommend that you try moving to the appropriate IPC approach (Events or Public Render Parameters instead). I’ll quote David Nebinger on session usage:

Session storage negatively affects your nodes ability to serve users. Plus you either need to replicate session throughout the cluster (another performance hit and resource consumer) or be okay with losing session data if the node crashes.
 
It seems like an easy way to span requests (and in your case share data), but therein lies the trap.

Avoid using the session if at all possible.

- Kyle

P.S. I don't think that cdi-portlet-bridge-shared is necessary for your configuration (although Liferay 6.2 + Wildfly is not officially supported anyway) and I don't think you are using the correct versions of our Liferay Faces jars. Please go to liferayfaces.org to determine the correct versions.

Javier Martin, modified 6 Years ago. New Member Posts: 2 Join Date: 8/3/12 Recent Posts

Hi Kile, thanks for you answer,

I will have on consideration all your recommendations, we have already configured some portlets in different plugins using IPC events with success results, and for me is a very clean solution to cover certain requirements but this part of IPC using JSF is a bit unknown for me and we are preparing some stress benchmarks to check the final behavior of JSF - IPC under high load conditions.

Another requirements need to share information between different plugins, and to use events is not the best fit for me. In relation to the public render parameter, and inside the documentation of JSF - IPC https://dev.liferay.com/fr/develop/tutorials/-/knowledge_base/6-2/communicating-between-jsf-portlets-using-ipc , I read that:

"The Public Render Parameters technique provides a way for portlets to share data by setting public/shared parameter names in a URL controlled by the portal. While the benefit of this approach is that it is relatively easy to implement, the drawback is that only small amounts of data can be shared. Typically the kind of data that is shared is simply the value of a database primary key. "

Sadly is not my case because my final targets is to do a transactional flow process with a distributive layer components and we need that the information reside on session container or a different container linked to the session. However the objects used across the transactional flow have a size of 2K - 8K, too expensive and small (size/latency) to store in database storage and too large to set in a public render parameter.

Taking with priority your recommendations I will study to add new ways of solution to set my final design.

Thanks so much and regards.