Liferay Portal 6:Pluggable Enterprise Search and Plugin Management

May 2010

(Read more interesting articles on Liferay Portal 6 here.)

Pluggable Enterprise Search

As an alternative to using Lucene, the portal supports pluggable search engines. The first implementation of this uses the open source search engine Solr, but in the future, there will be many such plugins for search engine of your choice, such as FAST, GSA, Coveo, and so on. In this section, we're going to discuss caching, indexing, and using Solr for search

Caching settings

EHCache is a widely-used cache implemented in Java, which the portal uses to provide distributed caching in a clustered environment. EHCache is also used in a non-clustered environment to speed up repeated data retrievals. The portal uses EHCache caching by default. At the same time, the portal uses Hibernate caching as well. The portal provides the capability to confi gure EHCache caching and Hibernate caching.

The portal has specified Hibernate as default ORM (Object-Relational Mapping) persistence in


The preceding code sets the provider hibernate used for ORM persistence. Of course, you can set this property to jpa (Java Persistence API), thus the properties with the prefi x jpa.* will be read. Similarly, if this property is set to hibernate, then the properties with the prefix hibernate.* will be read. Note that this property affects the loading of hibernate-spring.xml or jpa-spring.xml in the property spring.configs. For example, the portal has the following JPA configuration specified in


As shown in the preceding code, the property jpa.configs sets a list of commadelimited JPA configurations. The default JPA provider is set as eclipselink via the property jpa.provider. You can set it to other values such as hibernate, openjpa, and toplink. The property allow-zero-id specifies provider-specific properties prefixed with jpa.provider. property.*.On the other hand, LoadTimeWeaver interface specified via the property jpa.load.time.weaver is a Spring class that allows JPA ClassTransformer instances to be plugged in a specific manner depending on the environment. Note that not all JPA providers require a JVM agent. If your provider doesn't require an agent or you have other alternatives, the loadtime weaver shouldn't be used.

Configure Hibernate caching

First of all, let's consider Hibernate caching settings. The portal will automatically detect the Hibernate dialect. However, you can set the property in to manually override the automatically detected dialect.


The portal also specified the following properties related to Hibernate caching in

hibernate.configs=\//ignore details

As shown in the preceding code, the property hibernate.configs sets Hibernate configurations. You may input a list of comma-delimited Hibernate configurations in The property hibernate.cache.provider_class sets the Hibernate cache provider. On the other hand, the property net.sf.ehcache.configurationResourceName is used if Hibernate is confi gured to use Ehcache's cache provider, where Ehcache is recommended in a clustered environment. In a clustered environment, you need to set the property in as follows:


The portal has specified other Hibernate cache settings with properties starting with hibernate.cache.use_*. The property hibernate.jdbc.batch_size sets the JDBC batch size to improve performance. Note that if you're using Hypersonic databases or Oracle 9i, you should set the batch size to 0 as a workaround for a logging bug in the Hypersonic database driver or Oracle 9i driver.

In addition, the property hibernate.query.factory_class sets the classic query factory, whereas the portal sets the property hibernate.generate_statistics to false. Of course, you could set the property hibernate.generate_statistics to true to enable Hibernate cache monitoring in

Setting up EHCache caching

The portal has specified the following EHCache caching settings in


As shown in the preceding code, the property ehcache.single.vm.config.location sets the classpath to the location of the Ehcache configuration file / ehcache/liferay-single-vm.xml for internal caches of a single VM, whereas the property ehcache.multi.vm.config.location sets the classpath to the location of the Ehcache configuration file /ehcache/liferay-multi-vm.xml for internal caches of multiple VMs. In a clustered environment, you need to set the following in


In addition, the portal sets the property ehcache.portal.cache.manager.jmx.enabled to true to enable JMX integration in com.liferay.portal.cache.EhcachePortalCacheManager. Moreover, the portal sets the property ehcache.blocking.cache.allowed to, true to allow Ehcache to use blocking caches. This improves performance signifi cantly by locking on keys instead of the entire cache. The drawback is that threads can hang if the cache isn't used properly. Therefore, make sure that all queries that return a miss also immediately populate the cache, or else other threads that are blocked on a query of that same key will continue to hang.

Of course, you can override the preceding properties in


As you can see, the property net.sf.ehcache.configurationResourceName can have the value /ehcache/hibernate.xml for a non-clustered environment and /ehcache/hibernate-clustered.xml for a clustered environment. The propertynet.sf.ehcache.configurationResourceName can have the value /ehcache/hibernate.xml for a non-clustered environment and /ehcache/hibernateclustered.xml for a clustered environment.

