Liferay is one of the portal frameworks based on java. You can create portlets in Liferay using Spring MVC framework. The main purpose of this post is to provide the complete solution for free text search integration with Liferay Spring MVC portlets. If I say in short, this post may be the answer of below questions:
  • How to create a portlet in Liferay using Spring MVC
  • How to use Liferay free text search functionality in custom portlet
Liferay uses Apache Lucene to provide the free text search functionality. Apache Lucene is a high-performance, full-featured text search engine library written entirely in Java.
Example Portlets

I have created below Spring MVC portlets in Liferay to understand that how we can use free text search functionality in our web site.
1.       Add Search Content Portlet: This portlet adds the content which needs to be searched. For demo purpose, I have used three fields to add the search contents: ID, Title and Description. If you see in below screen shots, I have added three hotel names as search content in terms of ID (hotel id), Title (hotel name) and Description (about hotel).
2.       Search Portlet: This portlet provides search field from where you can search the content
which have been added using above portlet ‘Add Search Content Portlet’.  For example if you want
to search keyword like ‘Kapila Resort’.  It will search this text in all added contents and will return 
the result with matching score (Ratings).

Source Code for Example Portlets

This section provides source code for example portlets. To create the spring MVC portlet in Liferay you need to consider below points:
      Adding configuration in portlet.xml, liferay-display.xml and liferay-portlet.xml
      View Render Servlet configuration in web.xml
      Spring context configuration for View Resolver and Controller
      Creating Value Objects
      Creating Controller
      Creating JSP

For more detail about creating Spring MVC portlets in Liferay please refer.
      To create ‘Add Search Content Portlet’, follow below steps:

1.       Configure ‘applicationContext.xml’ file:

xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
     <import resource="classpath:spring/applicationContext-core.xml" />
      <context:annotation-config />
      <context:component-scan base-package="your.package.mvc" />
            
            <bean id="messageSource"
                       class="org.springframework.context.support.ResourceBundleMessageSource">
                        <property name="basenames">
                                    <list>
                                                <value>messages</value>
                                    </list>
                        </property>
            </bean>
            <bean id="viewResolver"
                        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                        <property name="viewClass"
                                    value="org.springframework.web.servlet.view.JstlView" />
                        <property name="prefix" value="/WEB-INF/jsp/" />
                        <property name="suffix" value=".jsp" />
            </bean>
         <bean id="parameterMappingInterceptor"      
class="org.springframework.web.portlet.handler.ParameterMappingInterceptor"/>
            <bean id="portletMultipartResolver"class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver"/>
</beans>

2.       Add below configuration in ‘portlet.xml’ file:

<portlet>
            <portlet-name>addSearchContent</portlet-name>
            <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
            <init-param>
                        <name>contextConfigLocation</name>
                        <value>/WEB-INF/context/addSearchContent.xml</value>
            </init-param>
            <supports>
                        <mime-type>text/html</mime-type>
                        <portlet-mode>view</portlet-mode>
            </supports>
            <resource-bundle>content.messages</resource-bundle>
            <portlet-info>
                        <title>Add Search Contents Portlet</title>
            </portlet-info>
</portlet>

3.       Add below configuration in ‘liferay-portlet.xml’ file:

<portlet>
            <portlet-name>addSearchContent</portlet-name>
            <instanceable>true</instanceable>
</portlet>    
             

4.       Add below configuration in ‘liferay-display.xml’ file:

<category name="SearchPOC">
          <portlet id="addSearchContent"/>
</category>            

5.       Create ‘addSearchContent.xml’ file with below contents:

xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:util="http://www.springframework.org/schema/util"
            xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
                                                          
<bean class=
"org.springframework.web.portlet.mvc.annotation
.AnnotationMethodHandlerAdapter"/>
   
<bean id="portletModeHandlerMapping"class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
                        <property name="portletModeMap">
                                    <map>
                                                <entry key="view">
                                                <ref bean="addSearchContentController" />
                                    </entry>
                                    </map>
                        </property>
    </bean>
</beans>

6.       Create value objects:

      SearchContentVO Object

package your.package.mvc.vo;
import java.util.List;
/**
 * The Class SearchContentVO.
 *
 * @author nverma
 */
