Saturday, February 21, 2015

Store Portlet Preferences using Portlet Edit Mode

Portlet Preferences is the way to store Portlet specific information in the Portlet development. Generally if we wanted to add Portlet specific behaviour then we will use Portlet preferences.

Assume we want display date with different date format to each Portlet based on our need to so to make this I will store date format value in Portlet preferences.

We will use edit mode or edit page to configure Portlet related preferences to make this first we need add edit mode capability to portlet so that in the Portlet configuration we can see preferences link in the menu and when we click the link it will navigate to edit page.

Add Edit Mode capability to Portlet

We need to create edit JSP page
Need to do following configuration in the portlet.xml file

<portlet>
           <portlet-name>portlet-preferenses-action</portlet-name>
           <display-name>Portlet Preferenses</display-name>
           <portlet-class>
                com.meeera.liferay.PortletPreferensesAction
          </portlet-class>
           <init-param>
                <name>view-template</name>
                <value>/html/jsps/view.jsp</value>
           </init-param>
           <init-param>
                <name>edit-template</name>
                <value>/html/jsps/edit.jsp</value>
           </init-param>
           <expiration-cache>0</expiration-cache>
           <supports>
                <mime-type>text/html</mime-type>
                <portlet-mode>view</portlet-mode>
                <portlet-mode>edit</portlet-mode>
           </supports>
           <portlet-info>
                <title>Portlet Preferenses</title>
                <short-title>Portlet Preferenses Action</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>

Note:

Above red color xml tags will add edit mode capability to the Portlet. There we can edit template init param and its value that is jsp path of edit page.

When we add edit mode capability to Portlet then we can see preferences link in the Portlet configuration menu.

When we click the link it will go to edit page and when we observed URL of Portlet we can see request param name Portlet mode and its value is edit.

The following screen show preferences link in the Portlet configuration


When we click preferences link the URL we can see Portlet mode param values as edit.

http://localhost:8080/web/guest/test?p_p_id=portletpreferensesaction_WAR_StorePreferensesInPortletEditModeportlet&
p_p_lifecycle=0&p_p_state=normal&p_p_mode=edit&p_p_col_id=column-1

When we call above URL then it will execute doEdit(--)  method of Portlet action class which is one of the method implemented in the MVCPortlet.java class

The following is implementation was present in MVCPortlet.java for doEdit(--)

@Override
     public void doEdit(
                RenderRequest renderRequest, RenderResponse renderResponse)
           throws IOException, PortletException {

           PortletPreferences portletPreferences = renderRequest.getPreferences();

           if (portletPreferences == null) {
                super.doEdit(renderRequest, renderResponse);
           }
           else {
                include(editTemplate, renderRequest, renderResponse);
           }
     }


Create Portlet URL that will execute doEdit(--) method

The Portlet URL to execute doEdit(--) method we need to use attribute portletMode and value should be "edit" so that when we call this URL its will execute edit method of Portlet action class.

We override doEdit(--) method in our Custom Portlet Action it will execute our overridden method otherwise it will execute the super class doEdit(--) method that is MVCPortlet.

Example to create URL to execute doEdit(--)   method

Render URL with Edit Mode

<portlet:renderURL var="savePreferensesActionURL" windowState="normal" portletMode="edit">
</portlet:renderURL>

Action URL with Edit Mode

<portlet:actionURL var="savePreferensesActionURL" windowState="normal" portletMode="edit">
</portlet:actionURL>

Store Portlet Preferences in the Portlet Edit Mode

Now we will store Portlet preferences or we can Portlet configuration values using Portlet edit mode to make this we need follow following steps

Steps:
  1. Add Edit Mode capability to Portlet
  2. Override doEdit(--)  method in Custom Portlet Action
  3. Get Portlet Preferences Values in View pages and Present Data as for Portlet preferences.

Add Edit Mode capability to Portlet

We need to create edit JSP page
Need to do following configuration in the portlet.xml file

<portlet>
           <portlet-name>portlet-preferenses-action</portlet-name>
           <display-name>Portlet Preferenses</display-name>
           <portlet-class>
                com.meeera.liferay.PortletPreferensesAction
           </portlet-class>
           <init-param>
                <name>view-template</name>
                <value>/html/jsps/view.jsp</value>
           </init-param>
           <init-param>
                <name>edit-template</name>
                <value>/html/jsps/edit.jsp</value>
           </init-param>
           <expiration-cache>0</expiration-cache>
           <supports>
                <mime-type>text/html</mime-type>
                <portlet-mode>view</portlet-mode>
                <portlet-mode>edit</portlet-mode>
           </supports>
           <portlet-info>
                <title>Portlet Preferenses</title>
                <short-title>Portlet Preferenses Action</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>
