Building Personal Community in Liferay Portal 5.2

Exclusive offer: get 50% off this eBook here
Liferay Portal 5.2 Systems Development

Liferay Portal 5.2 Systems Development — Save 50%

Liferay Portal 5.2 Systems Development

£20.99    £10.50
by Jonas X. Yuan | June 2009 | Java

In this article by Jonas Yuan, we will learn how to build My Street — an example of a personal community, which is a customizable web space for parents and children. We will also address the best practices to use My Community efficiently, including dynamic query API, pop-up JavaScript, My Community settings, My Account Control Panel, user account extension, and user preferences. We will also learn how to individualize the built community using personalized preferences.

Besides public web sites, it would be nice if we could provide a personal community, that is, My Community, for each registered user. In My Community, users can have a set of public and private pages. Here you can save your favorite games, videos and playlists, and the My Street theme — your background color.

As shown in the following screenshot, there is a page my_street with a portlet myStreet, where an end user can sign up, log in, or handle an issue such as Forgot Your Password?

Building Personal Community in Liferay Portal 5.2o

When you click on the SIGN UP button, this My Street portlet will allow the end users to set up his/her account such as creating a nickname, password hint question, password hint answer, your password, and verify password. Further, as the end user, you can set up favorite games, videos and playlists, and background color.

You can have your own favorites: number of favorites displayed in My Street (for example, 4, 20, and 35) and My Street theme, (for example, default, Abby Cadabby, Bert, Big Bird, Cookie Monster, and so on). A set of default My Street themes is predefined in /cms_services/images/my_street/ under the folder $CATALINA_HOME/webapps/ and you can choose any one of them at any time. At the same time, you can upload a photo to your own Book Street web page.

When logged in, the My Street theme will be applied on Home page, Games landing page, Videos landing page, and Playlist landing page. For example, current user's My Street theme could be applied on Playlist landing page.

You may play videos, games, and playlists when you visit the web site www.bookpubstreet.com. When you find your favorite videos, games, and playlists, you can add them into My Street. As shown in the following screenshot, you could be playing a playlist Tickle Time. If you are interested in this playlist, just click on the Add to My Street button. The playlist Tickle Time will be added into My Street as your favorite playlist. In this section, we will show how to implement these features.

Building Personal Community in Liferay Portal 5.2

Customizing user model

First, let's customize user model in service.xml in order to support extended user and user preferences. To do so, use the following steps:

  1. Create a package com.ext.portlet.user in the /ext/ext-impl/src folder.
  2. Create an XML file service.xml in the package com.ext.portlet.comment and open it.
  3. Add the following lines in this file and save it:
  4. <?xml version="1.0"?><!DOCTYPE service-builder PUBLIC "-//
    Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/
    dtd/liferay-service-builder_5_2_0.dtd">
    <service-builder package-path="com.ext.portlet.user">
    <namespace>ExtUser</namespace>
    <entity name="ExtUser" uuid="false" local-service="true"
    remote-service="true"
    persistence-class="com.ext.portlet.user.service.
    persistence. ExtUserPersistenceImpl">
    <column name="userId" type="long" primary="true" />
    <column name="favorites" type="int" />
    <column name="theme" type="String" />
    <column name="printable" type="boolean" />
    <column name="plainPassword" type="String" />
    <column name="creator" type="String" />
    <column name="modifier" type="String" />
    <column name="created" type="Date" />
    <column name="modified" type="Date" />
    </entity>
    <entity name="ExtUserPreference" uuid="false"
    local-service="true" remote-service="true"
    persistence-class="com.ext.portlet.user.service.
    persistence.ExtUserPreferencePersistenceImpl">
    <column name="userPreferenceId" type="long" primary="true" />
    <column name="userId" type="long"/>
    <column name="favorite" type="String" />
    <column name="favoriteType" type="String" />
    <column name="date_" type="Date" />
    </entity>
    <exceptions>
    <exception>ExtUser</exception>
    <exception>ExtUserPreference</exception>
    </exceptions>
    </service-builder>

The code above shows the customized user model, including userId associated with USER_ table, favourites, theme, printable, plainPassword, and so on. This code also shows user preferences model, including userPreferenceId, userId, favorite (for example, game/video/playlist UID), favoriteType (for example, game/video/playlist), and the updated date date_. Of course, these models are extensible. You can extend these models for your unique current needs or future requirements.