public class SearchContentVO {
    /** The id. */
    private Long id;
    /** The title. */
    private String title;
    /** The description. */
    private String description;
    /** The search contents. */
    private List searchContents;
    /**
     * Gets the id.
     *
     * @return the id
     */
    public Long getId() {
        return id;
    }
    /**
     * Sets the id.
     *
     * @param id the new id
     */
    public void setId(Long id) {
        this.id = id;
    }
    /**
     * Gets the title.
     *
     * @return the title
     */
    public String getTitle() {
        return title;
    }
    /**
     * Sets the title.
     *
     * @param title the title to set
     */
    public void setTitle(String title) {
        this.title = title;
    }
    /**
     * Gets the description.
     *
     * @return the description
     */
    public String getDescription() {
        return description;
    }
    /**
     * Sets the description.
     *
     * @param description the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }
    /**
     * Gets the search contents.
     *
     * @return the search contents
     */                                                                                                          
    public List getSearchContents() {
        return searchContents;
    }
    /**
     * Sets the search contents.
     *
     * @param searchContents the new search contents
     */
    public void setSearchContents(List searchContents) {
        this.searchContents = searchContents;
    }
}

      ‘SearchResult’ Object

package your.package.mvc.vo;
/**
 * The Class SearchResult.
 * @author nverma
 */
public class SearchResult {
    /** The id. */
    private Long id;
    /** The title. */
    private String title;
    /** The description. */
    private String description;
    /** The search score. */
    private float searchScore;
    /**
     * Gets the id.
     * @return the id
     */
    public Long getId() {
        return id;
    }
    /**
     * Sets the id.
     * @param id the new id
     */
    public void setId(Long id) {
        this.id = id;
    }
    /**
     * Gets the title.
     * @return the title
     */
    public String getTitle() {
        return title;
    }
    /**
     * Sets the title.
     * @param title the title to set
     */
    public void setTitle(String title) {
        this.title = title;
    }
    /**
     * Gets the description.
     * @return the description
     */
    public String getDescription() {
        return description;
    }
    /**
     * Sets the description.
     * @param description the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }
    /**
     * Gets the search score.
     * @return the searchScore
     */
    public float getSearchScore() {
        return searchScore;
    }
    /**
     * Sets the search score.
     * @param searchScore the searchScore to set
     */
    public void setSearchScore(float searchScore) {
        this.searchScore = searchScore;
    }
} 

7.       Create controller ‘AddSearchContentController’:

package your.package.mvc.controller;
import java.util.ArrayList;
import java.util.List;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletRequest;
import javax.portlet.RenderResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.portlet.bind.annotation.ActionMapping;
import org.springframework.web.portlet.bind.annotation.RenderMapping;
import your.package.mvc.vo.SearchContentVO;
import your.package.mvc.vo.SearchResult;
import com.liferay.portal.kernel.search.BooleanQuery;
import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.DocumentImpl;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.ParseException;
import com.liferay.portal.kernel.search.SearchEngineUtil;
import com.liferay.portal.kernel.search.SearchException;
/**
 * Controller to add search contents.
 * @author nverma
 */
