Wednesday, May 11, 2016

Customize custom portlet configuration page

Using this feature we can store/change portlet related configuration at run time. Configuration page in liferay uses preferences to store the configuration.

There are two ways using which we can customize configuration page of custom portlet:

1. By using default DefaultConfigurationAction Class.
2. By using own java Class that extend  DefaultConfigurationAction  Class.


1. By using default DefaultConfigurationAction Class.

STEPS: 

Step 1. Create one project of portlet plugin type, name in this example : CustomizedPortletConfigurationPage-portlet

Step 2. Create one portlet inside created project, portlet class name in this example: CustomizedPortletConfiguration.java

Before customizing portlet configuration we will see what is portlet configuration and from where we can find  portlet configuration link.

Follow below screens:

In above last screen we can see that in configuration currently there are two tab links one for permission and one for sharing.

After customizing configuration page we will get one more link(Setup)  in configuration section

Step 3.  Add
<configuration-action-class>com.liferay.portal.kernel.portlet.DefaultConfigurationAction </configuration-action-class> in  liferay-portlet.xml just after <icon>tag,
after adding
liferay-portlet.xml looks like below:

<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_2_0.dtd">

<liferay-portlet-app>

<portlet>
<portlet-name>customized-portlet-configuration</portlet-name>
<icon>/icon.png</icon>
<configuration-action-class>com.liferay.portal.kernel.portlet.DefaultConfigurationAction </configuration-action-class>
<header-portlet-css>/css/main.css</header-portlet-css>
<footer-portlet-javascript>
/js/main.js
</footer-portlet-javascript>
<css-class-wrapper>
customized-portlet-configuration-portlet
</css-class-wrapper>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>

Step 4. Create one jsp name: configuration.jsp inside /html/customizedportletconfiguration
and paste below code in configuration.jsp

configuration.jsp

<%@page import="com.liferay.portal.kernel.util.StringPool"%>
<%@page import="javax.portlet.PortletPreferences"%>
<%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui" %>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />

 
 <h2>Select Fields and type message You Want to Show</h2>
 <liferay-portlet:actionURL portletConfiguration="true" var="configurationURL">
 </liferay-portlet:actionURL>

 <aui:form action="<%= configurationURL %>" method="post" name="fm">
<aui:input name="cmd" type="hidden" value="update" />
<aui:input name="preferences--showMessage--" type="checkbox"/>
<aui:input name="preferences--message--" type="text" />
<aui:button type="submit" value="Display Message"></aui:button>

 </aui:form>

Step 5. Give entry for configuration.jsp as config-template   for configuration mode in portlet.xml like by deafult there is view-template for view mode.
<init-param>
       <name>config-template</name>
       <value>/html/customizedportletconfiguration/configuration.jsp</value>
</init-param>

portlet.xml

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">

<portlet>
<portlet-name>customized-portlet-configuration</portlet-name>
<display-name>Customized Portlet Configuration</display-name>
<portlet-class>
com.test.CustomizedPortletConfiguration
</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/customizedportletconfiguration/view.jsp</value>
</init-param>
<init-param>
       <name>config-template</name>
       <value>/html/customizedportletconfiguration/configuration.jsp</value>
        </init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>Customized Portlet Configuration</title>
<short-title>Customized Portlet Configuration</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>

</portlet-app>

Step 6. Paste below code in view.jsp

 <%@page import="com.liferay.portal.kernel.util.StringPool"%>
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@page import="javax.portlet.PortletPreferences"%>
<portlet:defineObjects />

<%
   PortletPreferences prefs = renderRequest.getPreferences();

   String showMessage = (String)prefs.getValue("showMessage", "false");
   String message = (String)prefs.getValue("message",StringPool.BLANK);
%>
   <h4>For Show/Hide Message:- <br>Click on Gear->Configuration->Set Up</h4><br>
 
   <p>Configure Today's Message Based On preference</p>
   <table border="1" cellpadding="8">
      <tr>
 <c:if test='<%=showMessage.equalsIgnoreCase("true") %>'>