Enter the following tables into database through command prompt:

create table ExtUser (
userId bigint not null primary key,
creator varchar(125), modifier varchar(125),
created datetime null,modified datetime null,
favorites smallint, theme varchar(125),
plainPassword varchar(125), printable boolean );
create table ExtUserPreference (
usePreferenceId bigint not null primary key,
userId bigint not null,favorite varchar(125),
favoriteType varchar(125),date_ datetime null
);

The preceding code shows the database SQL script for customized user model and user preference model. Similar to XML model ExtUser, this code shows the userId, favorites, theme, plainPassword, and printable table fields. Again, for the XML model ExtUserPreference, this code shows the userId, favorite, favoriteType, date_, and userPreferenceId table fields.

Afterwards, we need to build a service with ServiceBuilder. After preparing service.xml, you can build services. To do so, locate the XML file /ext/ext-impl/buildparent.xml, open it, add the following lines between </target> and <target name="build-service-portlet-reports">, and save it:

<target name="build-service-portlet-extUser">
<antcall target="build-service">
<param name="service.file"
value="src/com/ext/portlet/user/service.xml" />
</antcall>
</target>

When you are ready, just double-click on the Ant target build-service-portletextUser. ServiceBuilder will build related models and services for extUser and extUserPreference.


 

Building the portlet My Street

Similar to how we had built portlet Ext Comment, we can build the portlet My Street as follows:

  1. Configure the portlet My Street in both portlet-ext.xml and liferay-portlet-ext.xml files.
  2. Set title mapping in the Language-ext.properties file.
  3. Add the My Street portlet to the Book category in the liferay-display.xml file.
  4. Finally, specify Struts actions and forward paths in the struts-config.xml and tiles-defs.xml files, respectively.

Then, we need to create Struts actions as follows:

  1. Create a package com.ext.portlet.my_street.action in the folder /ext/ext-impl/src.
  2. Add the Java files ViewAction.java, EditUserAction.java, and CreateAccountAction.java in this package.
  3. Create a Java file AddUserLocalServiceUtil.java in this package and open it.
  4. Add the following methods in AddUserLocalServiceUtil.java and save it:
  5. public static ExtUser getUser(long userId){
    ExtUser user = null;
    try{
    user = ExtUserLocalServiceUtil.getExtUser(userId);
    }
    catch (Exception e){}
    if(user == null){
    user = ExtUserLocalServiceUtil.createExtUser(userId);
    try{
    ExtUserLocalServiceUtil.updateExtUser(user);
    }
    catch (Exception e) {}
    }
    return user;
    }
    public static void deleteUser(long userId) {
    try{
    ExtUserLocalServiceUtil.deleteExtUser(userId);
    }
    catch (Exception e){}
    }
    public static void updateUser(ActionRequest actionRequest,
    long userId) {
    /* ignore details */
    }
    public static List<ExtUserPreference> getUserPreferences(
    long userId, int limit){
    /* ignore details */
    }
    public static ExtUserPreference addUserPreference(
    long userId, String favorite, String favoriteType){
    /* ignore details */
    }

As shown in the code above, it shows methods to get ExtUser and ExtUserPreference, to delete ExtUser, and to add and update ExtUser and ExtUserPreference.

In addition, we need to provide default values for private page and friendly URL in portal-ext.properties as follows:

ext.default_page.my_street.private_page=false
ext.default_page.my_street.friend_url=/my_street

The code above shows the default private page of my_street as false, default friendly URL of my_street as /my_street. Therefore, you can use VM service to generate a URL in order to add videos, games, and playlists into My Street.

Adding Struts view page

Now we need to build Struts views pages view.jsp, forget_password.jsp, create_account.jsp, congratulation.jsp, and congrates_uid.jsp. The following are main steps to do so:

  1. Create a folder my_street in /ext/ext-web/docroot/html/portlet/ext/.
  2. Create JSP file pages view.jsp, view_password.jsp, userQuestions.jsp, edit_account.jsp, create_account.jsp, congratulation.jsp, and congrates_uid.jsp in /ext/ext-web/docroot/html/portlet/ext/my_street/.

Note that congrates_uid.jsp is used for the pop-up congratulation of Add to My Street. When you click on the Add to My Street button, a window with congrates_uid.jsp will pop up. userQuestions.jsp is used when the user has forgotten the password of My Street, view_password.jsp is for general view of My Street, congratulation.jsp is used to represent successful information after creating user account, and edit_account.jsp is used to create/update user account.