@Controller("addSearchContentController")
@RequestMapping(value = "VIEW")
public class AddSearchContentController extends AbstractBaseController {
    /** The Constant LOG. */
    private static final Log LOG = LogFactory
            .getLog(AddSearchContentController.class);
    /** The Constant MODEL_ATT. */
    private static final String MODEL_ATT = "searchContentVO";
    /**
     * Inits the command object.
     *
     * @param portletRequest the portlet request
     * @return the search content vo
     */
    @ModelAttribute(MODEL_ATT)
    public SearchContentVO initCommandObject(final PortletRequest portletRequest) {
        LOG.debug("Initializing command object 'SearchContentVO'...");
        SearchContentVO searchContentVO = new SearchContentVO();
       searchContentVO.setSearchContents(allItems());
        return searchContentVO;
    }
    /**
     * Render add search content.
     *
     * @param renderResponse the render response
     * @return the string
     */
    @RenderMapping
    public String renderAddSearchContent(final RenderResponse renderResponse) {
        return "addSearchContent";
    }
    /**
     * Adds the search contents.
     *
     * @param searchContentVO the search content vo
     * @param actionRequest the action request
     * @param actionResponse the action response
     */
    @ActionMapping(params = "action=addSearchContent")
    public void addSearchContents(@ModelAttribute SearchContentVO searchContentVO,
            final ActionRequest actionRequest, ActionResponse actionResponse) {

        // Adding Search Document
        Document document = new DocumentImpl();
        document.addKeyword("Id", searchContentVO.getId());
        document.addText(Field.TITLE, searchContentVO.getTitle());
        document.addText("description", searchContentVO.getDescription());
        document.addText("AllDocuments""OnlyMyItems");
        try {
            LOG.info("Adding search content...");
            SearchEngineUtil.addDocument(10132, document);    
            LOG.info("Added search content successfully.");
        } catch (SearchException e) {

            LOG.error("Failed to add search document." +e.getMessage());
        }
        searchContentVO.setSearchContents(allItems());
     }
    /**
     * Delete search contents.
     *
     * @param searchContentVO the search content vo
     * @param actionRequest the action request
     * @param actionResponse the action response
     */
    @ActionMapping(params = "action=deleteSearchContent")
    public void deleteSearchContents(@ModelAttribute SearchContentVO searchContentVO,
            final ActionRequest actionRequest, ActionResponse actionResponse) {
        try {
            LOG.info("Deleting search content...["+searchContentVO.getId()+"]");
            SearchEngineUtil.deleteDocument(10132, String.valueOf(searchContentVO.getId()));
            LOG.info("Deleted search content successfully.");
        } catch (SearchException e) {
            LOG.error("Failed to deleted search document." +e.getMessage());
        }
        searchContentVO.setSearchContents(allItems());
    }
   /**
    * All items.
    *
    * @return the list
    */
   public  List allItems(){
       List searchResultLst = new ArrayList();
       Document[] resultDocs = null;
       Hits hits = null;
       BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
       try {
           searchQuery.addTerm("AllDocuments""OnlyMyItems");
           hits = SearchEngineUtil.search(10132, searchQuery, -1, -1);
           resultDocs = hits.getDocs();
       } catch (ParseException e) {
           LOG.error("Failed to parse while searching. " + e.getMessage());
           e.printStackTrace();
       } catch (SearchException e) {

           LOG.error("Failed to search. " + e.getMessage());
           e.printStackTrace();
       }
       for (int i = 0; i < resultDocs.length; i++) {
           LOG.debug("Searched Items: ");
           SearchResult searchResult = new SearchResult();
           LOG.debug("Document ->  " + hits.doc(i).get(Field.UID));
         String idStr = hits.doc(i).get("Id");
           if(idStr==null || idStr.isEmpty()){
               continue;
           }
           Long  id = Long.parseLong(idStr);
           LOG.debug("Id ->  " + id);
           searchResult.setId(id);

           String title = hits.doc(i).get(Field.TITLE);
           if(title==null || title.isEmpty()){
               continue;
           }
           LOG.debug("Title ->  " + title);
           searchResult.setTitle(title);
           String description = hits.doc(i).get("description");
           LOG.debug("Description ->  " + description);
           searchResult.setDescription(description);
           //Add search result into list
           searchResultLst.add(searchResult);
       }
       return searchResultLst;
   }
}

The API marked under arrow lines is responsible to fetch the search content from JSP and then add them into search content repository.

8.       Create JSP with name ‘addSearchContent.jsp’:

<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page contentType="text/html" isELIgnored="false"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<portlet:actionURL var="addSearchContent">
    <portlet:param name="action" value="addSearchContent" />
</portlet:actionURL>
<c:if test="${searchContentVO != null}">
         
