Portlet development best practices

We talked about some of the key UI best practices. Now let's talk about some of the key portlet development best practices to achieve best performance.

Limiting the use of dynamic queries

To implement the service and persistence layer in custom portlets, Liferay provides a very good code generator called Service Builder. Service Builder generates a persistence layer using the Hibernate framework. Service Builder also generates code in the Service and Persistence classes to cache responses in a multi-VM cache pool. Service Builder provides a way to define finder methods using an XML configuration. Responses of these finder methods are also cached in a multi-VM cache pool. Liferay Service Builder also provides a way to execute dynamic queries using the dynamic query API. Service Builder generates methods in the service and persistence layer to execute dynamic queries. Here is an example of dynamic query execution:

DynamicQuery query = DynamicQueryFactoryUtil.forClass(CalEvent.class)
.add(PropertyFactoryUtil.forName("groupId").in(new Long[]{new Long(1L),new Long(2L)})) .add(PropertyFactoryUtil.forName("startDate").ge(CalendarFactoryUtil.getCalendar().getTime())).addOrder(OrderFactoryUtil.asc("startDate"));
List events2 = CalEventLocalServiceUtil.dynamicQuery(query);

As shown in the preceding code snippet, a dynamic query makes it easy to query the database without creating the specific finder. But unlike regular finder methods, Liferay does not generate code to cache dynamic query responses. To cache a query response, Liferay needs a unique cache key. For regular finder methods, the key is generated from method arguments. But for a dynamic query, it will be difficult to generate a unique key from arguments. Also it will be difficult to implement cache invalidation logic for dynamic queries.

It is recommended to limit the use of dynamic queries because they are not cached. They increase the load on the database server and ultimately affect the performance of the system. They can be used along with a custom caching implementation.

Liferay caching API

In Chapter 4, Caching Best Practices, we discussed Liferay's caching capabilities in detail. We talked about different cache pools used by Liferay Portal. We talked about the cluster-enabled multi-VM cache pool and nonclustered single-VM cache pool. Liferay provides an API to add custom cache buckets in both cache pools. This API can be used by custom portlets or plugins for caching. By using Liferay's caching APIs, we can leverage Liferay's built-in cache support. We do not need to worry about cache replication, cache monitoring, or cache configuration. They are handled at the portal level.

To use Liferay's caching API, first we need to decide which cache pool we want to use. As discussed in Chapter 4, Caching Best Practices, a single-VM cache pool is ideal for resources that are unique per node and do not require cache replication. Here is an example class from a custom portlet that utilizes a single-VM pool:

package com.connectsam.development;

import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
import java.util.ArrayList;
import java.util.List;

public class SingleVMPoolExample {
  public List<String> getTestList(String key){
   List<String> listOfStrings = null;
//Retrieve List from Single-VM Pool by passing Cache Name and Key of cached object
listOfStrings = (List<String>) SingleVMPoolUtil.get("com.connectsam.development.SingleVMPoolExample",key);
    if(listOfStrings == null){
//If object not found in cache then retrieve the object from source
      listOfStrings = getSampleList();
      //Put the retrieved object in cache
SingleVMPoolUtil.put( "com.connectsam.development.SingleVMPoolExample" ,key, listOfStrings);
    }
    return listOfStrings;
  }
  private List<String> getSampleList(){
    List<String> list = new ArrayList<String>();
    list.add("Single VM List");
    return list;
  }
}

As shown in the preceding code snippet, we used the SingleVMPoolUtil class to store objects in the cache. It is recommended to define the Utility class within the custom portlet for handling cache-related functions. To use the multi-VM cache pool, we can use the exact same approach as previously mentioned. Instead of using SingleVMPoolUtil, we will need to use the MultiVMPoolUtil class to store and retrieve objects from the cache. As discussed in Chapter 4, Caching Best Practices, a multi-VM cache pool should be used for caching those resources that require cache replication across the cluster.

Coding best practices

We briefly talked about some of the key Liferay-Portal-specific best practices. But it is proven that most of the time performance issues arise from poorly-written code. For example, if database connections are not properly closed, even caching will not improve the performance. It is recommended to use standard automated code analysis tools to find out coding violations. Automated code analysis tools help us to locate performance-specific violations such as open JDBC connections, unused variables, and so on. Here are some of the popular code analysis tools:

  • PMD
  • CPD
  • FindBugs
  • SONAR

It is also required to perform manual code reviews to point out low-level design issues.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.162.51