Note:

Above red color xml tags will add edit mode capability to the Portlet. There we can edit template init param and its value that is jsp path of edit page.

In the edit.jsp page we need to create form with input elements that is Portlet preferences which we are taking from user/client for this Portlet.

We already assumed we wanted display different date format to date when we display current date in Portlet.  Here we will take date format as Portlet preferences as form input

We will submit our form using Portlet render URL and that is in the edit mode so that it will execute the Portlet doEdit(--) method in Portlet action class, there we will capture user from inputs and store into databased as Portlet preferences .

The following is code in edit.jsp page

<%@page import="com.liferay.portal.kernel.util.StringPool"%>
<%@page import="com.liferay.portlet.PortletPreferencesFactoryUtil"%>
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@page import="javax.portlet.PortletPreferences"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<portlet:renderURL var="savePreferensesRenderURL" windowState="normal" portletMode="edit">
</portlet:renderURL>
<%
PortletPreferences preferences = renderRequest.getPreferences();
String portletResource = ParamUtil.getString(request, "portletResource");
if (Validator.isNotNull(portletResource)) {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(request, portletResource);
}
String dateFormat = preferences.getValue("dateFormat",null);
%>
<h1> Add Portlet Preferenses</h1>
<form action="<%=savePreferensesRenderURL%>" name="savePreferenses"  method="POST">
Expected Date Format<br/>
<input  type="text" name="<portlet:namespace/>prefdateformat"<portlet:namespace/>prefdateformat" value='<%=dateFormat!=null?dateFormat:StringPool.BLANK%>'/><br/>
<input type="submit" name="savepref" id="savepref" value="Save Preferenses"/>
</form>

Override doEdit(--)  method in Custom Portlet Action

Now we need to override doEdit(--) method in our Portlet Action class so that here we will write preferences storing logic and  the values store into the database on behalf  of Portlet. 

It will use portlet preferences database table where it will store all preferences with portlet id and all values will make it as XML string and store in the table.

The following is Custom Portlet Action class with doEdit(--) and preferences storing

public class PortletPreferensesAction extends MVCPortlet {
      @Override
     public void doEdit(RenderRequest renderRequest,
                RenderResponse renderResponse) throws IOException, PortletException {
           String dateFormat = ParamUtil
                     .getString(renderRequest, "prefdateformat");
           System.out.println("====" + dateFormat);
           PortletPreferences preferences = renderRequest.getPreferences();
           String portletResource = ParamUtil.getString(renderRequest,
                     "portletResource");
           if (Validator.isNotNull(portletResource) && (preferences == null)) {
                try {
                     preferences = PortletPreferencesFactoryUtil.getPortletSetup(
                                renderRequest, portletResource);
                } catch (PortalException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                } catch (SystemException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                }
           }
           preferences.setValue("dateFormat", dateFormat);
           preferences.store();
           SessionMessages.add(renderRequest,"potlet-config-saved");
           super.doEdit(renderRequest, renderResponse);
          
     }
    
}

Get Portlet Preferences Values in View page and Present Data as for Portlet preferences.

Finally we will take the preferences values from portlet preferences and will display view as for preferences stored for that particular Portlet.

In our case we will take date format that configured by user and display current date with user desired format.

When we take the values from preference object with getValue(--) method we need to pass default value as second parameter so that it will use when the preferences value is not available.

The following is Sample Code in the view.jsp

<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="com.liferay.portlet.PortletPreferencesFactoryUtil"%>
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@page import="javax.portlet.PortletPreferences"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<portlet:defineObjects />

<%
PortletPreferences preferences = renderRequest.getPreferences();
String portletResource = ParamUtil.getString(request, "portletResource");
if (Validator.isNotNull(portletResource)) {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(request, portletResource);
}
String dateFormat = preferences.getValue("dateFormat",null);
%>
<%
if(dateFormat!=null){
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
String date = sdf.format(new Date());
out.println("Today Date:"+date);
}else{
     out.println("Please configure date format");
}

%>
Portlet Screens:

Following screen shows navigate to portlet edit mode or edit jsp page



The following is Store Date format preferences from edit page


Display Current Date in view page with desired data format


Download Store Preferences in Edit Mode Portlet


Another way also we can store Portlet preferences using Liferay Configuration Action mechanism



Saturday, January 31, 2015

Liferay Pugins SDK Ivy Download Problem and Solution

Some time we may face problem of creating Liferay plugin application with liferay-plugins-sdk-6.2-ce-ga3 with Liferay IDE 2.x due to incomplete download of ivy required jar files and configuration files through eclipse.

When we trying to create Liferay plugin project for first time, the project may not be created successfully due to problem with downloading of ivy related required jar files from eclipse.

In Liferay plugins sdk 6.2 GA3, we can find .ivy directory (liferay-plugins-sdk-6.2\.ivy). In side of .ivy directory we can see cache directory and ivy-2.3.0.jar file.

Due to some proxy issues or fire wall problems or internet connectivity, the ivy related all jar files and other configuration files will not be downloaded in the cache (liferay-plugins-sdk-6.2\.ivy\cache) directory for first time when we create Liferay plugin project.

For the first time if everything is fine then it will take several minutes to download all required jar files and configuration files in plugins-sdk cache location (liferay-plugins-sdk-6.2\.ivy\cache).

In some cases the creation of new Liferay plugin project may not be completed and keep on loading like shown in below screenshot, then there might be a problem with downloading of ivy related jar file. In that case we need to download all .ivy related jar files manually.



What are all jar file should be downloaded and its repository locations was specified in the ivy-settings.xml file which is in liferay-plugins-sdk-6.2.

The following is reference of settings.xml



Solution for the above problem:

To fix the above explained problem, we should manually download ivy related jar files and configuration files and place them in appropriate location of liferay plugins sdk 6.2 GA3.

Procedure:

Download ivy zip files from following location


Copy ivy-cache.zip to liferay-plugins-sdk-6.2 (this is your Liferay plugins sdk)

Now extract the downloaded ivy-cache.zip in the same location. i.e., Liferay-plugins-sdk-6.2 (use extract here from WinRAR or zip software)

Now all required jar files and configuration files will be placed in .ivy directory.

The following is the screenshot of .ivy directory (\liferay-plugins-sdk-6.2\.ivy)


The following is the cache directory screenshot, which shows all required jar files



You can follow above procedure or you can download fully working Liferay-plugins-sdk-6.2-ce-ga3 from following location and  in this plugins SDK i already downloaded ivy related jar files and included in the Liferay-plugins-sdk-6.2-ce-ga3.


Author

Wednesday, January 21, 2015

Access Liferay Portal Live Users in Plugin Portlet


Some time we may get requirement to access liferay portal live users/logged in users information in Plugin portlets.

Generally Liferay have implemented class called “LiveUsers.java” class in the portal level which is not available in Plugin environment.

LiveUsers.java is class which contains set of methods from this we can get logged in users/portal live users information.

Problem:

LiveUsers.java implemented in portal level so which is not directly available in Plugin portlet environment.

Solution:

We will use portal class loader to load LiveUsers class and we will use Java Reflection Mechanism to call methods from LiveUsers.java

What is portal Live Users?

Portal Live users are the logged in users they are currently live in the portal.

Access Portal Live Users in Plugin Portlet Environment

Add “live.users.enabled=true” property in portal-ext.properties file

Use Portal Class Loader and Java Reflection API to access methods in LiveUsers.java

Add “live.users.enabled=true” property in portal-ext.properties file

Generally live.users.enabled property set as “false” in portal.properties file . If we want to know portal live users information we need to make that value as “true” this property value overridden through the portal-ext.properties file which in Liferay Home directory.

Add following property in “portal-ext.properties”

live.users.enabled=true

Use Portal Class Loader and Java Reflection API to access methods in “LiveUsers.java”

As we know that “com.liferay.portal.liveusers.LiveUsers.java” class implemented in portal level so it count not be accessible in Plugin portlet environment.

So we will use portal class loaded to load class and crate instance from that we will use Java Reflection API to invoke methods which are implemented in “LiveUsers.java”

We have different methods in LiveUsers.java we will use “getSessionUsers” method to get Portal Live Users information and it will return map object which contains all portal live users information.