In the same pattern, the property ehcache.single.vm.config.location can havethe value /ehcache/liferay-single-vm.xml and the property ehcache.multi.vm.config.location can have the value /ehcache/liferay-multi-vm.xml for a non-clustered environment.

ehcache.multi.vm.config.location has a value /ehcache/liferay-multi-vmclustered.xml for a clustered environment.

In real cases, you may need to update both Hibernate caching settings and Ehcache caching settings, either in a non-clustered environment or in a clustered environment. The following is an example of how to do this:

  1. Create a folder named ext-ehcache under the folder $PORTAL_ROOT_HOME/WEB-INF/classes/. Obviously, you can have different names for the folder ${}. Here we use the folder ext-ehcache of ${} as an example
  2. Locate the JAR file portal-impl.jarunder the folder $PORTAL_ROOT_HOME/WEB-INF/lib and unzip all the fi les under the folder ehcache into the folder $PORTAL_ROOT_HOME/WEB-INF/classes/ext-ehcache.
  3. Update following fi les according to your requirements for both a non-clustered environment and a clustered environment.
  4. hibernate.xml
  5. Set the following for a non-clustered environment in
  7. Otherwise, set the following for a clustered environment in

That's it! You have customized both the both Hibernate caching settings and Ehcache caching settings


Indexing settings

Search engine indexing collects, parses, and stores data to facilitate fast and accurate information retrieval. Apache Lucene is a high-performance, full-featured text search engine library written entirely in Java-based indexing. It is a technology suitable for nearly any application that requires full-text search, especially cross-platform. Refer to for more information. By default, the portal uses Lucene search and indexing.

Lucene search

The portal sets the default Lucene index on start-up to false for faster performance, as follows,in

As you can see, the portal sets the property to false to allow any writes to the index. You should set it to true if you want to avoid any writes to the index. This is useful in some clustering environments where there is a shared index, and only one node of the cluster updates it.

The portal sets the property index.on.startup to false in order to avoid indexing on every startup. You could set this property to true if you want to index your entire library of files on startup. This property is available so that automated test environments index the files on startup.

Don't set this to true on production systems, or else your index data will be indexed on every startup.

The property index.on.startup.delay adds a delay before indexing on startup. A delay may be necessary if a lot of plugins need to be loaded and re-indexed. Note that this property is only valid if the property index.on.startup is set to true.

In addition, the portal sets the property index.with.thread to true to allow indexing on startup to be executed on a separate thread to speed up execution.

Of course, you could re-index either all resources or an individual resource through web UI. For example, for re-indexing all search indexing, you can go to Control Panel | Server | Server Administration | Resources | Actions, and click on the button Execute next to the "Reindex all search indexes" option.

Suppose that you're going to re-index individual resource like Users, you can use the Plugin Installation portlet in the Control Panel. Go to Control Panel | Server | Plugin Installation | Portlet Plugins, and click on the button Reindex next to the portlet Users.

Index storage

Lucene stores could be in the filesystem, the database, or in RAM. Anyway, the portal provides a set of properties to configure index storage as follows in*

As shown in the preceding code, the property designates whether Lucene stores indexes in a database via JDBC, filesystem, or in RAM. The default setting is filesystem. When using Lucene's storage of indexes via JDBC, temporary files don't get removed properly. This can eat up disk space over time. Thus set the property to true to automatically clean up the temporary files once a day.

The property* sets the JDBC dialect so that Lucene can use it to store indexes in the database. This property is referenced only when Lucene stores indexes in the database. The portal will attempt to load the proper dialect based on the URL of the JDBC connection.

The property lucene.dir sets the directory where Lucene indexes are stored. This is referenced only when Lucene stores indexes in the filesystem. In a clustered environment, you could point the property lucene.dir to a shared folder, which is accessible for all nodes. More interestingly, you could set one node to allow any writes to the indexes via the property and set the rest of nodes to allow read only.

The property lucene.file.extractor specifies a class, called by Lucene to extract text from complex fi les so that they can be properly indexed. The file extractor can sometimes return text that isn't valid for Lucene. The property lucene.file. extractor.regexp.strip expects a regular expression. Any character that doesn't match the regular expression will be replaced with a blank space. You can set an empty regular expression to disable this feature. The property lucene.analyzer sets the default analyzer used for indexing and retrieval.

