Using jQuery/jqGrid in Portlet with Ajax
Portlet is a java-technology-based web component desciribed in JSR 186.JSR 168 Portlet APIs and request processing is not suitable for Ajax. If we want to use ajax in a portlet, jQuery is one of the best choices. jQuery is an amazing JavaScript library that makes it easy to create wonderful web effects in just a few lines of code and it is a great library for developing AJAX based application. It has a lot of features for css manupilation, effects ,events etc. Best of it, it is very simple to use, and there are tons of tutorials. There is also a jquery-portlet library for adding namespaces to JQuery for multiple portlets displayed on the same page. Also there are many plugins for jQuery. One of my favorite is the jqGrid for manipulating tables and data grids.

In this tutorial, I will use jqGrid to build a portlet with a master-detail table. Here is a brief summary of the steps:
- Create a new portlet class.
- Add the view and edit JSP files with jQuery library.
- Add Servlet for ajax requests
- Add Portlet.xml file
Have a look at the tutorial creating portlet class and adding portlet.xml to complete these steps. We will concentrate to adding view jsp and adding servlet for ajax request.
Add the view JSP
Create jsp file which name is view.jsp with portlet tags.
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ page import="javax.portlet.PortletSession" %> <%@ page session="false" %> <portlet:defineObjects/> <div id="<portlet:namespace/>_main"> <div id="<portlet:namespace/>_content"></div> </div>
After that, add script and jss file for jQuery library after the <div id=”<portlet:namespace/>_main”> tag.
<pre><script src="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js/jquery.js") %>" type="text/javascript" ></script> <script src="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js/jquery.easing.js") %>" type="text/javascript" ></script> <script src="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js/jquery.portlet-1.0.js") %>" type="text/javascript" ></script> <script src="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js//js/jquery-ui.js") %>" type="text/javascript" ></script> <script src="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js/jquery.jqGrid.min.js") %>" type="text/javascript" ></script> <link href="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/css/smoothness/jquery-ui-1.7.2.custom.css")%>" rel="stylesheet" type="text/css" media="screen" ></link> <link href="<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/css/ui.jqgrid.css")%>" rel="stylesheet" type="text/css" media="screen" ></link>
Now add two table before <div id=”<portlet:namespace/>_content”> tag.We added two tables because we will use two jqGrid components. Id values of the tables will be used in jQuery components.
<table id="masterGrid" cellpadding="0" cellspacing="0"></table> <table id="detailGrid" cellpadding="0" cellspacing="0"></table>
Next we add the namespace that separates this portlet from the others. We use the functions available in the jqeury-portlet library for this. Without the portlet namespace, displaying multiple portlets that use jquery on the same page may cause problems. To do this Add jQuery function after css description
<script type="text/javascript">
var MasterDetailPortlet = function(nameSpace) {
var mThis = $.Portlet.call(this, nameSpace); // This extends your portlet object
mThis.ready = function() {
};
return mThis;
};
jQuery.registerPortlet(new MasterDetailPortlet("<portlet:namespace />"));
</script>
Now we will add a servlet to serv data to jqGrids.jqGtrid accepts two data formats:json and xml.In this tutorial we use xml.Because there are some libraries to convert java classes to xml easily like JAXB and XmlBeans. JAXB is a part of Java 6 and some portals don’t work with Java 6. So in this tutorial, we will use XmlBeans. The following XSD file describes our simple model.
Employee.xsd
<pre><?xml version="1.0" encoding="UTF-8"?> <schema targetNamespace="http://turkcell.com/terminal/1.0/2009" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:trm="http://turkcell.com/terminal/1.0/2009"> <element name="employee" type="trm:EmployeeCatalog"></element> <complexType name="EmployeeCatalogType"> <sequence> <element name="employeeId" type="float"> </element> <element name="name" type="string"></element> <element name="surname" type="string"></element> <element name="division" type="string"></element> <element name="detail" type="trm:EmployeeProjectInformation" minOccurs="0" maxOccurs="unbounded"></element> </sequence> </complexType> <complexType name="EmployeeProjectInformation"> <sequence> <element name="projectName" type="string"></element> <element name="startDate" type="date"></element> <element name="endDate" type="date"></element> <element name="projectStatus" type="string"></element> </sequence> </complexType> <complexType name="EmployeeCatalog"> <sequence> <element name="employeeList" type="trm:EmployeeCatalogType" minOccurs="0" maxOccurs="unbounded"></element> </sequence> </complexType> </schema>
Next, we will use XmlBeans to map XSD to Java objects. We can generate java classes from xsd file. The simple servlet gets the ID as a parameter, send data for the corresponding all employees. Master table calls this servlet with id parameter as null and gets the full list.
public class JQGridServlet extends HttpServlet{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter ();
String id=request.getParameter("id");
if(id==null){
EmployeeDocument document= EmployeeDAO.getInstance().getAllEmployeeDocument();
out.println(getStringFromXml(document));
}else{
EmployeeCatalogType catalog=EmployeeDAO.getInstance().getEmployeeCAtalogById(id);
out.println(getStringFromXml(catalog));
}
}
MASTER TABLE
Now, we can add jqGrid components. There will be two jqGrid. Id of the jqGrid ‘s are masterGrid and detailGrid.
Add these code in mThis.ready = function() for masterGrid jqGrid
$("#masterGrid").jqGrid({
url: '<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/JQGridServlet")%>',
datatype: "xml",
colNames:["EMPLOYEE ID","NAME", "SURNAME", "DIVISION"],
colModel:[
{name:"EMPLOYEE",index:"Author", width:120, xmlmap:"employeeId"},
{name:"NAME",index:"Title", width:180,xmlmap:"name"},
{name:"SURNAME",index:"Manufacturer", width:100, align:"right",xmlmap:"surname"},
{name:"DIVISION",index:"ProductGroup", width:130,xmlmap:"division"}
],
height:100,
rowNum:10,
rowList:[10,20,30],
viewrecords: true,
loadonce: true,
xmlReader: {
root :"employee",
row: "employeeList",
repeatitems: false,
id: "employeeId"
},
caption: "Master Table",
onSelectRow: function(ids)
{
$("#detailTable").setGridParam({ datatype: 'xml',url:'<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/JQGridServlet")%>?id='+ids}).trigger("reloadGrid");
$("#detailTable").setCaption("DETAIL TABLE- SELECTED_ID=: "+ids)
;
}
});
Let me explain the parameters:
$(“#masterGrid”):points to <table id=”masterGrid”>
url : url of data , in this example /JQGridServlet servlet
datatype:format of data
height :height of table
caption:caption of table
xmlReader :This is the most important tag.This is a sample xml data
<?xml version="1.0" encoding="UTF-8"?>
<employee xmlns="http://turkcell.com/terminal/1.0/2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://turkcell.com/terminal/1.0/2009 Employee.xsd ">
<employeeList>
<employeeId>0.0</employeeId>
<name>name</name>
<surname>surname</surname>
<division>division</division>
<detail>
<projectName>projectName</projectName>
<startDate>2001-01-01</startDate>
<endDate>2001-01-01</endDate>
<projectStatus>projectStatus</projectStatus>
</detail>
</employeeList>
</employee>
in xmlReader
root:root of xml data
row : information for particular row
id :id of the row,(will be used when row selected)
colNames : Column names
colModel :column attributes
xmlMap in colModel:attribute name in the xml
onSelectRow: select event.We will explain later.
DETAIL TABLE
Add these code in mThis.ready = function() for detailGrid jqGrid
$("#detailTable").jqGrid({
url: '<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/JQGridServlet")%>',
datatype: "xml",
colNames:["PROJECT NAME","STATUS", "START DATE", "END DATE"],
colModel:[
{name:"Author",index:"Author", width:120, xmlmap:"projectName"},
{name:"Title",index:"Title", width:180,xmlmap:"startDate"},
{name:"Price",index:"Manufacturer", width:100, align:"right",xmlmap:"endDate"},
{name:"DatePub",index:"ProductGroup", width:130,xmlmap:"projectStatus"}
],
height:100,
rowNum:10,
rowList:[10,20,30],
viewrecords: true,
loadonce: true,
xmlReader: {
root :"xml-fragment",
row: "detail",
repeatitems: false,
id: "employeeId"
},
caption: "Detail Table",
});
Now, we have two jqGrid in page….
onSelect Event
Our purpose is, when we select a row in masterTable,we want to see detail of the selected record in detailTable table
We can do it by onSelectRow event in masterTable.
onSelectRow: function(ids)
{
$("#detailTable").setGridParam({ datatype: 'xml',url:'<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/JQGridServlet")%>?id='+ids}).trigger("reloadGrid");
$("#detailTable").setCaption("DETAIL TABLE- SELECTED_ID=: "+ids)
;
}
Lets look at parameters:
onSelectRow:function(ids) : ids means is ‘id of the selected row’.Id of the row can be configured by id element in xmlReader.
$(“#detailTable”).setGridParam : This method is used for setting parameters of jqGrid.This example we set datatype and url.In fact, there is no need to set datatype. Because datatype is no changed.But in my environment,it doesnt work without datatype.When setting url, we add id parameter to the url.Thus, JQGridServlet can detect by id which element we want.So we can see selected element’s data in detailTable.
$(“#detailTable”).trigger(“reloadGrid”);Reload the data with new url.
$(“#detailTable”).setCaption(); Set caption with selected row’s id.
This is the screeenShot.
Now you can deploy your portlet.But to see data, you can add it manually in JQGridServlet. if you want , you can use this util class
package com.eteration.util;
import java.util.Calendar;
import com.turkcell.terminal.x10.x2009.EmployeeCatalog;
import com.turkcell.terminal.x10.x2009.EmployeeCatalogType;
import com.turkcell.terminal.x10.x2009.EmployeeDocument;
import com.turkcell.terminal.x10.x2009.EmployeeProjectInformation;
public class EmployeeUtil {
static EmployeeUtil instance;
EmployeeDocument employeeDocument;
public static EmployeeUtil getInstance() {
if(instance == null) {
instance = new EmployeeUtil();
}
return instance;
}
protected EmployeeUtil() {
employeeDocument = EmployeeDocument.Factory.newInstance();
EmployeeCatalog employeeCatalog=employeeDocument.addNewEmployee();
EmployeeCatalogType ramazan= employeeCatalog.addNewEmployeeList();
ramazan.setDivision("SOFTWARE");
ramazan.setEmployeeId(1);
ramazan.setName("Ramazan");
ramazan.setSurname("FIRIN");
EmployeeProjectInformation ramazanDetail1=ramazan.addNewDetail();
ramazanDetail1.setProjectName("Turkcell");
ramazanDetail1.setProjectStatus("PASSIVE");
ramazanDetail1.setEndDate(Calendar.getInstance());
ramazanDetail1.setStartDate(Calendar.getInstance());
EmployeeCatalogType necati=employeeCatalog.addNewEmployeeList();
necati.setDivision("SOFTWARE");
necati.setEmployeeId(2);
necati.setName("Necati");
necati.setSurname("PEYNİRCİ");
EmployeeProjectInformation necatiDetail1=necati.addNewDetail();
necatiDetail1.setProjectName("Turkcell");
necatiDetail1.setProjectStatus("PASSIVE");
necatiDetail1.setEndDate(Calendar.getInstance());
necatiDetail1.setStartDate(Calendar.getInstance());
EmployeeProjectInformation necatiDetail2=necati.addNewDetail();
necatiDetail2.setProjectName("AKBANK");
necatiDetail2.setProjectStatus("PASSIVE");
necatiDetail2.setEndDate(Calendar.getInstance());
necatiDetail2.setStartDate(Calendar.getInstance());
EmployeeProjectInformation necatiDetail3=necati.addNewDetail();
necatiDetail3.setProjectName("TREDA");
necatiDetail3.setProjectStatus("PASSIVE");
necatiDetail3.setEndDate(Calendar.getInstance());
necatiDetail3.setStartDate(Calendar.getInstance());
EmployeeCatalogType betul=employeeCatalog.addNewEmployeeList();
betul.setDivision("SOFTWARE");
betul.setEmployeeId(3);
betul.setName("Betul");
betul.setSurname("UNUVAR");
EmployeeProjectInformation information= betul.addNewDetail();
information.setProjectName("Turkcell");
information.setProjectStatus("ACTIVE");
information.setEndDate(Calendar.getInstance());
information.setStartDate(Calendar.getInstance());
EmployeeProjectInformation informationAvea= betul.addNewDetail();
informationAvea.setProjectName("AVEA");
informationAvea.setProjectStatus("ACTIVE");
informationAvea.setEndDate(Calendar.getInstance());
informationAvea.setStartDate(Calendar.getInstance());
}
public EmployeeDocument getEmployeeDocument() {
return employeeDocument;
}
public void setEmployeeDocument(EmployeeDocument employeeDocument) {
this.employeeDocument = employeeDocument;
}
public EmployeeCatalogType getEmployeeCatalogById(String id){
EmployeeCatalogType[] list= employeeDocument.getEmployee().getEmployeeListArray();
for(int i=0;i<list.length;i++){
EmployeeCatalogType temp=list[i];
if(temp.getEmployeeId()==Float.parseFloat(id))
return temp;
}
return null;
}
}

nice but… xml to send not a good idea… XmlBeans…nice tecnology but it would be easier with json
FYI there are some frameworks (e.g: flexjson) that can serialize Java classes into Json Strings that you can send out to the ajax call back and it would be easier to work with from javascript…and when you made the ajax request…in normal ajax calls you send strings as request parameters…so:
The point xml beans works and does is job but there are simpler soluctions for the same behaviour!! keep it simple my friend!!
Like or Dislike:
2
1
error with EmployeeDAO.getInstance().getAllEmployeeDocument();
and getStringFromXml(document) ;
understand how do you have these class
Like or Dislike:
0
0