The following is sample Code to get Portal Live Users

ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
Class<?> liveUsers = PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.liveusers.LiveUsers");
System.out.println(liveUsers);
Method getSessionUsers = liveUsers.getDeclaredMethod("getSessionUsers",long.class);
Object map = getSessionUsers.invoke(null,themeDisplay.getCompanyId());
Map<String, UserTracker> sessionUsers = null;
sessionUsers=(ConcurrentHashMap<String, UserTracker>)map;
System.out.println(sessionUsers);

Output Some thing like below and its map object

{92C0414115E50E0D5A3F9EDA23CBC6FE={userTrackerId=0, companyId=10157, userId=10201, modifiedDate=Wed Jan 21 17:09:42 GMT 2015, sessionId=92C0414115E50E0D5A3F9EDA23CBC6FE, remoteAddr=127.0.0.1, remoteHost=127.0.0.1, userAgent=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:32.0) Gecko/20100101 Firefox/32.0}, 5508BE3C06C9AECABF99088009E866F5={userTrackerId=0, companyId=10157, userId=10201, modifiedDate=Wed Jan 21 17:10:45 GMT 2015, sessionId=5508BE3C06C9AECABF99088009E866F5, remoteAddr=127.0.0.1, remoteHost=127.0.0.1, userAgent=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:32.0) Gecko/20100101 Firefox/32.0}}

Scenario:

Assume we want display all portal live users information in Plugin portlet. When we click on some button it will display all portal live users in the portlet view page.

The following is full code of implementation

Portlet Action class

package com.meera.portallive.users;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.UserTracker;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class PortalLiveUsersPortletAction extends MVCPortlet {
@SuppressWarnings("unchecked")
public void getLiveUsers(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
try{
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
Class<?> liveUsers = PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.liveusers.LiveUsers");
System.out.println(liveUsers);
Method getSessionUsers = liveUsers.getDeclaredMethod("getSessionUsers",long.class);
Object map = getSessionUsers.invoke(null,themeDisplay.getCompanyId());
Map<String, UserTracker> sessionUsers = null;
sessionUsers=(ConcurrentHashMap<String, UserTracker>)map;
System.out.println(sessionUsers);
actionRequest.setAttribute("portalLiveUsers", sessionUsers);
}catch(Exception e){
e.printStackTrace();
}
} 
}

Portlet view.jsp page

<%@page import="java.util.concurrent.ConcurrentHashMap"%>
<%@page import="com.liferay.portal.model.UserTracker"%>
<%@page import="java.util.Map"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<%@taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %>
<%@taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
<%@taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@
taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
<portlet:defineObjects />
<liferay-theme:defineObjects />
<portlet:actionURL var="getLiveUsers" windowState="normal" name="getLiveUsers">
</portlet:actionURL>
<h2>Portal Live Users/Portal Logged in Users</h2>
<form action="<%=getLiveUsers%>" name="getLiveUsersForm" method="POST">
<input type="submit" name="GetPortalLiveUsers" id="GetPortalLiveUsers" value="Get Portal Live Users"/>
</form>

<%
if(renderRequest.getAttribute("portalLiveUsers")!=null){
Map<String, UserTracker> sessionUsers = null;
sessionUsers=(ConcurrentHashMap<String, UserTracker>)renderRequest.getAttribute("portalLiveUsers");
%>
<table border="1">
<tr>
<th>Company Id</th>
<th>Email Address</th>
<th>FullName</th>
<th>User Agent</th>
<th>Remote Host</th>
<th>Remote Address</th>
<th>Session Id</th>
</tr>
<%

for (Map.Entry<String, UserTracker> entry : sessionUsers.entrySet())
{
UserTracker liveUserTracker=entry.getValue();%>
<tr>
<td><%=liveUserTracker.getCompanyId()%></td>
<td><%=liveUserTracker.getEmailAddress()%></td>
<td><%=liveUserTracker.getFullName()%></td>
<td><%=liveUserTracker.getUserAgent()%></td>
<td><%=liveUserTracker.getRemoteHost()%></td>
<td><%=liveUserTracker.getRemoteAddr()%></td>
<td><%=liveUserTracker.getSessionId()%></td>
</tr>

<%}%>
</table>
<%}%>

Portlet view in the portal page


Download Porta Live users Portlet


Important Point

Please have look into LiveUsers.java class you can find more useful methods


Please look into Java Reflection API for better understanding of invoke the methods


Recent Posts

Recent Posts Widget

Popular Posts