Introduction
This article will demonstrate how to integrate Java web with DataTable
(DataTables.net) in an easy way.
- Integrate
Datatable
into Servlet - Initiate new
Datatable
s on demand (one click to create a table) - Automatically handle AJAX requests, Response for
Datatable
(simply by implementing an interface).
Background
If you're looking up on Google, there are some tutorials and articles of integrating Datatables.net into Java Web Application, but for me, I can't find an example that meets my need. I need something comprehensive, something that will help me control the Datatable
s on Java code and I can easily working with. Finished by my own, and here are the ideas:
- Map all
Datatable
s properties into Java Objects, of course with the document from Datatables.net. - Find a way to render the table's header easier, and end up with two ways: Classical class, and Annotation
- What is the best way to handle Ajax request sent from the table if the
Datatable
s is set with server side processing.
In order to fully understand the article, you have to be familiar with the following terms:
- Java language (Reflection, annotation), J2EE or at least Java web application.
- JavaScript, jQuery, AJAX
- JSON
DataTable
s
The article uses following tools and libraries:
- Eclipse IDE (Recommend Eclipse IDE for Java EE Developers)
- Jquery http://jquery.com/, Jquery UI http://jqueryui.com/
- Datatables http://datatables.net/
- Jackson library (for serialize JSON purpose) http://jackson.codehaus.org/
- Tomcat server http://tomcat.apache.org/
Using the Code
The source code of this project mainly demonstrates how to use datatable
s wrapper library. You can find more details and the source code here.
There are two types of tables we want to create on client side (specify by bServerSide
properties of DataTable
object):
Static
data <static table>: Client requests for a table, server returns a Json contains definition for table and data (rows). This type is usually suitable if the database doesn't contain too many records. Dynamic
data <dynamic table>: Client requests for a table, server returns only the definition of the table, and then the table itself will make an Ajax request to retrieve data, to serve this request server only returns a limited amount of data from database. This type is the best choice for the database which has thousand records.
The following steps need to be done when working with datatables
wrapper:
- Add
datatables
wrapper and dependencies into project. - Create a jsp file <index.jsp> that includes the necessary JavaScripts, CSS libraries.
- Create a Java bean class that represents a table row (including column header definition)
- Add a new servlet class that declares URL pattern in web.xml file.
- To handle data for the table, implements
IDataHanlder
interface.
Here is the screenshot:
Eclipse project structure:
I. Dependencies
The project requires dependencies:
datatableswapper-1.0.jar,
jackson-annotations-2.2.3.jar,
jackson-core-2.2.3.jar,
jackson-databind-2.2.3.jar
II. Jsp File
Both of them also share the same index.jsp file and require the following JavaScript and CSS libraries:
<link rel="stylesheet" type="text/css"
href="js/data_table/reset-min.css">
<link rel="stylesheet" type="text/css"
href="js/data_table/complete.css">
<script type="text/javascript"
language="javascript" src="js/jquery-1.8.3.js"></script>
<script type="text/javascript" language="javascript"
src="js/data_table/jquery.dataTables.min.js"></script>
<script type="text/javascript" language="javascript"
src="js/data_table/jquery.dataTables.plugins.js"></script>
JavaScript after page is loaded (Note: Due to limitations of
JSON, we cannot add callback code into JSON, therefore JSON.parse
will substitute the callback name by callback function which usually defines in plugin file.)
$.ajax({
dataType: "text",
url: "DataTableCtrl",
success: function(data){
var jsonTbl = JSON.parse(data, applyCallback);
var DOMTable = $("<table>").attr("class", "pretty");
$("body").append(DOMTable);
oTable = DOMTable.dataTable(jsonTbl);
}
});
Complete index.jsp file:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css"
href="js/data_table/reset-min.css">
<link rel="stylesheet" type="text/css"
href="js/data_table/complete.css">
<script type="text/javascript" language="javascript"
src="js/jquery-1.8.3.js"></script>
<script type="text/javascript" language="javascript"
src="js/data_table/jquery.dataTables.min.js"></script>
<script type="text/javascript" language="javascript"
src="js/data_table/jquery.dataTables.plugins.js"></script>
<script language="javascript" type="text/javascript">
var oTable;
$(document).ready(function(){
$.ajax({
dataType: "text",
url: "DataTableCtrl",
success: function(data){
var jsonTbl = JSON.parse(data, applyCallback);
var DOMTable = $("<table>").attr("class", "pretty");
$("body").append(DOMTable);
oTable = DOMTable.dataTable(jsonTbl);
}
});
});
</script>
</head>
<body>
</body>
</html>
III. Bean Class
The Java bean class will have @AoColumn
annotation on each field. It indicates the column header for the table.
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import net.datatables.wrapper.annotation.AoColumn;
public class Student {
@AoColumn(sTitle = "ID")
private int id;
@AoColumn(sTitle = "Name")
@JsonInclude(Include.ALWAYS)
private String name;
@AoColumn(sTitle = "Age")
private int age;
@AoColumn(sTitle = "Class")
@JsonInclude(Include.ALWAYS)
private String clazz;
@AoColumn(sTitle = "Address", bSearchable = false)
@JsonInclude(Include.ALWAYS)
private String address;
.... Setters and getters method
}
The above code defines table column's header will have [ ID | Name | Age | Class | Address].
Note: By default, Datatables
wrapper will not include in the JSON response if the value is null
, however we want it included if it's the data row values by adding extra annotation.
@JsonInclude(Include.ALWAYS)
IV. Servlet Class and web.xml:
DataTableCtrl.java
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
DataTableWrapper tableWrapper = new DataTableWrapper();
DataTable<Student> table = new DataTable<>(Student.class);
table.bServerSide = true;
table.bDestroy = true;
table.sPaginationType = "full_numbers";
table.fnServerData = new FnCallBack("fnDataTablesPipeline");
tableWrapper.setDataHandler(StudentDataHandler.class);
tableWrapper.setDataTable(table);
try {
tableWrapper.wrap(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
web.xml
<servlet>
<servlet-name>DataTableCtrl</servlet-name>
<servlet-class>servlet.DataTableCtrl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DataTableCtrl</servlet-name>
<url-pattern>/DataTableCtrl</url-pattern>
</servlet-mapping>
V. Implementing IDataHandler Interface
StudentDataHandler.java.
There are three methods that you need to overwrite:
public List<Student> getListData(AjaxRequest tableRequest,...)
AjaxRequest
object will contain all the information to which table has sent.
Like: sSearchKeyword
, iDisplayStart
, iDisplayLength
... For example: In a dynamic table, after the user clicks the next button on the pagination control. Based on iDisplayStart
and iDisplayLength
,
we will return the correct amount of rows that the table needs.
Note: If on the servlet class we have defined: table.bServerSide = false
, the object AjaxRequest
will be null
, and we should return all records in the database at once. Two methods: getITotalRecords()
and getITotalDisplayRecords()
need not return any value
other than 0
.
public class StudentDataHandler implements IDataHandler<Student> {
List<Student> list;
int itotalRecords;
int iTotalDisplay;
public StudentDataHandler() {
list = getAllStudents();
itotalRecords = iTotalDisplay = list.size();
}
@Override
public List<Student> getListData(AjaxRequest tableRequest,
HttpServletRequest request) {
return filterStudents(tableRequest);
}
@Override
public int getITotalRecords() {
return itotalRecords;
}
@Override
public int getITotalDisplayRecords() {
return iTotalDisplay;
}
Conclusion
By using annotation, creation of datatable
s now seems pretty easy. The
table will be created on the client side whenever you need it with no limit on columns header and data.
Based on this idea, we can create another table and replace the current table
using AJAX.