<table>
            <tr>
                        <td>
                            <h1>Add Search Contents in Search Repository</h1>
                        </td>
            </tr>
            <tr>
              <td>
            <form:form id="search" commandName="searchContentVO" action="${addSearchContent}">
                        <table border=0>
            <tr>
                        <td width=80 align = "center"><b>ID</b></td>
                        <td width=80 align = "center"><b>Title</b></td>
                        <td width=80 align = "center"><b>Description</b></td>                                             </tr>
            <tr>
            <td width=80 align = "center"><form:input path="id" class="textfield disabledfield"/></td>
            <td width=80 align = "center"><form:input path="title" class="textfield disabledfield"/></td>
            <td width=80 align = "center"><form:input path="description" class="textfield disabledfield"/></td>                
            </tr>                                                                                        
            </table>
                        <br/>
                        <input type="submit" value="Add Search Contents"/>                        
            </form:form>
            </td>
                        <td width=150>
                        </td>
                        <td>
                        <form:form id="search2" commandName="searchContentVO" action="${addSearchContent}">
                                    <table border=0>
                                                <tr>
                                                            <td width=80 align = "center"><b>ID</b></td>
                                                </tr>
                                               
                                                <tr>
                        <td width=80 align = "center"><form:input path="id" class="textfield disabledfield"/></td>
                                    </tr>                            
                                                         
                        </table>
                                    <br/>
                                    <input type="submit" value="Delete Search Content"/>                     
                                    </form:form>
                                    </td>
                        </table>
                        <br/>
                        <br/>
                        <h1>Added Search Contents in Search Repository</h1>
                       
                        <table border=1>
                                                <tr height=50>
                                                            <td width=80 align = "center"><b>ID</b></td>
                                                            <td width=250 align = "center"><b>Title</b></td>
                                                            <td width=480 align = "center"><b>Description</b></td>                                          
                                                </tr>
                                    <c:forEach var="searchContent" items="${searchContentVO.searchContents}">
                       
                                                <tr height=50>
                                                <td width=80 align = "center">${searchContent.id}</td>
                                                <td width=250 align = "center">${searchContent.title}</td>
                                                <td width=480>${searchContent.description}</td>                    
                                                </tr>
                
                                    </c:forEach>
                        </table>                                                 
</c:if> 
<br/>           

      To create ‘Search Portlet’, follow below steps:
1.       Add below configuration in ‘portlet.xml’ file:

<portlet>
                        <portlet-name>search</portlet-name>
                        <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
                        <init-param>
                                    <name>contextConfigLocation</name>
                                    <value>/WEB-INF/context/search.xml</value>
                        </init-param>
                        <supports>
                                    <mime-type>text/html</mime-type>
                                    <portlet-mode>view</portlet-mode>
                        </supports>
                        <resource-bundle>content.messages</resource-bundle>
                        <portlet-info>
                                    <title>Search Portlet</title>
                        </portlet-info>
</portlet>

2.       Add below configuration in ‘liferay-portlet.xml’ file:

<portlet>
            <portlet-name>search</portlet-name>
            <instanceable>true</instanceable>
</portlet>
             

3.       Add below configuration in ‘liferay-display.xml’ file

<category name="SearchPOC">
          <portlet id="search"/>
</category>            

4.       Create ‘search.xml’ file with below contents

xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:util="http://www.springframework.org/schema/util"
            xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
                                                          
<beanclass="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
   
<bean id="portletModeHandlerMapping"class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
                        <property name="portletModeMap">
                                    <map>
                                                <entry key="view">
                                                <ref bean="searchController" />
                                    </entry>
                                    </map>
                        </property>
    </bean>
</beans>

5.       Create Value object ‘SearchVO’:

package your.package.mvc.vo;
import java.util.List;
/**
 * The Class SearchVO.
 *
 * @author nverma
 */
public class SearchVO {
    /** The no search result flag. */
    private boolean noSearchResultFlag;
    /** The search words. */
    private String searchWords;

    /** The hotel search result. */
    private List searchResult;
    /**
     * Checks if is no search result flag.
     *
     * @return true, if is no search result flag
     */
    public boolean isNoSearchResultFlag() {
        return noSearchResultFlag;
    }
    /**
     * Sets the no search result flag.
     *
     * @param noSearchResultFlag the new no search result flag
     */
    public void setNoSearchResultFlag(boolean noSearchResultFlag) {
        this.noSearchResultFlag = noSearchResultFlag;
    }
    /**
     * Gets the search words.
     *
     * @return the search words
     */
    public String getSearchWords() {
        return searchWords;
    }
    /**
     * Sets the search words.
     *
     * @param searchWords the new search words
     */
    public void setSearchWords(String searchWords) {
        this.searchWords = searchWords;
    }

    /**
     * Gets the search result.
     *
     * @return the search result
     */
    public List getSearchResult() {
        return searchResult;
    }

    /**
     * Sets the search result.
     *
     * @param searchResult the new search result
     */
    public void setSearchResult(List searchResult) {
        this.searchResult = searchResult;
    }
}

6.       Create controller  ‘SearchController’:

package your.package.controller;
import java.util.ArrayList;
import java.util.List;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletRequest;
import javax.portlet.RenderResponse;
import com.liferay.portal.kernel.search.BooleanQuery;
import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.ParseException;
import com.liferay.portal.kernel.search.SearchEngineUtil;
import com.liferay.portal.kernel.search.SearchException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.portlet.bind.annotation.ActionMapping;
import org.springframework.web.portlet.bind.annotation.RenderMapping;
import your.package.mvc.vo.SearchResult;
import your.package.mvc.vo.SearchVO;
/**
 * Controller for free text search.
 *
 * @author nverma
 */