In addition, the property lucene.commit.batch.size sets how often index updates will be committed. Set the batch size to confi gure how many consecutive updates will trigger a commit. If the value is 0, then the index will be committed on every update. The property lucene.commit.time.interval sets the time interval in milliseconds to confi gure how often to commit the index. The time interval isn't read unless the batch size is greater than 0 because the time interval works in conjunction with the batch size to guarantee that the index is committed after a specifi ed time interval. The portal sets the time interval to 0 to disable committing the index by a time interval.

The property lucene.buffer.size sets Lucene's buffer size in megabytes and the property lucene.merge.factor sets Lucene's merge factor. For both of these properties, higher numbers mean that indexing goes faster but uses more memory. The default value from Lucene is 10. Note that this should never be set to a number less than 2. The property lucene.optimize.interval sets how often to run Lucene's optimize method. Optimization speeds up searching but slows down writing. You can set this property to 0 to always optimize.

Indexer framework

As mentioned earlier, you could re-index either all resources or an individual resource through web UI. For example, you could re-index out-of-the-box portlets like Users (Portlet ID 125) and plugins like the Mail portlet. This is because, in $PORTAL_ROOT_HOME/WEB-INF/liferay-portlet.xml, the portlet Users (named as enterprise_admin_users) has specified the following line:


As shown in the preceding code, the indexer-class value, which is the specified indexer framework, must be a class that implements and is called to create or update a search index for the portlet Users. Additionally, you could fi nd the indexer framework in out-of-the-box portlets such as Organizations (portlet ID 126, called enterprise_admin_organizations), Web Content (portlet ID 15), Image Gallery (Portlet ID 31), Document Library (Portlet ID 20), and so on.

Similarly the indexer-class value, which is the specified indexer framework, is also available in plugins. For example, the portlet Mail has specifi ed the following line in $AS_WEB_APP_HOME/mail-portlet/WEB-INF/liferay-portlet.xml.


In the same pattern, you may add the indexer framework in other plugins, like the Knowledge base portlet KBIndexer, which supports keyword search against titles, descriptions, content, tags, categories and category hierarchy, and "San Francisco" as oneword, and 'San Francisco' as multiple words ("San" or "Francisco") at

(Read more interesting articles on Liferay Portal 6 here.)

Solr search

Solr is the fast open source enterprise search platform, providing powerful full-text search, hit highlighting, faceted search, dynamic clustering, database integration, and rich document (for example, Word, PDF, and so on) handling. Solr is highly scalable, providing distributed search and index replication. Refer to In this section, we're going to show how to integrate Solr within the portal.

Install Solr instance

In five steps, you can install the Solr example as an instance under Tomcat. Of course, you can find similar installation processes for JBoss, Jetty, Resin, WebSphere, Weblogic, and so on.

  1. Download the latest version of Solr from, install it, and mark the root of installation folder as the variable $SOLR_HOME.
  2. Copy the WAR file $SOLR_HOME/dist/apache-solr-${solr.version}. war into $SOLR_HOME/example where ${solr.version} represents the Solr version number, that is, 1.4.0.
  3. Create a Tomcat Context fragment called solr.xml with the following lines:
  4. <?xml version="1.0" encoding="utf-8"?>
    <Context docBase="$SOLR_HOME/example/apache-solr-${solr.version}.
    war" debug="0" crossContext="true">
    <Environment name="solr/home" type="java.lang.String"
    value="$SOLR_HOME/example" override="true"/>
  5. Drop the file solr.xml into the folder $TOMCAT_AS_DIR/conf/Catalina/localhost
  6. Add the following line at the end of $TOMCAT_AS_DIR/bin/ for Linux or MacOS as follows:
    JAVA_OPTS="$JAVA_OPTS -Dsolr.solr.home=$SOLR_HOME/example/solr/
    Or add the following line at the end of $TOMCAT_AS_DIR/bin/setenv.batfor Windows as follows:
    set JAVA_OPTS=%JAVA_OPTS% -Dsolr.solr.home=$SOLR_HOME/example/


Repeat the preceding steps with different installation directories to run multiple instances of Solr side-by-side. Starting Tomcat, the Solr admin should be available at http://${}:${solr.port.number}/solr/admin, where ${} represents the Solr instance domain name, such as locahost, and ${solr.port.number} represents the Solr instance port number such as 8080.

Configuring the Solr plugin

Once the Solr instance is set, you can install the Solr plugin in the portal. How does it work?

The following is an example of how you can bring the plugin solr-web into the portal. The plugin solr-web is the Solr Search Engine implementation.

  1. Download the WAR file ${solr.web.war} from
  2. Drop the WAR file ${solr.web.war} to the folder $LIFERAY_HOME/deploy when the portal is running.


