Portals are all about personalization, and Liferay is no different.
I mean, there are many, many other things involved in portals other than personalization. But none of them really make sense without it.
Personalization is the dressing that makes your portal salad bearable. So, it has to be pretty good dressing.
Beyond the portal and personalization, we have the reason the portal exists at all: Portlets. Portlets are the ingredients needed to make a portal salad worth eating.
- You have your greens (the hard working portlets: E-Commerce, BI, BPM, CMS, etc.).
- Then you have your non-green veggies (Email, Forums, Blogs, Wiki, etc.).
- Finally you have your crutons and bacon bits, the stuff we know we can live without but just can't bring ourselves to leave out (social networking and other generally superfluous gadgets, widgetry, and such).
Yet it doesn't end there, it's gotta be MY salad, not someone else's... and it's gotta have MY name on it too. Who wants to eat someone else's food anyway...
That said, personalization at the portlet level is very important. There are two types of portlet personalization mechanisms available in Liferay.
- Personalization defined by the Portlet spec(s) (low fat, low cal. dressing)
- Liferay personalization (fatty, rich, tasty dressing)
Let's go through putting both to use in your Portlet application and then you can decide for yourself which best suites your diet.
Personalizaton via Portlet spec(s)
Both the 1.0 version and 2.0 (upcomming) versions of the spec define a mechanism called "user-attributes" defined as such:
"The deployment descriptor of a portlet application must define the user attribute names the portlets use. The following example shows a section of a deployment descriptor defining a few user attributes:
<portlet-app> ... <user-attribute> <description>User Given Name</description> <name>user.name.given</name> </user-attribute> <user-attribute> <description>User Last Name</description> <name>user.name.family</name> </user-attribute> <user-attribute> <description>User eMail</description> <name>user.home-info.online.email</name> </user-attribute> <user-attribute> <description>Company Organization</description> <name>user.business-info.postal.organization</name> </user-attribute> ... <portlet-app>A deployer must map the portlet application’s logical user attributes to the corresponding user attributes offered by the runtime environment. At runtime, the portlet container uses this mapping to expose user attributes to the portlets of the portlet application. User attributes of the runtime environment not mapped as part of the deployment process must not be exposed to portlets."
[JavaTM Portlet Specification, version 1.0, PLT.17.1]
This means that without having to do anything other than configuration, the portlet is requesting access to the defined user attributes. The list of available attributes can be found in the spec docs.
The next part is of course getting access to those user attributes at runtime.
Here is a complete JSP which handles getting the user.name.given attribute.
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%@ page import="javax.portlet.PortletRequest"%>
<%@ page import="java.util.Map"%>
<portlet:defineObjects />
<%
Map userInfo = (Map)renderRequest.getAttribute(PortletRequest.USER_INFO);
String givenName = (userInfo != null) ? (String)userInfo.get("user.name.given") : "";
%>
Given Name: <%= givenName %>
The result looks something like the following:
That's 100% spec complient and includes the following list of attributes:
package com.liferay.portlet;
public class UserAttributes {
// Mandatory Liferay attributes
public static final String LIFERAY_COMPANY_ID = "liferay.company.id";
public static final String LIFERAY_USER_ID = "liferay.user.id";
public static final String USER_NAME_FULL = "user.name.full";
// See page 119 of the JSR 168 spec
public static final String USER_BDATE = "user.bdate";
public static final String USER_GENDER = "user.gender";
public static final String USER_EMPLOYER = "user.employer";
public static final String USER_DEPARTMENT = "user.department";
public static final String USER_JOBTITLE = "user.jobtitle";
public static final String USER_NAME_PREFIX = "user.name.prefix";
public static final String USER_NAME_GIVEN = "user.name.given";
public static final String USER_NAME_FAMILY = "user.name.family";
public static final String USER_NAME_MIDDLE = "user.name.middle";
public static final String USER_NAME_SUFFIX = "user.name.suffix";
public static final String USER_NAME_NICKNAME = "user.name.nickName";
public static final String USER_HOME_INFO_POSTAL_NAME = "user.home-info.postal.name";
public static final String USER_HOME_INFO_POSTAL_STREET = "user.home-info.postal.street";
public static final String USER_HOME_INFO_POSTAL_CITY = "user.home-info.postal.city";
public static final String USER_HOME_INFO_POSTAL_STATEPROV = "user.home-info.postal.stateprov";
public static final String USER_HOME_INFO_POSTAL_POSTALCODE = "user.home-info.postal.postalcode";
public static final String USER_HOME_INFO_POSTAL_COUNTRY = "user.home-info.postal.country";
public static final String USER_HOME_INFO_POSTAL_ORGANIZATION = "user.home-info.postal.organization";
public static final String USER_HOME_INFO_TELECOM_TELEPHONE_INTCODE = "user.home-info.telecom.telephone.intcode";
public static final String USER_HOME_INFO_TELECOM_TELEPHONE_LOCCODE = "user.home-info.telecom.telephone.loccode";
public static final String USER_HOME_INFO_TELECOM_TELEPHONE_NUMBER = "user.home-info.telecom.telephone.number";
public static final String USER_HOME_INFO_TELECOM_TELEPHONE_EXT = "user.home-info.telecom.telephone.ext";
public static final String USER_HOME_INFO_TELECOM_TELEPHONE_COMMENT = "user.home-info.telecom.telephone.comment";
public static final String USER_HOME_INFO_TELECOM_FAX_INTCODE = "user.home-info.telecom.fax.intcode";
public static final String USER_HOME_INFO_TELECOM_FAX_LOCCODE = "user.home-info.telecom.fax.loccode";
public static final String USER_HOME_INFO_TELECOM_FAX_NUMBER = "user.home-info.telecom.fax.number";
public static final String USER_HOME_INFO_TELECOM_FAX_EXT = "user.home-info.telecom.fax.ext";
public static final String USER_HOME_INFO_TELECOM_FAX_COMMENT = "user.home-info.telecom.fax.comment";
public static final String USER_HOME_INFO_TELECOM_MOBILE_INTCODE = "user.home-info.telecom.mobile.intcode";
public static final String USER_HOME_INFO_TELECOM_MOBILE_LOCCODE = "user.home-info.telecom.mobile.loccode";
public static final String USER_HOME_INFO_TELECOM_MOBILE_NUMBER = "user.home-info.telecom.mobile.number";
public static final String USER_HOME_INFO_TELECOM_MOBILE_EXT = "user.home-info.telecom.mobile.ext";
public static final String USER_HOME_INFO_TELECOM_MOBILE_COMMENT = "user.home-info.telecom.mobile.comment";
public static final String USER_HOME_INFO_TELECOM_PAGER_INTCODE = "user.home-info.telecom.pager.intcode";
public static final String USER_HOME_INFO_TELECOM_PAGER_LOCCODE = "user.home-info.telecom.pager.loccode";
public static final String USER_HOME_INFO_TELECOM_PAGER_NUMBER = "user.home-info.telecom.pager.number";
public static final String USER_HOME_INFO_TELECOM_PAGER_EXT = "user.home-info.telecom.pager.ext";
public static final String USER_HOME_INFO_TELECOM_PAGER_COMMENT = "user.home-info.telecom.pager.comment";
public static final String USER_HOME_INFO_ONLINE_EMAIL = "user.home-info.online.email";
public static final String USER_HOME_INFO_ONLINE_URI = "user.home-info.online.uri";
public static final String USER_BUSINESS_INFO_POSTAL_NAME = "user.business-info.postal.name";
public static final String USER_BUSINESS_INFO_POSTAL_STREET = "user.business-info.postal.street";
public static final String USER_BUSINESS_INFO_POSTAL_CITY = "user.business-info.postal.city";
public static final String USER_BUSINESS_INFO_POSTAL_STATEPROV = "user.business-info.postal.stateprov";
public static final String USER_BUSINESS_INFO_POSTAL_POSTALCODE = "user.business-info.postal.postalcode";
public static final String USER_BUSINESS_INFO_POSTAL_COUNTRY = "user.business-info.postal.country";
public static final String USER_BUSINESS_INFO_POSTAL_ORGANIZATION = "user.business-info.postal.organization";
public static final String USER_BUSINESS_INFO_TELECOM_TELEPHONE_INTCODE = "user.business-info.telecom.telephone.intcode";
public static final String USER_BUSINESS_INFO_TELECOM_TELEPHONE_LOCCODE = "user.business-info.telecom.telephone.loccode";
public static final String USER_BUSINESS_INFO_TELECOM_TELEPHONE_NUMBER = "user.business-info.telecom.telephone.number";
public static final String USER_BUSINESS_INFO_TELECOM_TELEPHONE_EXT = "user.business-info.telecom.telephone.ext";
public static final String USER_BUSINESS_INFO_TELECOM_TELEPHONE_COMMENT = "user.business-info.telecom.telephone.comment";
public static final String USER_BUSINESS_INFO_TELECOM_FAX_INTCODE = "user.business-info.telecom.fax.intcode";
public static final String USER_BUSINESS_INFO_TELECOM_FAX_LOCCODE = "user.business-info.telecom.fax.loccode";
public static final String USER_BUSINESS_INFO_TELECOM_FAX_NUMBER = "user.business-info.telecom.fax.number";
public static final String USER_BUSINESS_INFO_TELECOM_FAX_EXT = "user.business-info.telecom.fax.ext";
public static final String USER_BUSINESS_INFO_TELECOM_FAX_COMMENT = "user.business-info.telecom.fax.comment";
public static final String USER_BUSINESS_INFO_TELECOM_MOBILE_INTCODE = "user.business-info.telecom.mobile.intcode";
public static final String USER_BUSINESS_INFO_TELECOM_MOBILE_LOCCODE = "user.business-info.telecom.mobile.loccode";
public static final String USER_BUSINESS_INFO_TELECOM_MOBILE_NUMBER = "user.business-info.telecom.mobile.number";
public static final String USER_BUSINESS_INFO_TELECOM_MOBILE_EXT = "user.business-info.telecom.mobile.ext";
public static final String USER_BUSINESS_INFO_TELECOM_MOBILE_COMMENT = "user.business-info.telecom.mobile.comment";
public static final String USER_BUSINESS_INFO_TELECOM_PAGER_INTCODE = "user.business-info.telecom.pager.intcode";
public static final String USER_BUSINESS_INFO_TELECOM_PAGER_LOCCODE = "user.business-info.telecom.pager.loccode";
public static final String USER_BUSINESS_INFO_TELECOM_PAGER_NUMBER = "user.business-info.telecom.pager.number";
public static final String USER_BUSINESS_INFO_TELECOM_PAGER_EXT = "user.business-info.telecom.pager.ext";
public static final String USER_BUSINESS_INFO_TELECOM_PAGER_COMMENT = "user.business-info.telecom.pager.comment";
public static final String USER_BUSINESS_INFO_ONLINE_EMAIL = "user.business-info.online.email";
public static final String USER_BUSINESS_INFO_ONLINE_URI = "user.business-info.online.uri";
}
It should be noted that as of right now, we haven't implemented the additonal attributes defined in javax.portlet.PortletRequest.P3PUserInfos, of the current version 2.0 recommendation.
Liferay Personalizaton
Liferay personalization provides access to pojos which can be interacted with in a much richer fashion than above. It also ties your application to Liferay so, if you plan to target more than just Liferay as plaform, don't use it.
The easiest way to take avantage of Liferay personalization is to use a couple of Liferay's taglibs; more precisely, the liferay-theme and liferay-ui taglibs.
Since these are not included in a deployed portlet by default, add the following property to your liferay-plugin-package.properties file:
portal.dependency.tlds=\
liferay-ui.tld,\
liferay-theme.tld
and the following taglib definitions to your web.xml:
<taglib> <taglib-uri>http://liferay.com/tld/theme</taglib-uri> <taglib-location>/WEB-INF/tld/liferay-theme.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://liferay.com/tld/ui</taglib-uri> <taglib-location>/WEB-INF/tld/liferay-ui.tld</taglib-location> </taglib>
Now that we have the right tools available, let's start with the very simplest example that gives us the most bang.
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %> <%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %> <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> <liferay-theme:defineObjects /> <portlet:defineObjects /> <liferay-ui:user-display userId="<%= user.getUserId() %>" />
The result of the above JSP code is something like the following:
Now you might be asking yourself "Where did that user object suddenly come from?"
The answer is simple! It comes from the <liferay-theme:defineObjects /> tag we used. This tag puts a whole bunch of context sensitive objects into our JSP page context, including the com.liferay.portal.model.User pojo associated with the current user..
The objects that are injected into the pageContext by the <liferay-theme:defineObjects /> tag are:
- themeDisplay - com.liferay.portal.theme.ThemeDisplay
- company - com.liferay.portal.model.Company
- account - com.liferay.portal.model.Account (deprecated)
- user - com.liferay.portal.model.User
- realUser - com.liferay.portal.model.User
- contact - com.liferay.portal.model.Contact
- ?layout - com.liferay.portal.model.Layout
- ?layouts - List<com.liferay.portal.model.Layout>
- plid - java.lang.Long
- ?layoutTypePortlet - com.liferay.portal.model.LayoutTypePortlet
- portletGroupId - java.lang.Long
- permissionChecker - com.liferay.portal.security.permission.PermissionChecker
- locale - java.util.Locale
- timeZone - java.util.TimeZone
- theme - com.liferay.portal.model.Theme
- colorScheme - com.liferay.portal.model.ColorScheme
- portletDisplay - com.liferay.portal.theme.PortletDisplay
Wow, now that's lots of bacon!!! I like bacon!
I won't try to explain the use of all of these objects here on this post. Suffice it to say that after exploring all of these objects and the remaining tags available to you in the Liferay taglibs, you shouldn't run out of personalization options any time soon.
You can't use JSP taglibs?
Never fear! All these objects are actually obtained by various getter methods on the com.liferay.portal.theme.ThemeDisplay object. We just put them right into the page context to cut down on code.
So, all you need is the themeDisplay object, and you can get it from the portletRequest like so:
ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
themeDisplay.getCompany();
themeDisplay.getAccount();
themeDisplay.getUser();
themeDisplay.getRealUser();
themeDisplay.getContact();
if (themeDisplay.getLayout() != null) {
themeDisplay.getLayout();
}
if (themeDisplay.getLayouts() != null) {
themeDisplay.getLayouts();
}
themeDisplay.getPlid());
if (themeDisplay.getLayoutTypePortlet() != null) {
themeDisplay.getLayoutTypePortlet();
}
new Long(themeDisplay.getPortletGroupId());
themeDisplay.getPermissionChecker();
themeDisplay.getLocale();
themeDisplay.getTimeZone();
themeDisplay.getTheme();
themeDisplay.getColorScheme();
themeDisplay.getPortletDisplay(); Well, feel to ask questions about the ones for which the meanings are less than obvious. The Message Boards are also full of answers regarding various personalization topics. And remember to have a look at the API docs on the site for the methods provided from each of these objects.