@Controller("searchController")
@RequestMapping(value = "VIEW")
public class SearchController extends AbstractBaseController {
    /** The Constant LOG. */
    private static final Log LOG = LogFactory
            .getLog(SearchController.class);
    /** The Constant MODEL_ATT. */
    private static final String MODEL_ATT = "searchVO";
    /**
     * Inits the command object.
     *
     * @param portletRequest the portlet request
     * @return the search vo
     */
    @ModelAttribute(MODEL_ATT)
    public SearchVO initCommandObject(final PortletRequest portletRequest) {
        LOG.debug("Initializing command object 'SearchVO'...");
       return new SearchVO();
    }
    /**
     * Render search.
     *
     * @param renderResponse the render response
     * @return the string
     */
    @RenderMapping
    public String renderSearch(final RenderResponse renderResponse) {
        return "search";
    }
    /**
     * Render search result.
     *
     * @param renderResponse the render response
     * @return the string
     */
    @RenderMapping(params = "action=showSearchResult")
    public String renderSearchResult(final RenderResponse renderResponse) {
        return "search";
    }

    /**
     * Search.
     *
     * @param searchVO the search vo
     * @param actionRequest the action request
     * @param actionResponse the action response
     */
    @ActionMapping(params = "action=search")
    public void search(@ModelAttribute SearchVO searchVO,
            final ActionRequest actionRequest, ActionResponse actionResponse) {
        List searchResultLst = new ArrayList();
        String searchKeyWords = searchVO.getSearchWords();

        LOG.debug("Searing for input keywords  [" + searchKeyWords + "]...");
        Document[] resultDocs = null;
        Hits hits = null;
        BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();

        try {
            searchQuery.addTerm(Field.TITLE, searchKeyWords);
            searchQuery.addTerm("description", searchKeyWords);
            hits = SearchEngineUtil.search(10132, searchQuery, -1, -1);
            resultDocs = hits.getDocs();
        } catch (ParseException e) {
            LOG.error("Failed to parse while searching. " + e.getMessage());
            e.printStackTrace();
        } catch (SearchException e) {
            LOG.error("Failed to search. " + e.getMessage());
            e.printStackTrace();
        }
        if(hits == null || hits.getLength() == 0){
            searchVO.setNoSearchResultFlag(true);
        }
        LOG.debug(" Search result count [" + hits.getLength() + "]");
       for (int i = 0; i < resultDocs.length; i++) {
            LOG.debug("Searched Items: ");
            SearchResult searchResult = new SearchResult();
            LOG.debug("Document ->  " + hits.doc(i).get(Field.UID));
           String onlyForHotel = hits.doc(i).get("AllDocuments");
            if(!"OnlyMyItems".equals(onlyForHotel)){
                continue;
            }
       String idStr = hits.doc(i).get("Id");
            if(idStr==null || idStr.isEmpty()){
                continue;
            }
            Long  id = Long.parseLong(idStr);
            LOG.debug("Id ->  " + id);
            searchResult.setId(id);
            String title = hits.doc(i).get(Field.TITLE);
            LOG.debug("Title ->  " + title);
            searchResult.setTitle(title);

            String description = hits.doc(i).get("description");
            LOG.debug("Description ->  " + description);
            searchResult.setDescription(description);
            float score = hits.score(i);
            LOG.debug("Result Score ->  " + hits.score(i));
            searchResult.setSearchScore(score);
            //Add search result into list
            searchResultLst.add(searchResult);
        }

        searchVO.setSearchResult(searchResultLst);
       actionResponse.setRenderParameter("action""showSearchResult");

        LOG.debug("Searched successfully.");
    }
}

The API marked under arrow lines is responsible to perform the search for given keywords and set the result into VO to render on JSP.

7.       Create JSP ‘search.jsp’:

<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page contentType="text/html" isELIgnored="false"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<portlet:actionURL var="searchUrl">
    <portlet:param name="action" value="search" />
</portlet:actionURL>
<c:if test="${searchVO != null}">
   <form:form id="search" commandName="searchVO" action="${searchUrl}">
            <form:input path="searchWords"  value = "Search Words" class="textfield disabledfield"/>
       <input type="submit" value="Search"/>
   </form:form>     