After having deployed it successfully, you should shut down the portal and Solar instance and also configure the Solr instance with the Solr plugin as follows:

  1. Open the XML configuration file $AS_WEB_APP_HOME/solr-web/WEB-INF/classes/META-INF/solr-spring.xml and update the Solr instance settings as follows:
    <bean id="solrServer"
    <constructor-arg type="java.lang.String"
    value=" http://${}:${solr.port.number}/solr"
  2. Drop the schema file schema.xml from $AS_WEB_APP_HOME/solr-web/WEBINF/conf to $SOLR_HOME/example/solr/conf in the domain ${}—replacing the existing schema file schema.xml, and restart the Solr instance and the portal.
    • Advanced full-text search capabilities optimized for high-volume web traffic
    • Standards-based open interfaces—XML,JSON, and HTTP, comprehensive HTML administration interfaces, server statistics exposed over JMX for monitoring
    • Scalability—efficient replication to other Solr search servers, flexible and adaptable with XML configuration, extensible Plugin architecture
  3. What's happening?

    The XML file solr-spring.xml under the folder $AS_WEB_APP_HOME/solr-web/WEB-INF/classes/META-INF describes how to integrate Solr in the portal via the plugin web. The following is a piece of code.

    <bean id="indexSearcher.solr" class="
    <property name="solrServer" ref="solrServer" />

    As shown in the preceding code, the XML file solr-spring.xml describes the index searcher, index writer, search engine, and so on.

    The XML file schema.xml under the folder $AS_WEB_APP_HOME/solr-web/WEB-INF/conf describes how the fields will be indexed to the Solr index. The following is a piece of code

    <fieldType name="string" class="solr.StrField"
    sortMissingLast="true" omitNorms="true" />
    <!-- ignore details -->
    <field name="comments" type="text"
    indexed="true" stored="true" />
    <!-- ignore details -->
    <solrQueryParser defaultOperator="OR" />

    As shown in the preceding code, the XML file schema.xml uniquely describes types, fields, default search field, and Solr query parser.

    In addition, there are a lot of the benefits to Solr in clustered environments. Solr can be installed in a separated Tomcat, and that is its main benefi t.

    Thus you can deal with stop words, localization, synonyms, along with other great features including:


Plugins management

The portal supports six different types of plugins out of the box—Portlets, Themes, Layout Templates, Webs, Hooks, and Ext. Note that a single plugin can contain multiple portlets, themes, and hook packages in a single WAR file logically:

  • Portlets: Web applications that run in a portion of a web page
  • Themes: Look and feel of pages
  • Layout Templates: Ways of choosing how the portlets will be arranged on a page
  • Hooks: Allow hooking into the portal's core functionality—for example, the plugin Asset Importer, a portlet with hook, which reads a fi le and converts it into web content and uses hook service
  • Webs: Regular Java EE web modules designed to work with the portal, such as ESB (Enterprise Service Bus), SSO (Single Sign-On), and so on
  • Ext: Ext environment as a plugin


Plugins installation

The use of plugins is one of the primary ways to extend the functionality of the portal. The portlet Plugins Installation (portlet ID 136) shows a list of the plugins installed and allows us to install new ones.

The Plugin Installer portlet

The portlet Plugin Installer (portlet ID 111) gives us access to the Liferay public repository. The portlet allows us to search and browse for different types of plugins such as Portlets, Themes, Layout Templates, Hooks, and Web Plugins.

To install a plugin, choose the plugin from Liferay's public repository from under the tab Browse Repository by clicking on its name. You can search and browse for different types of plugins. As you can see, you can search plugins with the following items. First log in as an administrator, then go to Control Panel | Server | Plugins Installation, and then click on the Install more portlets button.

Similarly, you can upload or download WAR files via the Plugin Installer portlet. You can also set up the configuration for hot deployment. You can then enable the hot deploy, set up display directory and destination directory, set the interval as, say 10 seconds, and blacklist threshold to something like 10. You can unpack WAR, Custom portlet.xml, Tomcat Configuration Directory, Tomcat Library Directory, Trusted Plugin Repositories, Un-trusted Plugin Repositories, Plugin Notification Enabled, Plugin Package with Updates Ignored, and so on.

How to make the Plugins Installer appear? You could simply navigate to Control Panel, then go to Server | Plugins Installation, and click on the button Install More Portlets.

Plugins administration