<th><p style="color:green;">Today's Message: <%=Validator.isNotNull(message) ? message : StringPool.BLANK%></p></th>
 </c:if>
</tr>
   </table>
 
Now deploy and place portlet on portal page.

Output:





















Monday, May 9, 2016

Captcha use and validation using session in liferay

In this blog we will see how to use of captcha and validate that captcha in liferay custom portlet.

In this example for validation we will get loaded captcha text value from session and matched with user entered captcha entered value.

STEPS:

Step1: Create one liferay plugin portlet project, name in this example: CaptchaValidation-portlet
and portlet name: Captcha.

Step 2: Copy below code in view.jsp page,

In below jsp code we have created one  form with captcha field and create one action url for form submission for validating captcha.
Before validating captcha we will load captcha image in that captcha input field so that user can provide captcha value for validation.
For loading captcha we are calling one serve resource url that will load captcha image.

view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>

<portlet:defineObjects />
<liferay-theme:defineObjects />

<!-- Serve resource url for loading captcha -->
<portlet:resourceURL var="loadCaptchaURL"/>

<!-- action url for submitting form for doing captcha validation... -->
<portlet:actionURL  var="validateCaptchaURL" name="validateCaptcha"/>

<liferay-ui:error key="Message" message="Invalid captcha text. Please re-Enter"/>

<aui:form action="<%=validateCaptchaURL %>" method="post" name="fm">  
   <liferay-ui:captcha url="<%=loadCaptchaURL%>">
   </liferay-ui:captcha>
   <aui:button-row>
  <aui:button type="submit" value="Validate Captcha"/>
   </aui:button-row>

</aui:form>

Step 3: Paste below code in portlet controller.(java file)

Captcha.java

package com.test;

import com.liferay.portal.kernel.captcha.CaptchaUtil;
import com.liferay.portal.kernel.servlet.SessionErrors;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.util.bridges.mvc.MVCPortlet;

import java.io.IOException;
import java.util.Enumeration;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

/**
 * Portlet implementation class Captcha
 */
public class Captcha extends MVCPortlet {


public void validateCaptcha(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
      System.out.println("inside validateCaptcha method...");

      String userEnteredCaptcha = ParamUtil.getString(actionRequest, "captchaText");
      System.out.println("userEnteredCaptcha value:::"+userEnteredCaptcha);
      try {
          boolean captchaMatched = checkCaptcha(actionRequest, userEnteredCaptcha);
          if(!captchaMatched){
          SessionErrors.add(actionRequest, "Message");
          }else{
          System.out.println("Captcha Validated Successfully");
          }
         } catch (Exception e) {
  e.printStackTrace();
}
}

/*code for matching userEntered captcha text with loaded captcha text, if matched return true else false*/
private boolean checkCaptcha(PortletRequest request,String enteredCaptchaText) throws Exception {
boolean captchaMatched = false;
PortletSession session = request.getPortletSession();
    String captchaTextFromSession = getCaptchaValueFromSession(session);
   
       if (Validator.isNotNull(captchaTextFromSession)) {
           if(enteredCaptchaText.equals(captchaTextFromSession)){
           captchaMatched = true;
       }
       }
      return captchaMatched;
 }

      /*code for getting loaded captcha text from session*/
 private String getCaptchaValueFromSession(PortletSession session) {
       Enumeration<String> atNames = session.getAttributeNames();
       while (atNames.hasMoreElements()) {
           String name = atNames.nextElement();
           if (name.contains("CAPTCHA_TEXT")) {
               String captchaValueFromSession = (String) session.getAttribute(name);
            return captchaValueFromSession;
           }
       }
       return null;
 }

/*Code inside serve resource method for loading captcha...*/
@Override
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException,
PortletException {
try {
           CaptchaUtil.serveImage(resourceRequest, resourceResponse);
           System.out.println("captcha loaded...");
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
// TODO Auto-generated method stub
super.serveResource(resourceRequest, resourceResponse);
}

}



Output:
Captcha loaded