Liferay Portal 5.2 Systems Development Liferay Portal 5.2 Systems Development
Published: May 2009
eBook Price: £20.99
Book Price: £33.99
See more
Select your format and quantity:

 

Sharing the My Street theme

The My Street theme can be shared by other portlets on top of Liferay portal. The com.ext.portlet.user.service.ExtUserLocalServiceUtil service resides in ext-service.jar, which is a part of external services as well as that of portal-service.jar. So the other portlets, whether they are developed in Ext or in Plugins SDK, can use this service and directly get the My Street theme of the current user. The following code shows this ability:

ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute
(WebKeys.THEME_DISPLAY);
ExtUser extUser = ExtUserLocalServiceUtil.getExtUser(
themeDisplay.getUserId());
String theme = extUser.getTheme();

For instance, the portlet Playlist landing can use the code above to get the My Street theme first. Then it can display the My Street theme as background color in its view JSP file.

Adding videos, games, and playlists into My Street

We can reuse jQuery service as mentioned earlier in order to add videos, games, and playlists into My Street. First of all, we can generate a URL follows:

String shareTitle = "Add to My Street";
String url = "/c/portal/render_portlet?p_p_id=myStreet&p_l_id=" + p_l_
id + &uid=23&assetType=PLAYLIST";

Then we can get the value of p_l_id using the following code:

Layout shareLayout = ExtJournalUtil.getFriendlyURLLayout(
themeDisplay.getGroupId(), PropsUtil.get("
ext.default_page.my_street.private_page"),
PropsUtil.get("ext.default_page.my_street.friend_url"));
long p_l_id = shareLayout.getPlid();

At the same time, we need to add portlet render in ViewAction.java under the package com.ext.portlet.my_street.action.

public ActionForward render(ActionMapping mapping, ActionForm form, 
PortletConfig portletConfig, RenderRequest renderRequest,
RenderResponse renderResponse)
throws Exception {
String fwd = "portlet.ext.my_street.view";
String uid = renderRequest.getParameter(myStreetUrl_uid);
String assetType = renderRequest.getParameter
(myStreetUrl_assetType);
if(uid != null && assetType != null){
ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.
getAttribute(WebKeys.THEME_DISPLAY);
AddUserLocalServiceUtil.addUserPreference(
themeDisplay.getUserId(), uid, assetType);
fwd = "portlet.ext.my_street.congrates_uid";
}
return mapping.findForward(fwd);
}

The code above shows two rendering scenarios. If uid or assetType is null, then render a normal view. Otherwise, add user preference and, moreover, render a success view for Add to My Street. It is simple for other portlets to share this feature in order to add videos, games, or playlists into My Street. For the Add to My Street button, it generates a URL as stated above. Then it calls jQuery Liferay.PortletSharing.showShareInfo as follows:

javascript: Liferay.PortletSharing.showShareInfo("<%= url %>", 
"<%= shareTitle %>")

Using personal community efficiently

On top of the portal, all of the users get personal space that can be made public or kept private. These public and private pages will be published as a web site with a unique friendly URL. You can customize My Community (or called personal community) for example, how the space looks via the layout templates, what tools and applications are included, what goes into Document Library and Image Gallery, and who can see and access it. This would be sufficient for most of the requirements. But in some requirements, users want to have preference data as well. For example, users may want to have their own favorite games and videos. In this case, we have to extend the user table and user preferences.

Extending user account and user preferences

It would be pretty helpful to recover, and moreover extend, the user data if we know the user model very well. As shown in the following fi gure, a User may belong to Group, and Group may have many users as its members. A user may have Email Address, Address, Account, and an address may belong to a Country. More importantly, each user must have a Contact. Thus, when you recover users, keep in mind to recover contacts at the same time.

When adding user preferences, do not overwrite the user table USER_ directly. If you do so, you would have issues while upgrading your custom code to a higher version. But you can create a new table ExtUser to hold single preference data, for example 20 — the number of your favorites (videos, games, or playlists), elmo — your favorite theme, and so on. Further, you can create a new table ExtUserPreference to save multiple preferences, for example 5 favorite videos, 10 favorite games and 15 favorite playlists as mentioned earlier.

Building Personal Community in Liferay Portal 5.2

Liferay Portal 5.2 Systems Development Liferay Portal 5.2 Systems Development
Published: May 2009
eBook Price: £20.99
Book Price: £33.99
See more
Select your format and quantity:

 

Setting My Community

Liferay portal provides the ability to configure default user public and private pages (or called layouts), and default guest public pages. The maximum number of members a personal community can have is one. A user with a personal zone cannot make anyone else a member of his/her community. If you own a personal community, you can have administrative rights over the pages within the community. You can find default settings for default user public pages in the portal.properties file as follows:

default.user.public.layout.name=Welcome
default.user.public.layout.template.id=2_columns_ii
default.user.public.layout.column-1=82,23
default.user.public.layout.friendly.url=/home
default.user.public.layout.regular.theme.id=classic
default.user.public.layouts.lar=${resource.repositories.root}/deploy/
default_user_public.lar
layout.types=portlet,panel,embedded,article,url,link_to_layout
layout.user.public.layouts.enabled=true
layout.user.public.layouts.modifiable=true
layout.user.public.layouts.auto.create=true

The code above shows how to specify a LAR file that can be used to create the user private layouts. If this property was set, the previous layout properties will be ignored. It also shows default theme, default layout template, default friendly URL, and so on. The properties layout.user.public.layouts.enabled and layout. user.public.layouts.auto.create are both set to true. It means that the users will have public layouts that will be automatically created. For even more complex behavior, you can override the addDefaultUserPublicLayouts method in com.liferay.portal.events.ServicePreAction under the /portal/portal-impl/src/ folder.

Using Control Panel to manage My Account

You can also use Control Panel to manage My Account and My Pages in a uniform view. For look and feel of Control Panel, you can check theme specifications in /portal/portal-web/docroot/html/themes/control_panel. You can also find the default settings of Control Panel in the portal.properties file as follows:

control.panel.layout.name=Control Panel
control.panel.layout.friendly.url=/manage
control.panel.layout.regular.theme.id=controlpanel

The code above shows name, friendly URL, and theme of the layout for Control Panel.

By default, the portal allows the users who forgot their passwords to obtain a new one through email. This functionality will allow a second security mechanism based on reminder queries. This mechanism can be configured through several properties in the portal.properties file as follows:

users.reminder.queries.enabled=true
users.reminder.queries.custom.question.enabled=true
users.reminder.queries.questions=what-is-your-primary-frequent-flyernumber,
what-is-your-library-card-number,what-was-your-first-phonenumber,
what-was-your-first-teacher's-name,what-is-your-father'smiddle-
name

As shown in the code above, the first property enables the mechanism of reminder queries and makes them essential to obtain a new password. The second property allows the user to write his/her own question so that he/she can choose his/her own question in addition to the ones offered to him/her by default. The third property allows us to write preset reminder queries. By the way, any organization can define its own reminder queries instead of the default ones in the Control Panel.

Using dynamic query API

The Dynamic Query API provides an elegant way to define complex queries without a complex setup, or a stiff and abstract learning curve. This API allows us to leverage the existing mapping definitions through access to the Hibernate Session. The interface of the API is specified in the com.liferay.portal.kernel.dao.orm.DynamicQuery class under the folder /portal/portal-kernel/src. The following is the interface:

public DynamicQuery add(Criterion criterion);
public DynamicQuery addOrder(Order order);
public void compile(Session session); public List list();
public List list(boolean unmodifiable);
public void setLimit(int start, int end);
public DynamicQuery setProjection(Projection projection);

Subqueries, associations, projections, and aliases are the features available in Dynamic Query API. For example, let us suppose that you want to find Ext comments by classPK and classNameId. You can specify it with the Dynamic Query API as follows:

public static List<ExtComment> getComments(long classNameId, long 
classPK) throws Exception {
List<ExtComment> comments = Collections.synchronizedList(new
ArrayList<ExtComment>());
DynamicQuery query = DynamicQueryFactoryUtil.forClass(ExtComment
.class).add(PropertyFactoryUtil.forName(
"classPK").eq(new Long(classPK))).add(
PropertyFactoryUtil.forName("classNameId").
eq(new Long(classNameId)));
try{
List<Object> assets = ExtCalEventLocalServiceUtil.
dynamicQuery(query);
for (Object obj: assets) {
ExtComment asset = (ExtComment)obj;
comments.add(asset);
}
}
catch (Exception e){
return comments;
}
}

The code above shows a simple dynamic query on the ExtComment table. As mentioned earlier, we could use subquery, order, associations, projections, and aliases to find the most popular articles on the TagsAsset and JournalArtcile tables.

Using pop ups

There are two kinds of pop ups—Floating Div pop up and Window pop up. Let's look at these pop ups in detail.

Applying Floating DIV pop up

Liferay portal provides a class called Expanse.Popup to implement the Floating DIV pop up. The following JavaScript code will make an asynchronous call to a URL, which will place content in a page as follows:

showPopupDialog: function(url, title) {
new Expanse.Popup( { fixedcenter: true,
header: title, width: 400, height: 350,
url: url, modal: true } );
},

The code above shows a JavaScript function showPopupDialog. It defines a Expanse.Popup pop up with parameters: title, position, modal, width, and height. If the URL is a portlet URL, it must have the windowState parameter set to LiferayWindowstate.EXCLUSIVE. To implement a button or a link to close the pop up, you can use the code: Expanse.Popup.close(this). Moreover, you can find more information about pop ups in the JavaScript file /portal/portal-web/docroot/html/js/liferay/popup.js.

Employing window pop up

Window pop up is loaded in a new window. In order to do that, we must set the windowState parameter in the portlet URL to LiferayWindowState.POP_UP. The following code shows a slideshow as a window pop-up in Image Gallery:

function <portlet:namespace />viewSlideShow() {
var slideShowWindow = window.open('
<portlet:renderURL windowState="<%= LiferayWindowState.
POP_UP.toString() %>">
<portlet:param name="struts_action"
value="/image_gallery/view_slide_show" />
<portlet:param name="folderId"
value="<%= String.valueOf(folderId) %>" />
</portlet:renderURL>',
'slideShow','directories=no,location=no,menubar=no, resizable=yes,
scrollbars=yes,status=no, toolbar=no');
slideShowWindow.focus();
}

If you want to close the pop up, you can use the window.close() code. Further, if you want to close the parent page, you can use the opener.close() code.

Summary

This article introduced how to customize My Account and how to build My Street with personalized preferences. It also addressed the best practices to use My Community efficiently including dynamic query API, pop-up JavaScript, My Community settings, My Account Control Panel, user account extension, and user preferences.

 

 


If you have read this article you may be interested to view :


About the Author :


Jonas X. Yuan

Jonas X. Yuan is a Chief Architect of ForgeLife LLC and an expert on Liferay Portal, e-commerce, and Content Management Systems (CMS). As an open source community contributor, he has published five Liferay books from 2008 to 2012. He is also an expert on Liferay integration with Ad Server OpenX, different search engines, enterprise content including videos, audio, images, documents, and web contents, and other technologies, such as BPM Intalio and Business Intelligence Pentaho, LDAP, and SSO. He holds a Ph.D. in Computer Science from the University of Zurich, where he focused on Integrity Control in federated database systems.

He earned his M.S. and B.S. degrees from China, where he conducted research on expert systems for predicting landslides. Previously, he worked as a Project Manager and a Technical Architect in Web GIS (Geographic Information System).
He is experienced in Systems Development Lifecycle (SDLC) and has deep, hands-on skills in J2EE technologies. He developed a BPEL (Business Process Execution Language) engine called BPELPower from scratch at the NASA data center. As the chief architect, Dr. Yuan successfully led and launched several large-scale Liferay/Alfresco e-commerce projects for millions of users each month.

He has worked on the following books: Liferay Portal Enterprise Intranets, 2008; Liferay Portal 5.2 Systems Development, 2009; Liferay Portal 6 Enterprise Intranets, 2010; Liferay User Interface Development, 2010; Liferay Portal Systems Development, 2012.

Books From Packt

Apache Maven 2 Effective Implementations: RAW
Apache Maven 2 Effective Implementations: RAW

Pentaho Reporting 1.0 for Java Developers
Pentaho Reporting 1.0 for Java Developers

Drools JBoss Rules 5.0 Developer's Guide
Drools JBoss Rules 5.0 Developer's Guide

Grails 1.1 Web Application Development
Grails 1.1 Web Application Development

Seam 2.x Web Development
Seam 2.x Web Development

JBoss Drools Business Rules
JBoss Drools Business Rules

JBoss Tools 3 Developers Guide
JBoss Tools 3 Developers Guide

Spring Web Flow 2 Web Development
Spring Web Flow 2 Web Development

 


 

 

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software