« Back

Indexer post processor hook in Liferay 6.1

General Blogs November 30, 2011 By Jonas Yuan

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.
 

Threaded Replies Author Date
Really cool feature, as we can do indexing... Nagendra Kumar Busam November 30, 2011 10:59 PM
Really informative. One question, is it... Sandeep Nair December 1, 2011 4:19 AM
Hi Nagendra, Are you able to download after... Jonas Yuan December 1, 2011 10:17 AM
If only this would be available for 5.2 :/ I'd... Tomas Polesovsky December 1, 2011 3:11 PM
I tried after logged into Liferay only - Not... Nagendra Kumar Busam December 1, 2011 10:15 PM
Hi Sandeep, good point. Ideally, the deploy... Jonas Yuan December 2, 2011 11:35 AM
Hi Tomas, this feature is not available in the... Jonas Yuan December 6, 2011 3:16 PM
Hi Nagendra, It is weird. The "VIEW"... Jonas Yuan December 2, 2011 11:43 AM
Nice Article. Thanks for your detailed... Kowbathullah Gnaniyar December 3, 2011 11:00 AM
Hi Nagendra & Zubair, please use teh following... Sandeep Nair December 4, 2011 10:34 PM
Hi Jonas Yuan, Is ther any way to index related... Alireza Zare December 12, 2011 12:22 AM
Hello, I've just solved my problem by using a... Alireza Zare December 12, 2011 2:31 AM
Nice! Thanks to update, Alieeza! Jonas Yuan December 12, 2011 4:40 PM
Hi, ¿Does this also work when using the Solr... Salvador Baena June 22, 2012 4:05 AM
The answer should be YES. Do you meet any... Jonas Yuan June 25, 2012 11:28 AM
Jonas, I want to index filesize field of... Amit Shah December 26, 2012 12:34 PM
Hi Jonas, thanks for the useful blog. I used it... Hugo Alvarez January 21, 2013 12:51 AM
HI, I want to filter users from search result... Nitin Yeola May 22, 2014 12:34 AM
Hi Jonas, Very nice article.I have one query... Praveen Singh Bais May 22, 2014 9:45 PM

Really cool feature, as we can do indexing through hooks (not only indexing though)

Not able to download hook attached.

Getting following error.

You do not have permission to access the requested resource.

http://www.liferay.com/documents/31578/11633350/sample-indexer-post-pro­cessor-hook-6.1.0.1.war
Posted on 11/30/11 10:59 PM.
Really informative. One question, is it necessary to add those entries in web.xml. While deploy will those be not automatically added in the web.xml
Posted on 12/1/11 4:19 AM.
Hi Nagendra,

Are you able to download after logged in?

Thanks

Jonas
Posted on 12/1/11 10:17 AM in reply to Sandeep Nair.
If only this would be available for 5.2 :/ I'd use it right now. Anyway, nice post, thanks for sharing, Jonas!
Posted on 12/1/11 3:11 PM.
I tried after logged into Liferay only - Not able to download
Posted on 12/1/11 10:15 PM.
Hi Sandeep, good point. Ideally, the deploy process should automatically add these lines in the web.xml.
Posted on 12/2/11 11:35 AM in reply to Nagendra Kumar Busam.
Hi Tomas, this feature is not available in the 5.2 and 6.0 yet. Hope that this could be back-ported in the near future.

Thanks

Jonas
Posted on 12/6/11 3:16 PM in reply to Jonas Yuan.
Hi Nagendra,

It is weird. The "VIEW" permission was assigned to the "Guest". Would you be able to download anything from the site?

Thanks

Jonas
Posted on 12/2/11 11:43 AM in reply to Jonas Yuan.
Nice Article. Thanks for your detailed explanation Jonus.

Like Nagendra, I am also getting that same error while trying to download this war file: "You do not have permission to access the requested resource."
Posted on 12/3/11 11:00 AM in reply to Jonas Yuan.
Hi Nagendra & Zubair, please use teh following link

http://www.liferay.com/documents/31578/6144150/sample-jquery-portlet-6.1.0.1­.war
Posted on 12/4/11 10:34 PM.
Hi Jonas Yuan,
Is ther any way to index related discussions with the document entry?
The indexer post processor hook is great. There is one issue in my case:
I try to post process the DLFileEntry to index the discussions related to the documents, but it doesn't work while adding comments does not update the file entry itself.
Is there any way to achieve that?

Thanks
Posted on 12/12/11 12:22 AM in reply to Sandeep Nair.
Hello,
I've just solved my problem by using a ModelListener for MBMessage.
onAfterCreate I reindex the DLEntry and then the post processor hook take over to add discussions to my index.

Regards,
Alireza
Posted on 12/12/11 2:31 AM in reply to Alireza Zare.
Nice! Thanks to update, Alieeza!
Posted on 12/12/11 4:40 PM in reply to Alireza Zare.
Hi,

¿Does this also work when using the Solr plugin?

Thanks.
Posted on 6/22/12 4:05 AM.
The answer should be YES. Do you meet any issues?

Thanks
Posted on 6/25/12 11:28 AM in reply to Salvador Baena.
Jonas,
I want to index filesize field of document library and i am using liferay 6.0. So is their any way to use this hook or i must have to go through ext.
Posted on 12/26/12 12:34 PM in reply to Jonas Yuan.
Hi Jonas, thanks for the useful blog. I used it to add metadata information extracted from a document type to its properties field. By doing so we want to be able to search for the document using not only its title and/or description but also i.e. the type of document information. So far, using the Solr plugin and cheking its index, we have seen that the metadata are added to the properties filed of the document although we are not able to search the document with these metadata yet. Are we missing something else to be done?, Should some service be extended in terms of a hook?

We would appreciate any information someone could provide us with on this matter.

Thank you very much.
Posted on 1/21/13 12:51 AM.
HI,

I want to filter users from search result on country which I select from selectbox.
How can I use index post processor for this.

Can you give example?
Posted on 5/22/14 12:34 AM.
Hi Jonas,

Very nice article.I have one query can we index other models for which the indexer is not already defined. E.g if we want to index the Address model, can that be achieved using this approach ?
Posted on 5/22/14 9:45 PM.