Posted on 2 Comments

Setting Custom Portlet Titles in Liferay

Liferay Logo

Setting custom portlet titles in Liferay can be a little tricky. Changing the title via the portlet configuration in the frontend is easy but when it comes to reading the custom title property programmatically things seem to get a little messy.

Setting the Title

So, first of set your portlet title as usual via the portlet configuration in the frontend. That’s the easy part.

Determining Portle Title Programmatically

Then, in order to determine custom portlet titles use the following code:

ThemeDisplay themeDisplay = ((ThemeDisplay) request
  .getAttribute(WebKeys.THEME_DISPLAY));
String portletId = themeDisplay.getPortletDisplay().getId();
javax.portlet.PortletPreferences portletSetup = PortletPreferencesFactoryUtil
  .getLayoutPortletSetup(themeDisplay.getLayout(), portletId);
String portletCustomTitle = themeDisplay.getPortletDisplay()
  .getTitle();
portletCustomTitle = portletSetup.getValue("portletSetupTitle_"
  + themeDisplay.getLanguageId(), portletCustomTitle);

This code will determine the current portlet’s ID, get its preferences, determine the current namespace and finally retrieve the custom portlet title.

In case you need to read other custom portlet properties simply look up their keys in the database and use the portletSetup.getValue(“yourKey_”, …) option as shown previously.

Posted on 1 Comment

Setting Custom Timezones in Liferay

Liferay Logo

By default Liferay uses UTC as timezone. In order to set custom timezones you may choose from the following options:

  1. Create an EXT-Plugin
  2. Specify timezone in Tomcat’s setenv script

EXT-Plugin

Create an EXT-plugin (or use your existing one) and put system-ext.properties in extyour-extdocrootWEB-INFext-implsrc using the following setting:

user.timezone=Europe/Vienna

Be sure the deploy and restart Tomcat afterwards. Also, check via the Control Panel in Server Administration / System properies that the timezone attribute has been applied correctly.

Setenv Script

The other option is to set your desired timezone in Tomcat’s setenv script located in tomcat/bin by using the following command:

-Duser.timezone=Europe/Vienna

Depending on your operating system you will need to configure setenv.bat (Windows) or setenv.sh.

Liferay Developer Studio

If you happen to use Liferay Developer Studio you can easily set your desired timezone using the server properties, as shown below:

Posted on 1 Comment

Setting Custom User Model Attributes in Liferay

Liferay Logo

Oftentimes you will need to extend Liferay’s built-in User model by adding custom attributes, such as a list of preferred settings. Fortunately, Liferay provides developers with an ExpandoBridge implementation to do so.

Thus, in order to add custom attributes simply use the Custom Fields option via the Control Panel (or programmatically). Search for the User model and add your custom field(s). In order to programmatically access these properties you now have two options. First, you may iterate over all custom fields set, or access custom fields through their key.

Access List of Custom Attributes

The following code snippet shows how to access the list of custom attributes set:

Map<String, Serializable> customAttributes = userLiferay
  .getExpandoBridge().getAttributes();
Iterator<String> it = customAttributes.keySet().iterator();

while (it.hasNext()) {
  String attribute = it.next();
  Serializable attributeValue = customAttributes.get(attribute);
  System.out.println("user custom attribute " + attribute + "="
    + attributeValue);
}

NOTE:
When getting NULL instead of your desired value when using getAttribute be sure to check for corrects permissions.

Access Specific Custom Attribute

The other option is to access specific custom fields by using its key through ExpandoValueLocalServiceUtil, as shown below:

String userBookmarksString = (String) ExpandoValueLocalServiceUtil
  .getData(Long.parseLong(PropsUtil.get("default-companyId")),
    userExpBridge.getClassName(), "CUSTOM_FIELDS",
    "yourCustomField", userExpBridge.getClassPK());

Updating Custom Attributes

Finally, in case you need to update a custom field use the following code:

ExpandoValue expVal = ExpandoValueLocalServiceUtil
  .getValue(Long.parseLong(PropsUtil.get("default-companyId")),
    userExpBridge.getClassName(), "CUSTOM_FIELDS",
    "yourCustomField", userExpBridge.getClassPK());
expVal.setData("newValue");
ExpandoValueLocalServiceUtil.updateExpandoValue(expVal);