 Entered correct captcha value

Captcha use and validation using liferay API in liferay

In this blog we will see how to use of captcha and validate that captcha in liferay custom portlet.
Liferay provides necessary API as well as tag library to implement CAPTCHA.

In this example we will validate  Captcha  using liferay API.
(CaptchaUtil.check(actionRequest);)

STEPS:

Step1: Create one liferay plugin portlet project, name in this example: CaptchaValidation-portlet
and portlet name: Captcha.

Step 2: Copy below code in view.jsp page,

In below jsp code we have created one  form with captcha field and create one action url for form submission for validating captcha.
Before validating captcha we will load captcha image in that captcha input field so that user can provide captcha value for validation.
For loading captcha we are calling one serve resource url that will load captcha image.

view.jsp

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>

<portlet:defineObjects />
<liferay-theme:defineObjects />

<!-- Serve resource url for loading captcha -->
<portlet:resourceURL var="loadCaptchaURL"/>

<!-- action url for submitting form for doing captcha validation... -->
<portlet:actionURL  var="validateCaptchaURL" name="validateCaptcha"/>

<liferay-ui:error key="errorMessage" message="Enter correct data as shown in the image"/>

<aui:form action="<%=validateCaptchaURL %>" method="post" name="fm">
   <liferay-ui:captcha url="<%=loadCaptchaURL%>" />
   <aui:button-row>
  <aui:button type="submit"/>
   </aui:button-row>

</aui:form>

Step 3: Paste below code in portlet controller.(java file)

Captcha.java

package com.test;

import com.liferay.portal.kernel.captcha.CaptchaException;
import com.liferay.portal.kernel.captcha.CaptchaUtil;
import com.liferay.portal.kernel.servlet.SessionErrors;
import com.liferay.util.bridges.mvc.MVCPortlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

/**
 * Portlet implementation class Captcha
 */
public class Captcha extends MVCPortlet {


public void validateCaptcha(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
      System.out.println("inside validateCaptcha method...");
try {
            CaptchaUtil.check(actionRequest);
            System.out.println("CAPTCHA validated successfully");
            } catch (CaptchaException e) {
            SessionErrors.add(actionRequest, "errorMessage");
         }
}

@Override
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException,
PortletException {
try {
           CaptchaUtil.serveImage(resourceRequest, resourceResponse);
           System.out.println("captcha loaded...");
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
// TODO Auto-generated method stub
super.serveResource(resourceRequest, resourceResponse);
}

}


Output:
Captcha loaded




 Entered correct captcha value






Sunday, April 17, 2016

Generate Sonar Report for Maven and Ant Project

Below Post will describe about how to generate Sonar Report for maven and ant project.

Prerequisites : 