In order to get Plugins Installation to appear, you could navigate to Control Panel first, and then go to Server | Plugins Installation. As shown in the following screenshot, installed plugins would be displayed with a set of columns: Plugins (like Portlet, Theme, layout Template, Hook, and Web), Active, Roles, and Search Index (for portlets only). For example, the portlet Software catalog has the value Yes for Active, the values Power User and User for Roles, and a button Reindex for Search Index.

Auto Deploy

As mentioned earlier, you could install plugins manually via downloading a WAR file or by uploading a WAR file in the portlet Plugin Installer. This process is called Hot Deploy.

In addition, you could also deploy a WAR file to the portal automatically, called Auto Deploy. To do so, download the WAR file ${name.version.war} fi rst, then drop the WAR file ${name.version.war} to the folder $LIFERAY_HOME/deploy when the portal is running. That's it!

What's happening?

The portal has specified auto deploy as follows, but not limited, in

auto.deploy.listeners=\,\,\,\,\,\,\ auto.deploy.

As shown in the preceding code, the property auto.deploy.listeners takes a list of comma-delimited class names as input, which are used to process the autodeployment of WARs. The auto-deployable plugins include Ext, Hook, Layout Template, Portlet, Theme, and Web.

The portal first sets the property auto.deploy.enabled to true to enable autodeployment of layout templates, portlets. It then sets the directory to scan for layout templates, portlets, and finally, themes to auto deploy. This the main reason that you can drop the WAR file ${name.version.war} to the folder $LIFERAY_HOME/deploy for auto-deploy. The property auto.deploy.interval sets the interval in milliseconds, that is, how often to scan the resource directory for updates.

The property auto.deploy.blacklist.threshold sets the number of attempts to deploy a file before blacklisting it. Moreover, the portal sets the property auto.deploy.unpack.war to true to unpack deployed WARs. However, you should set this property to false if your application server has concurrency issues with deploying large WARs. The property auto.deploy.custom.portlet.xml is set tofalse, that is, you don't want your application server to rename portlet.xml toportlet-custom.xml. This is only needed when deploying the portal on WebSphere 6.1.x because WebSphere's portlet container will try to process a portlet at the same time at which Liferay is trying to process a portlet.

Furthermore, the portal has specified hot deploy and hot un-deploy in as follows, but its features are not limited to them.

## ignore details

As shown in the preceding code, the property hot.deploy.listeners takes a list of comma-delimited class names as input, used to process the deployment and undeployment of WARs at runtime. The hot-deployable plugins include Ext, Hook, Layout Template, Portlet, and Theme. Note that PluginPackageHotDeployListener must always be the fi rst to be deployed.

The portal has set the property hot.undeploy.enabled to true to enable the undeploying plugins. The propertyhot.undeploy.interval sets the un-deploy interval in milliseconds, depending on how long to wait for the un-deploy process to finish. On the other hand, the property hot.undeploy.on.redeploy sets the redeploy function. You can set this to true to un-deploy a plugin before deploying its new version. This property will only be used if the property hot.undeploy.enabled is set to true.

Plugins configuration

The portlet Plugins Configuration (portlet ID 132) provides the capability to configure each kind of plugin installed in the portal. You can use this portlet to configure which portal roles have access to the plugins.

For example, if you want to limit the use of the portlet Sitemap to just power users, then you can use the tab Portlets and remove the Users role and leave only the Power Users role in the field. To do this, simply click on the portlet you want, and enter the role names in the fi eld provided. Any role names that you enter here will be able to use this portlet.

How to get Plugins Configuration displayed? Firstly, you can simply navigate to the Control Panel, and then go to Portal | Plugins Configuration.

What's happening?

The portal has specified the following properties for plugins in


As shown in the preceding code, the property plugin.types takes a list of commadelimited supported plugin types as input, such as portlet, theme, layouttemplate, hook, and web. Of course, you could add custom plugin types, for example ext in The properties ,i>plugin.repositories.trusted and plugin.repositories.untrusted take a list of Liferay plugin repositories separated by characters as input. In addition, the property plugin.notifications.enabled is set to true, by default, to receive on-screen notifications whenever there is a new version of an installed plugin. You can set this property to false to avoid receiving on-screen notifi cations. How to develop your plugins? You may refer to the book Liferay Portal 5.2 System Development, Packt Publishing for details.

There's more

In this article, we have covered how to search with the pluggable enterprise and how to manage plugins

In the coming article, we will learn WAP sites, CRM integration, widgets, reporting, and auditing in detail.

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

You've been reading an excerpt of:

Liferay Portal 6 Enterprise Intranets

Explore Title