That’s it!

Posted on 1 Comment

Determining Absolute Path for FileEntry in Liferay

Liferay Logo

In case you are wondering how to determine the absolute path to FileEntry objects in Liferay (i.e. Document and Media Library elements) here is how it works.

First, add the following to your portal-ext.properties:

dl.hook.file.system.root.dir=${liferay.home}/data/document_library

Then, to calculate the absolute path for a FileEntry use the following code:

private String getDLFileAbsPath(FileEntry fileEntry) 
throws PortalException, SystemException {
  return PropsUtils.get("dl.hook.file.system.root.dir") + "/" 
    + fileEntry.getCompanyId() + "/"
    + fileEntry.getFolderId() + "/"
    + ((DLFileEntry) fileEntry.getModel()).getName() + "/"
    + fileEntry.getVersion();
}

Note that in order to get the foldername where your FileEntry resides you need to cast FileEntry to DLFileEntry, as shown above.

Posted on Leave a comment

Dynamically determine Structure IDs in Liferay

Liferay Logo

When using multiple Web Content (aka JournalArticle) structures in Liferay managing their corresponding IDs via configuration files can become a tedious task. Luckily, there is an easy way to determine structure IDs dynamically based on their title, like the following code snippet demonstrates:

private static String STRUCTUREID = null;

private String getStructureId() {
  try {
    if (STRUCTUREID != null) {
      return STRUCTUREID; // already set
    }

    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
      JournalStructure.class).add(PropertyFactoryUtil.forName("name").like(
      "%\">Your Structure Title</>%"));
			
  @SuppressWarnings("unchecked") //optional
  List<JournalStructure> structures = JournalStructureLocalServiceUtil.
    dynamicQuery(dynamicQuery, 0, 1);

  if (structures.size() < 1) {
    System.out.println("No structure found");
    return null;
  }

  STRUCTUREID = structures.get(0).getStructureId();

  System.out.println("Structure ID=" + STRUCTUREID);

  return STRUCTUREID;

} catch (SystemException e) {
    e.printStackTrace();
    return null;
  }
}
Posted on 3 Comments

Determine latest version of Web Content in Liferay

Liferay Logo

Most of the time when using Liferay’s Web Content (i.e. JournalArticle) you will want to determine the latest version to be displayed to your users. The following code snippet shows a simple solution to do so:

List<JournalArticle> articles = JournalArticleLocalServiceUtil.getStructureArticles(GROUPID, STRUCTUREID);
ListIterator<JournalArticle> it = articles.listIterator();
List<String> checkedArticleIds = new ArrayList<String>();

while (it.hasNext()) {
  JournalArticle article = it.next();

  if (checkedArticleIds.contains(article.getArticleId())) {
    continue; // previous article version already checked
  }

  JournalArticle articleLastVersion = JournalArticleLocalServiceUtil.getLatestArticle(GROUPID, article.getArticleId());

  checkedArticleIds.add(article.getArticleId());

  System.out.println("Added articleId " + article.getArticleId() + " with version " + article.getVersion());
}
Posted on Leave a comment

Determine Path to Portlet Assets in Liferay JSP Files

Liferay Logo

When developing the front end (i.e. templates and JSP files) for portlets you will definitely at some want to include/reference custom assets, such as images. Luckily, in Liferay in order to determine the path to your portlet’s assets you only need to follow two steps. In your view.jsp (or any custom JSP file for that matter):

  1. specify correct portlet taglib (Liferay 6+)
    <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
    
  2. and to reference portlet assets use request.getContextPath(), e.g.
    <img src="<%=request.getContextPath()%>/img/filter.png" />
    
  3. That’s it. This works for all assets deployed inside your portlet.

Posted on 6 Comments

Search Categories by Name or Vocabulary in Liferay 6+

Liferay Logo

When using categories (AssetCategory) for assets such as web content (i.e. JournalArticles) in Liferay one of the use cases you will most probably come across is to search for matching entries by name. Furthermore, as categories are made up of sets of vocabularies (AssetVocabulary) you might also want to search for categories matching certain vocabularies. The following code snippets demonstrates a solution based on DynamicQueries.

Search Category by Name

The first example shows how to search for a category named “Politics”:

package at.kerstner.portlet;

import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portlet.asset.model.AssetCategory;
import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;

import java.util.ArrayList;
import java.util.List;

public class DummyPortlet {

	public List getCategories() {

		List categories = new ArrayList();

		DynamicQuery query = DynamicQueryFactoryUtil.forClass(
				AssetCategory.class).add(
				PropertyFactoryUtil.forName("name").eq("Politics"));
		try {
			categories = AssetCategoryLocalServiceUtil
					.dynamicQuery(query, 0, 1); // we only want to first one
		} catch (SystemException e) {
                   // handle exception...
		}

		return categories;
	}
}

Search Category by Vocabulary

The second code snippet demonstrates how to search for categories matching the vocabulary “My Vocabulary”:

package at.kerstner.portlet;

import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portlet.asset.model.AssetCategory;
import com.liferay.portlet.asset.model.AssetVocabulary;
import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;

import java.util.ArrayList;
import java.util.List;

public class DummyPortlet {

	@SuppressWarnings("unchecked")
	public List getCategories() {

		List vocabularies = new ArrayList();
		List categories = new ArrayList();

		DynamicQuery queryVocabularies = DynamicQueryFactoryUtil.forClass(
				AssetVocabulary.class).add(
				PropertyFactoryUtil.forName("name").eq("My Vocabulary")); // first search for vocabulary
		try {
			vocabularies = AssetVocabularyLocalServiceUtil.dynamicQuery(
					queryVocabularies, 0, 1);

			if (vocabularies.size() < 1) {
				return categories;
			}

			DynamicQuery queryCategories = DynamicQueryFactoryUtil.forClass(
					AssetCategory.class).add(
					PropertyFactoryUtil.forName("vocabularyId").eq(
							vocabularies.get(0).getVocabularyId())); // then get all categories matching the vocabulary

			categories = AssetVocabularyLocalServiceUtil.dynamicQuery(
					queryCategories, 0, 100); // let's get some to show

		} catch (SystemException e) {
                   // handle exception...
		}

		return categories;
	}
}

The above code works for Liferay 6 and above.

Posted on 7 Comments

Add Email Verification to Registration Process in Liferay

Liferay Logo

By default users registering on a Liferay portals are assigned a randomly generated password and their accout is active immediately. Upon first login, users are then required to change their password. Well, to put it delicately, especially the second step in this registration process will definitely confuse some of your potential users since why do you need to change the password you just set during the registration process?

Today, most of the prominent web frameworks offer the possibility to add an additional layer of security OOTB by forcing users to verify their email address upon registration. Thus, accounts do not become active until potential users have verified their email address. Furthermore, no framework I know other than Liferay forces users to change their password on the first login after the registration process completed.

Registration Workflow with Verification

Luckily, Liferay is highly configurable and thus allows us to change the registration workflow without any changes to the code. As reference, the desired registration workflow looks as follows:

  1. The user fills out the registration form (username, email, password, first and surename, etc.)
  2. Liferay creates the account but does not yet mark it active
  3. Liferay sends a verification e-mail to the user e-mail account with a verification link that activates the account
  4. The user clicks on the link provided and Liferay finally activates the account

Now that we have defined the registration worklflow to be used how do we enable it in Liferay? Simply by editing portal-ext.properties by adding the following line:

company.security.strangers.verify=true

That’s it! Be sure to restart Tomcat (or respectively your servlet container of choice) for this settings to take effect and test your registration workflow 🙂

Posted on 2 Comments

Image Scaling in Liferay

Liferay Logo

Have you ever wondered if Liferay offer image scaling out of the box? Yes it does, you only need to enable this option!

In portal-ext.properties add:

image.auto.scale=true
image.hook.impl=com.liferay.portal.image.DLHook

The second property image.hook.impl sets the hook implementation to be used to trigger automatic data migration during an upgrade.

Requesting Scaled Images

Now in order to request scaled images simply use height and width as GET parameters, like so:

http://localhost:8080/image/journal/article?img_id=x&height=y&width=z

Caching

For performance reasons Liferay caches scaled images. Please refer to ImageUtil API for more information.

Further Readings

Further information can be obtained by consulting the Image section in the Liferay Portal 6.1 – User Guide.