</c:if> 
<br/><br/>
<h3>Search Result</h3>
<form:form id="searchItem" commandName="searchVO">
<table border=1>
                        <tr height=50>
                                    <td width=80 align = "center"><b>Search ID</b></td>
                                    <td width=250 align = "center"><b>Title</b></td>
                                    <td width=480 align = "center"><b>Description</b></td>
                                    <td width=140 align = "center"><b>Ratings</b></td>
                        </tr>
            <c:forEach var="searchResult" items="${searchVO.searchResult}">
            <tr height=50>
                                    <td width=80 align = "center"><a href="/search?searchId=${searchResult.id}">${searchResult.id}</a></td>
                                    <td width=250 align = "center"><a href="/search?searchId=${searchResult.id}">${searchResult.title}</a></td>
                                    <td width=480 align = "center"><a href="/search?searchId=${searchResult.id}">${searchResult.description}</a></td>
                               <td width=140 align = "center"><liferay-ui:ratings-score score="${searchResult.searchScore*5}"/></td>
                        </tr>
           
            </c:forEach>
</table>                                   
</form:form>

After configuring all above source files you can build your application and then deploy on application server. Access your Liferay server, add a test page and drop both portlets on test page and test the search functionality by adding search content first and then searching keywords.

                                   :) Happy Free Text Searching :)

See More:                                           


0

Add a comment

You might be seeking for the option to profile (capturing method's execution time) your spring application. Spring provides different ways to profile the application. Profiling should be treated as a separate concern and spring AOP facilitates easy approach to separate this concern. With the help of spring AOP you can profile your methods without making any changes in actual classes. 

You just need to perform pretty simple steps to configure your application for profiling using spring AOP:

In application context file, add below tag to enable the load time weaving          context:load-time-weaver      

With this configuration, AspectJ's Load-time weaver is registered with current class loader.

Why Locking is required?

When two concurrent users try to update database row simultaneously, there are absolute chances of losing data integrity. Locking comes in picture to avoid simultaneous updates and ensure data integrity.

Types of Locking

There are two types of locking, Optimistic and Pessimistic. In this post optimistic locking is described with example.

Optimistic Locking: This locking is applied on transaction commit.

I have got a problem in coding contest. In this post, I would like to share the approach to solve this problem. I would definitely not say that I have invented something new and I am not trying to reinvent the wheel again. I just described the end to end approach that I followed to solve this problem.It was really a great brain storming activity.

Jenkins is an open source tool which provides continuous integration services for software development. If you want to get more detail about Jenkins and it's history I would suggest refer this link. This post will help you installing and configuring Jenkins and creating jobs to trigger maven builds. Setting up Jenkins is not a rocket science indeed. In this post, I would like to concise the installation and configuration steps.

Peer code review is an important activity to find and fix mistakes which are overlooked during development. It helps improving both software quality as well as developers skills. Though, it’s a good process for quality improvement. But this process becomes tedious if you need to share files and send review comments through mails, you need to organize formal meetings and you need to communicate peers who are in different time zone.

If you are using Hudson as continuous integration server and you might feel lazy about accessing Hudson explicitly to check the build status or checking Hudson build status mails, there is an option to monitor Hudson build and perform build activities in Eclipse IDE itself. This post describes about installing, configuring and using the Hudson in Eclipse IDE.

As a developer or architect, you always need to draw some sequence diagrams to demonstrate or document your functionality. And of course, if you do this manually you have to spare much time for this activity. Just think about, what If sequence diagram is generated automatically and you get it free of cost. Your reaction would be ‘wow’ this is great. But the next question will be ‘how’.

If you are using JPA 2.0 with Hibernate and you want to do audit logging from middle-ware itself, I believe you landed up on the exact place where you should be. You can try audit logging in your local environment by following this post.

Required JPA/Hibernate Maven Dependencies

JPA Configuration in Spring Application Context File

For JPA/Hibernate, you need to configure entity manager, transaction, data source and JPA vendor in your ‘applicationContext.xml’ file.

If any issue is observed in production, there are two major aspects related to providing the solution. First ‘how quick you can analyze the root cause’ and second ‘how quick you can fix the issue’. Story starts from analyzing the root cause. Unless, you find the root cause, you can’t even think about providing solution for that. Can you?

Now let’s think about actual production environment. There may be multiple JVMs where application is deployed.
Loading