  • JDK 1.7
  • Mysql
  • sonarqube-5.4
  • Maven
  • Ant

Download sonarqube-5.4 from here sonar 5.4 and Extract the Sonar zip file.

Create database called "sonar" in mysql. You can choose oracle also in my case i have use mysql.
Open <sonar-directory>\conf\sonar.properties
Provide your database username and password as shown below                              

sonar.jdbc.username: root
sonar.jdbc.password: root



Uncomment below Lines of code by removing "#" for mysql jdbc connection

sonar.jdbc.url: jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8

if your using oracle then Uncomment above Lines of code by removing "#" for Oracle jdbc connection.

Now, Edited the \sonarqube-5.4\sonarqube-5.4\conf\wrapper.conf file and added the JDK path,
                wrapper.java.command=C:\Program Files\Java\jdk1.7.0_79\bin\java.exe as show below :

# Path to JVM executable. By default it must be available in PATH.
# Can be an absolute path, for example:
#wrapper.java.command=/path/to/my/jdk/bin/java
wrapper.java.command=C:\Program Files\Java\jdk1.7.0_79\bin\java.exe

Now we are all set for starting sonar server so start the sonar by clicking on
\sonarqube-5.4\bin\windows-x86-64\StartSonar.bat. 

If every thing goes fine then you should see below screen :


In the above screen in highlighted area you must be seeing as "Process[web] is up". It means your server has started. Now go to your browser and type "http://localhost:9000/" you should see below screen:


sonar default user name:  admin and password: admin. You can login and can see above screen.
So far have discuss about setting and starting sonar.

Now we will test our project with sonar.

Sonar Report For Maven Project -: 

Go to your project pom,xml file and add below line into your pom.xml file inside properties tag.

<sonar.host.url>http://localhost:9000/</sonar.host.url>

below is the properties tag for my project

<properties>
<jdk.version>1.7</jdk.version>
<spring.version>2.5.6</spring.version>
<jstl.version>1.2</jstl.version>
<servletapi.version>2.5</servletapi.version>
<sonar.host.url>http://localhost:9000/</sonar.host.url>
</properties>
I assume you already have installed maven in your system if not please installed it.
Now first clean and then install your maven project and then go to project path and open command prompt and type command mvn sonar:sonar it will generate sonar report as below :


After successfully generation sonar report you refresh your "http://localhost:9000/dashboard/"
you will be able to see your project name as shown in below screen : 


This is it for generating sonar report for maven project.
Note : 
If you don't want some file to include in sonar report then use exclusion property of sonar as shown below in your pom.xml file

<sonar.exclusions>
**/test/folderOne/**,**/test/folderTwo/**
</sonar.exclusions>

if you have multiple project and you want to skip a project as a whole then keep below property in that project pom.xml file.

<sonar.skip>true</sonar.skip>

Sonar Report For Ant Project -:

Open your build.xml file of your ant project and paste below line inside <project> tag as shown below: 

<!-- Define the SonarQube global properties (the most usual way is to pass these properties via the command line) -->
<property name="sonar.host.url" value="http://localhost:9000" />

<property name="build.dir" value="docroot/WEB-INF" />
<property name="src.dir" value="${build.dir}/src" />
<property name="classes.dir" value="${build.dir}/classes" />

<property name="sonar.projectKey" value="org.codehaus.sonar:yourprojectname" />
<property name="sonar.projectName" value="yourprojectname" />
<property name="sonar.projectVersion" value="1.0" />

<property name="sonar.sources" value="${src.dir}" />
<property name="sonar.binaries" value="${build.dir}" />


<!-- ========= Define SonarQube target ========= -->
<target name="sonar">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
</taskdef>

<sonar:sonar xmlns:sonar="antlib:org.sonar.ant"/>

</target>

below is screen of my project build.xml file


I Assume you already have installed ant in your system if not please install it.
Download from here sonar-ant-task/2.2 put sonar-ant-task/2.2 into your ant lib folder.
now first clean and then deploy your ant project and then go to project path and open command prompt and type command ant sonar it will generate sonar report as below :


After successfully generation sonar report you refresh your "http://localhost:9000/dashboard/"
you will be able to see your project name as shown in below screen : 


Note : 
For skipping any file or any project same property will be used as i have mentioned for maven, But in ant it will be under sonar target tag as shown below : 

for skipping file :

<target name="sonar">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
</taskdef>
<sonar:sonar xmlns:sonar="antlib:org.sonar.ant"/>
<sonar.exclusions>**/test/folderOne/**,**/test/folderTwo/**</sonar.exclusions>
</target>

for skipping project :

<target name="sonar">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
</taskdef>
<sonar:sonar xmlns:sonar="antlib:org.sonar.ant"/>
<sonar.skip>true</sonar.skip>
</target>

This is it for generating sonar report with ant.

To see blocker/critical/major issue of your project go through the screen according to highlighted area :  








Friday, February 12, 2016

Ajaxable Search Container Liferay

Ajaxable Search Container Liferay
Objective:  we are going to create a portlet which lists all the Liferay portal user using liferay-ui search container and making it ajaxable.
Here we are going to use liferay 6.2 EE (you can do it with CE as well) and inbuilt Alloy AUI JS .
Here I am starting with creating portlet and so on so if you are interested in knowing the magic code which makes it ajaxable then move to step 4.
Step 1

                Create a liferay plugin project  with name AjaxSearchContainer . so you will have one portlet entry in portlet.xml , change the view-template parameter to /html/ajaxsc/view.jsp.  Now Create an action class com.liferay.ajaxsc.UserListAction which extends MVCPortlet. 


Note: This step is intended for users who want to create same example which I am explaining here. So if you have any confusions in creating liferay plugin project you can go through the respective examples.

Step 2

            Now create init.jsp file to keep all you imports at one place and include it inside your view.jsp and also create  user_list.jsp file which will contain our search container.


Step 3

Concept: Here from our view.jsp we have created a div which will contain the dynamically loaded searchcontainer. On document ready we are making an ajax call which will hit the serveResource method in our Action Class and there we will prepare the SearchContainer object with results, delta etc and will set searchContainer object in request attribute and will  include user_list.jsp . In out user_list.jsp we will get that searchContainer object which will be used to populate Records.

Now  inside our view.jsp we  have created a div which will contain our searchcontainer . After  that we are doing an ajax call  which will be invoked on document ready i.e from aui ready context and ajax call will invoke searveResource Method   Below is the code. Here you can see in aui ready we are including two aui modules aui-base and aui-io-plugin-deprecated.
<%@ include file="init.jsp"%>
<portlet:resourceURL var="loadUsers"></portlet:resourceURL>
<div id="<portlet:namespace/>userList">
</div>
<aui:script>
AUI().ready('aui-base', 'aui-io-plugin-deprecated',function(A) {

            var userListCon = A.one('#<portlet:namespace/>userList');
            if(userListCon) {
                        userListCon.plug(
            A.Plugin.IO,
            {
                autoLoad: false
            }
        );
                        console.log("calling resource..")
                        userListCon.io.set('uri', "<%=loadUsers%>");
                userListCon.io.start();
            }          
});
</aui:script>

Step 4
            In our action class we are getting two parameters cur and delta where cur is current page and delta is items per page. In first call we will not have these parameters available so it will have default values current page 1 and delta 5. After that we are creating iteratorURL and After that we are creating SearchContainer Object with all necessary parameters. And ultimately setting that search container as request Attribute. Here is the code..

package com.liferay.ajaxsc;

import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayWindowState;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;

import java.io.IOException;
import java.util.List;

import javax.portlet.PortletException;
import javax.portlet.PortletURL;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

public class UserListAction extends MVCPortlet{
            Log _log = LogFactoryUtil.getLog(UserListAction.class.getName());


            @Override
            public void serveResource(ResourceRequest resourceRequest,
                                    ResourceResponse resourceResponse) throws IOException,
                                    PortletException {
                        _log.info("Getting Users..");
                        int cur = ParamUtil.getInteger(resourceRequest, "cur", 1);
                        int delta = ParamUtil.getInteger(resourceRequest, "delta", 5);
                        _log.info("cur: " + cur);
                        _log.info("delta: " + delta);
                        PortletURL iteratorURL = resourceResponse.createRenderURL();
                        iteratorURL.setWindowState(LiferayWindowState.NORMAL);
                       
                        SearchContainer<User> userListSearchContainer = new SearchContainer<User>(
                                                resourceRequest, null, null, "cur", cur, delta,
                                                iteratorURL, null, "No Users found.");
                        List<User> users = null;
                        int total = 0;
                        try {
                                    users = UserLocalServiceUtil.getUsers(userListSearchContainer.getStart(), userListSearchContainer.getEnd());
                                    total = UserLocalServiceUtil.getUsersCount();
                        } catch (SystemException e) {
                                    _log.error(e.getLocalizedMessage());
                        }
                       
                        userListSearchContainer.setResults(users);
                        userListSearchContainer.setTotal(total);
                        resourceRequest.setAttribute("userListSearchContainer", userListSearchContainer);
                        include("/html/ajaxsc/user_list.jsp", resourceRequest, resourceResponse);
                       
            }

}

In the above code we are including user_list.jsp.  So our search container will be available there as a request attribute.

Step 5
            In user_list.jsp we are getting that searchcontainer object from request attribute and populating searchcontainer.  For using liferay SearchContainer we have to import liferay-ui taglib which we have included in init.jsp as below

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui" %>
<portlet:defineObjects/>
<style scoped="scoped">

div.lfr-pagination-config {

display:none;
}
</style>
Now In final step we have to write Script which will help in pagination to work without refresh.
Here is our user_list.jsp

<%@page import="com.liferay.portal.kernel.dao.search.SearchContainer"%>
<%@page import="java.util.Enumeration"%>
<%@page import="com.liferay.portal.service.UserLocalServiceUtil"%>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@page import="com.liferay.portal.model.User"%>
<%@page import="java.util.List"%>
<%@ include file="init.jsp"%>
<%
SearchContainer userListSearchContainer = (SearchContainer)request.getAttribute("userListSearchContainer");

%>
<liferay-ui:search-container searchContainer="<%=userListSearchContainer %>">
     <liferay-ui:search-container-results />
           <liferay-ui:search-container-row className="com.liferay.portal.model.User" modelVar="userModel">
                <liferay-ui:search-container-column-text name="Name" value="<%=userModel.getFullName() %>"></liferay-ui:search-container-column-text>
                <liferay-ui:search-container-column-text name="Email" value="<%=userModel.getEmailAddress()%>"></liferay-ui:search-container-column-text>
           </liferay-ui:search-container-row>
     <liferay-ui:search-iterator paginate="<%= true %>" />
</liferay-ui:search-container>

<aui:script use="aui-base,aui-io-plugin-deprecated">
   
    var userListContainer = A.one('#<portlet:namespace/>userList');
    var paginator = userListContainer.all('.taglib-search-iterator-page-iterator-bottom,.taglib-search-iterator-page-iterator-top,.lfr-pagination-page-selector,.lfr-pagination-delta-selector');

    if (userListContainer) {
        var parent = userListContainer;
        parent.plug(
            A.Plugin.IO,
            {
                autoLoad: false
            }
        );
        paginator.all('a').on(
            'click',
            function(event) {
                event.preventDefault();

                var uri = event.currentTarget.get('href');
                    
                     if(window.console && window.console.log) {
                    
                           console.log('original uri:', uri, event.currentTarget);
                     }   
               
                if (uri != 'javascript:;') {
                     uri = event.currentTarget.get('href').replace(/p_p_lifecycle=0/i, 'p_p_lifecycle=2');                 
                     if(window.console && window.console.log) {
                    
                         console.log('altered uri:', uri);
                         }

                     parent.io.set('uri', uri);
                     parent.io.start();
                 }
            }
        );
    }
</aui:script>


In the above javascript we are getting out container which we have created in view.jsp then we are getting all paginators inside that with their class . After that we have plugged the Input/output component with our container. Now we have bind click  event on pagination . So when user clicks on pagination we are replacing lifecycle value from 0 to 2 where 0 is for render phase and 2 is for resource phase so with this our pagination becomes  resource serving urls and they will invoke the serve resource method of our action class. Same process will repeat.


Note: you can see in init.jsp we have kept
                        

This will make our left side paginators hidden. Because this implementation is not supporting left side pagination.


Now we are done with all necessary steps we will check results

You can see the ajax loader clicking on next.
Hope this helps Thanks.