Hooks are a feature to catch hold of the properties and JSP files into an instance of the portal, as if catching them with a hook. Hook plugins are more powerful plugins that come to complement portlets, themes, layout templates, and web modules. A hook plugin can, but does not have to, be combined with a portlet plugin or a web plugin. For instance, the portlet called so-portlet is a portlet plugin for Social Office with hooks; a hook plugin can simply provide translation or override JSP page. In general, hooks would be very helpful tool to customize the portal without touching the code part of the portal, as shown in the following diagram. In addition, you could use hooks to provide patches for portal systems or social office products.
In general, there are several kinds of hook parameters in order:
- portal-properties (called portal properties hooks),
- language-properties (called language properties hooks),
- custom-jsp-dir (called custom JSPs hooks),
- custom-jsp-global (applying custom JSPs hooks globally or locally),
- indexer post processors (called indexer hook),
- service (called portal service hooks) – including model listeners and service wrappers,
- servlet-filter and servlet-filter-mapping (called servlet-filter hooks),
- struts-action (called portal struts action hooks)
As you can see, JSPs hooks can set a custom-jsp-dir that will overwrite portal JSPs. You can also add <custom-jsp-global>false</custom-jsp-global> (default to true) so that JSPs hooks will not apply globally but only to the current scope. Each site (or organization) can choose to have that hook apply just for that site (or organization).
In addition, Liferay allows portal JSPs to be overloaded by theme templates – this pattern will require that within the theme's templates folder the complete path to the original JSP be maintained with the file extension replaced to match that of the theme's chosen template language.
Abstracted from the Liferay development cookbook: Liferay Portal Systems Development (for liferay portal 6.1 or above version)
The indexer hook allows building a post processing system on top of the existing indexer, therefore plugin hook developers could be able to modify the search summaries, indexes, and queries. Refer to LPS-15811.
This article will show how to build sample indexer post processor hook. Let’s consider use case. As you know, the version 6.1 adds a lot of CMS (Documents and Media) features like
- Capability to manage different document types: basic document, image (Image Gallery is merged into Document Library), video, audio, etc.
- Providing Dynamic Data List (DDL) and Dynamic Data Mapping (DDM) - see blogs Dynamic Data Lists I and Dynamic Data Lists II
For the document type “Image”, we are going to add searchable keyword “Image”; while for the document type “Video”, we are going to add searchable keyword “Video”. Thus whenever you search by keyword “Image” or “Video”, you would be able to find out documents from document type “Image” or “Video”.
Implementation
You can build sample indexer post processor hook plugin in following steps.
- Create a hook project, for example, sample-indexer-post-processor-hook
- In liferay-hook.xml, add following lines
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
<indexer-post-processor>
<indexer-class-name>com.liferay.portlet.documentlibrary.model.DLFileEntry</indexer-class-name>
<indexer-post-processor-impl>com.liferay.hook.indexer.SampleIndexerPostProcessor</indexer-post-processor-impl>
</indexer-post-processor>
</hook>
As you can see, you can set indexer-class-name as a model entity like DLFileEntry: com.liferay.portlet.documentlibrary.model.DLFileEntry; and set the indexer-post-processor-impl as com.liferay.hook.indexer.SampleIndexerPostProcessor, which must implement the interface com.liferay.portal.kernel.search.IndexerPostProcessor.
- In web.xml, add following lines
<web-app>
<display-name>sample-indexer-post-processor-hook</display-name>
<listener>
<listener-class>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener</listener-class>
</listener>
<listener>
<listener-class>com.liferay.portal.kernel.servlet.HookContextListener</listener-class>
</listener>
</web-app>
- Create sample indexer post processor class: com.liferay.hook.indexer.SampleIndexerPostProcessor
public class SampleIndexerPostProcessor implements IndexerPostProcessor
{
public void postProcessContextQuery(BooleanQuery arg0, SearchContext arg1)
throws Exception {
if(_log.isDebugEnabled())
_log.debug("called postProcessContextQuery()");
}
public void postProcessDocument(Document document, Object object)
throws Exception {
DLFileEntry dLFileEntry = (DLFileEntry) object;
if(_log.isDebugEnabled())
_log.debug("called postProcessDocument(): uuid=" + dLFileEntry.getUuid() +
" title=" + dLFileEntry.getTitle() +
" dLFileEntryId=" + dLFileEntry.getFileEntryId());
String text = "";
try {
long fileEntryTypeId = dLFileEntry.getFileEntryTypeId();
DLFileEntryType dLFileEntryType = DLFileEntryTypeLocalServiceUtil.getDLFileEntryType(fileEntryTypeId);
// add your logic here
text = dLFileEntryType.getName();
} catch (Exception e) {}
if(text.length() > 0)
document.addText(Field.URL, text);
}
public void postProcessFullQuery(BooleanQuery arg0, SearchContext arg1)
throws Exception {
if(_log.isDebugEnabled())
_log.debug("called postProcessFullQuery()");
}
public void postProcessSearchQuery(BooleanQuery arg0, SearchContext arg1)
throws Exception {
if(_log.isDebugEnabled())
_log.debug("called postProcessSearchQuery()");
}
public void postProcessSummary(Summary arg0, Document arg1, Locale arg2,
String arg3, PortletURL arg4) {
if(_log.isDebugEnabled())
_log.debug("postProcessSummary()");
}
private static Log _log = LogFactoryUtil.getLog(SampleIndexerPostProcessor.class);
}
As shown in the above code, you would be able to add your own logic for summary, search query, context query and document. That’s it.
Results
search by keyword "Image"
Search by keyword "Video"
Download URL
Sample indexer post processor hook Liferay 6.1 with source code.
What’s next?
The next post would be: sample servlet-filter and servlet-filter-mapping hook in Liferay 6.1.

