29 March 2016

Integrasi Spring-Boot dan DataTables

Presentation layer dalam sebuah aplikasi web, merupakan suatu hal yang sangat diperhatikan. Bahkan terkadang tingkat keberhasilan sebuah aplikasi web diukur dari puas tidaknya, mudah susahnya, atau bagus tidaknya user interface aplikasi web tersebut. Tidak heran dalam industri IT, user interface diperhatikan secara khusus, bahkan ada kualifikasi karir tersendiri untuk menangani user interface ini.  Dalam aplikasi web, user interface adalah sebuah media yang menjadi jembatan bagi para user untuk meng-input-kan data ke dalam sebuah aplikasi web. Meskipun pada dasarnya tampilan sebuah aplikasi web hanyalah representasi dari CRUD (create, read, update, dan delete) data dari database. Namun para developer aplikasi web dituntut untuk membuat sebuah tampilan yang menarik.  
Salah satu halaman standar aplikasi web adalah halaman untuk menampilkan data berupa list dalam sebuah tabel. Dan biasanya halaman ini dilengkapi dengan fitur pagination, pencarian data, sorting berdasarkan kolom, dan masing-masing baris data bisa disisipkan tombol action seperti delete atau edit data. Kemajuan teknologi javascript dan css memungkinkan berkembangnya project-project yang khusus menangani tampilan-tampilan data yang dikemas dalam bentuk tabulasi ini. Hasil dari project-project tersebut bisa saja dijadikan sebuah freeware, open source project, sampai produk yang komersil. 
Saat ini banyak sekali project-project atau hasil-hasil dari project-project tersebut yang bisa kita temukan di internet.  Salah satunya adalah datatables. Datatables adalah sebuah framework javascript yang bertujuan menjadi template suatu mekanisme tampilan data yang berupa tabulasi. Template ini kemudian diletakkan dalam sebuah halaman aplikasi web. Oleh karena framework ini menggunakan javascript maka penggunaan atau integrasi datatables tidak terbatas hanya pada suatu jenis bahasa pemrograman saja, entah itu java, php, python, pearl, asp, .net atau apapun platform pemrogramannya sepanjang itu adalah sebuah aplikasi web yang juga bisa menggunakan javascript, maka datatables bisa digunakan atau diintegrasikan.
Saya memilih freemarker sebagai presentasion layer dalam development stack yang biasa saya lakukan, dikarenakan freemarker merupakan template language yang akan menghasilkan html. Dengan keunggulan ini integrasi framework atau project-project seperti datatables ini bisa saya integrasikan dalam rangkaian aplikasi web saya , dan tentunya integrasi tersebut terletak pada layer presentasi, layaknya twitter-bootstrap yang pernah kita integrasikan dengan freemarker pada tutorial-tutorial sebelumnya. 
Untuk aktivitas kita kali ini, kita akan mengintegrasikan datatables ke dalam aplikasi web kita. Source code awal untuk latihan kita bisa di check-out dari link berikut ini, source code tersebut merupakan source code dasar aplikasi web yang kita pernah buat pada artikel-artikel sebelumnya tentang spring-boot, freemarker, dan bootstrap. Kemudian silahkan download dahulu file zip datatables dari link berikut ini, pada link download datatables tersebut sudah saya pilihkan sedemikian rupa sehingga hanya beberapa file yang kita butuhkan saja yang ada dalam file zip tersebut. Kemudian ekstrak file zip datatables tersebut sesuai dengan folder yang tersedia dalam source code, maksudnya file-file yang ada dalam folder css dalam file zip diekstrak ke dalam folder css pada source code, demikian juga dengan file-file yang ada pada folder js pada file zip diekstrak ke dalam folder js yang ada pada source code, sehingga akan terlihat seperti pada gambar berikut ini:
Sebagai langkah pertama, kita akan membuat sebuah file template yang bisa kita pakai dalam halaman list data, file ini adalah file yang berisi referensi file-file datatables yang akan kita pakai nantinya dalam halaman list data. File template ini sengaja kita pisahkan dengan tujuan agar tidak semua referensi datatables kita libatkan dalam setiap halaman, kita hanya ingin supaya referensi datatables hanya dimuat pada halaman list data yang menggunakan datatables saja, pada halaman edit kita tidak perlu melibatkan datatables. Sebab file-file statis seperti css dan javascript akan mengkonsumsi resource tersendiri dalam implementasi aplikasi web, jadi sudah selayaknya kita lebih bijak menggunakan resources agar aplikasi web kita dapat lebih efisien dan efektif ketika sedang digunakan oleh user, dalam artian tidak terlalu lama pada saat loading page
File yang akan kita buat ini kita beri nama sebagai “_datatables_script.ftl” dan kita letakkan pada foldersrc/main/resources/templates/include/”, adapun isi file ini adalah sebagai berikut:
<link rel="stylesheet" href="../css/jquery.dataTables.min.css"/>
<link rel="stylesheet" href="../css/dataTables.bootstrap.min.css"/>
<script type="text/javascript" src="../js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="../js/dataTables.bootstrap.min.js"></script>
Seperti yang kita lihat bersama-sama bahwa isi file tersebut hanyalah referensi-referensi yang berhubungan dengan datatables saja, sehingga file-file ini hanya akan dimuat pada halaman dimana kita meng-include file ini saja tentunya. Keuntungan lain dari pemisahan file referensi datatables ini adalah nantinya kita akan bisa menambahkan fungsi-fungsi javascript khusus datatables, atau css style khusus untuk datatables disini.
Sebelum kita melangkah ke tahap berikutnya ada baiknya kita mengenal sedikit bagaimana datatables bisa bekerja dalam sebuah aplikasi web. Datatables sebetulnya merupakan sebuah plugin jquery library, seiring perkembangannya datatables menjadi populer karena banyak sekali digunakan dalam aplikasi web karena sifatnya yang fleksibel. Ketika diintegrasikan dengan sebuah halaman web, datatables bisa bekerja dengan menggunakan konsep ajax. Pada load pertama kali sebuah halaman web, datatables akan membuat sebuah template tabel di atas halaman tersebut, kemudian list data yang terformat dalam bentuk json diambil dari sebuah link dengan menggunakan fungsi javascript, setelah list data tersebut selesai diambil, datatables akan mem-parsing list data tersebut dan kemudian mengisinya dalam template tabel yang sudah dibuat sebelumnya. 
Jadi pada dasarnya datatables bekerja dengan menggunakan konsep ajax yang menghasilkan format dengan bentuk json yang sudah ditentukan oleh datatables itu sendiri. Format json ini merupakan format baku yang dibuat oleh datatables sehingga core datatables bisa mem-parsing list data tersebut dan kemudian memasukkannya ke dalam template table yang sudah disiapkan sebelumnya oleh datatables dalam sebuah halaman web. Adapun contoh format json yang disyaratkan oleh datatables seperti contoh gambar berikut ini:

Dan pada implementasi aplikasi web yang akan kita buat, integrasi datatables ini kita wujudkan dengan cara membuat dua buah url map, url pertama adalah url yang merupakan halaman yang berisi template tabel list data tersebut, dan url kedua adalah url yang memproduksi json data seperti format di atas. Kita akan mengimplementasikan fitur datatables ini pada data Author, dan sudah tentu kedua url mapping yang kita rencanakan ini ada pada class AuthorController. Untuk url map yang pertama, berikut ini adalah kode yang bisa kita buat pada class AuthorController.
@RequestMapping(value = "/author/get_list", method = RequestMethod.GET)
public String getDataTableList(Map<String, Object> objectMap){
    objectMap.put("pageTitle","Author");
    return "author/dt_list";
}
Pada baris kode tersebut terlihat kita membuat sebuah url dengan alamat “author/get_list” dan kembalian dari fungsi tersebut akan mengarah pada file template freemarkerdt_list.ftl” yang kita letakkan pada foldersrc/main/resources/templates/author/”. Adapun isi dari filedt_list.ftl” ini adalah sebagai berikut.
<#import "../layout/main_layout.ftl" as layout>
<@layout.mainLayout>
<div class="container">
    <table id="authorDT" class="table table-striped table-hover table-bordered table-condensed">
        <thead>
        </thead>
        <tbody></tbody>
    </table>
</div>
</@layout.mainLayout>
<#include "../include/_datatables_script.ftl"/>
<script type="text/javascript" src="../js/author/author_app.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        jsApp("../service/json/author/datatable_list");
    })
</script>
Seperti yang terlihat bahwa file template freemarker tersebut sangat singkat, namun yang harus kita perhatikan adalah baris dimana kita membuat sebuah template tabel dengan idauthorDT”. Kemudian ada deklarasi dimana kita meng-include file_datatables_script.ftl” yang kita buat sebelumnya. Lalu ada juga deklarasi yang melibatkan file javascriptauthor_app.js” yang diambil dari lokasi foldersrc/main/templates/static/js/author/”, file ini berisi fungsi javascript untuk mem-parsing json data dari format json datatables dan kemudian memasukkan data hasil parsing tersebut ke template tabel yang sudah dibuat. Dan yang terakhir ada sebuah fungsi javascript yang berfungsi memerintahkan halaman tersebut untuk mengambil data dari url../service/json/author/datatable_list” dan kemudian mem-parsing data dengan format json. Fungsi utama ini sendiri sebenarnya terletak pada fileauthor_app.js”, dan pada file freemarker template inilah, fungsi tersebut diperintahkan untuk dijalankan.

Seperti yang kita ketahui bahwa url map yang kedua memiliki output dengan format json seperti gambar di atas, format json seperti ini bisa dibentuk dengan membuat sebuah object model java. Dan output dari url map kedua merupakan @ResponseBody  object model java ini. Maka yang harus kita buat adalah sebuah object model yang bisa merepresentasikan bentuk output tersebut. Mudah saja kita langsung membuat sebuah class yang bernama “DataTableObject” dan kita letakkan dalam packageorg.josescalia.blog.simple.util” 
package org.josescalia.blog.simple.util;
import java.util.List;
public class DataTableObject<T> {
    private int iTotalRecords;
    private int iTotalDisplayRecords;
    private String sEcho;
    private String sColumns;
    private String sSortBy;
    private String sSortOrder;
    private List<T> aaData;
    /*getter setter here*/
    
    /**
     * in spring data jpa library the Page Class need page no for paramater to get result set 
     * from database
     *
     * @return int
     * @param iDisplayStart int startRow from
     * @param iDisplayLength int startRow from
     * */
    public static int getPageFromStartAndLength(int iDisplayStart, int iDisplayLength) {
        int expectedCalc = 0;
        if (iDisplayStart > 1) {
            expectedCalc = (iDisplayStart / iDisplayLength);
        }
        return expectedCalc;
    }
}
Seperti yang kita lihat pada kode-kode tersebut, class ini merupakan class pojo (plain old java object)  biasa yang ditambahkan sebuah fungsi static untuk mempermudah kalkulasi dalam pencarian suatu bilangan. Class ini nantinya akan kita pakai sebagai template output dari fungsi controller yang akan di-parsing oleh datatables. Salah satu properti pada class tersebut adalah list of object yang bisa diisi dengan object model secara dinamis, perhatikan penggunaan huruf T pada nama class dan properti aaData, inilah yang disebut dengan “named parameter” dalam pemrograman java. Jadi jika kita hendak menggunakan class DataTableObject ini untuk men-display class model Author, maka yang kita lakukan cukup dengan mendeklarasikan object baru DataTableObject ini dengan class Author sebagai named paramater-nya. 
Kemudian kita akan membuat url mapping yang kedua yang  @RequestMapping value-nya kita namakan sesuai dengan file freemarker template dt_list.ftl” yang kita buat sebelumnya. Adapun fungsi pada class AuthorController ini adalah seperti di bawah ini.
@RequestMapping(value = "/service/json/author/datatable_list")
public @ResponseBody DataTableObject<Author> 
getDataTableList(@RequestParam(required = true) String sEcho,
                @RequestParam(required = true) String sColumns,
                @RequestParam(required = true) String sSearch,
                @RequestParam(required = true) Integer iDisplayStart,
                @RequestParam(required = true) Integer iDisplayLength,
                @RequestParam(required = true) Integer iSortCol_0,
                @RequestParam(required = true) String sSortDir_0){
    String[] columns = sColumns.split(",");
    Sort sort = new Sort(Sort.Direction.fromString(sSortDir_0), sColumns.split(",")[iSortCol_0]);
    Page<Author> modelList = null;
    DataTableObject<Author> dtObject = new DataTableObject<Author>();
    int page = DataTableObject.getPageFromStartAndLength( iDisplayStart, iDisplayLength);
    try {
        modelList = authorRepository.getPaginatedList(sSearch, new PageRequest(page,iDisplayLength,sort));
        dtObject.setsEcho(sEcho);
        dtObject.setAaData(modelList.getContent());
        dtObject.setiTotalDisplayRecords(authorRepository.getTotalData(sSearch));
        dtObject.setiTotalRecords((int) authorRepository.count());
        dtObject.setsColumns(sColumns);
        dtObject.setsSortBy(sColumns.split(",")[iSortCol_0]);
        dtObject.setsSortOrder(sSortDir_0);
        return dtObject;
    }catch (Exception e){
        logger.error(e.getMessage());
    }
    return null;
}
Perhatikan kode fungsi di atas, value dari request mapping telah kita sesuaikan, kemudian fungsi tersebut memiliki parameter yang lumayan banyak, harap diketahui parameter ini adalah paramater yang akan di lempar oleh mekanisme datatables ketika mengambil data dengan menggunakan konsep ajax. Dalam kode tersebut kita juga melihat kembalian dari fungsi ini adalah class DataTableObject, dan class DataTableObject ini kita assign class model Author sebagai named parameter object-nya. Pada bagian utama kode tersebut, setiap properti yang ada pada class DataTableObject di-set nilai-nilainya dengan menggunakan resources yang sudah ada sebelumnya, seperti properti aaData yang di-isi dengan list data Author, totalRecord yang di-isi dengan jumlah seluruh data dalam tabel mysql, dan seterusnya.
Sampai disini, kita hampir selesai mengimplementasikan datatables ke dalam halaman list pada aplikasi web kita, tinggal satu langkah lagi yaitu membuat sebuah fungsi javascript yang akan mem-parsing json data hasil dari pemanggilan ajax tadi. Jika kita  melihat kembali file freemarker template dt_list.ftl”, kita melihat ada sebuah file javascript yang di-include dalam file tersebut, yaitu fileauthor_app.js” yang terletak dalam foldersrc/main/resources/template/js/author/”, jika folder author belum ada dalam source code, silahkan buat sendiri. Dan kemudian buat lagi sebuah file dengan nama “author_app.js” di dalam folder tersebut. Adapun isi dari fileauthor_app.js” adalah sebagai berikut.
(function($) {
   jsApp = function(dataTableJsonURL) {
      $(document).ready(function() {
         $('#authorDT').dataTable({
             sPaginationType:"full_numbers", //remove this to delete first
            // and last button
            bProcessing : true,
            bServerSide : true,
            bStateSave : true, // to save state in cookie
            iCookieDuration : 60, // cookie will save for about 60 seconds
            sAjaxSource : dataTableJsonURL,
            iDisplayLength : 10,
            aoColumns : [ {
               "mData" : "id",
               "sClass" : "text-center",
               "sName" : "id",
               "sTitle" : "Action",
               "sWidth" : "12%"
            }, {
               "mData" : "authorName",
               "sName" : "authorName",
               "bSortable" : true,
               "sWidth" : "25%",
               "sTitle" : "Author Name"
            }, {
               "mData" : "authorAddress",
               "sName" : "authorAddress",
               "bSortable" : true,
               "sWidth" : "45%",
               "sTitle" : "Address"
            },{
               "mData" : "createdDate",
               "sName" : "createdDate",
               "bSortable" : true,
               "sWidth" : "15%",
               "sTitle" : "Date Created"
            } ]
         })
      });
   };
})(jQuery);
Ya, fungsi javascript inilah yang akan melakukan request http ke url map kedua yang sudah kita buat, dan kemudian hasil dari http request tersebut di-parsing ke dalam masing-masing field. Perhatikan baris aoColumns yang tertulis diatas, baris ini merupakan array javascript yang akan menempatkan masing-masing kolom pada template tabel yang dibuat oleh Datatables. Uniknya kolom-kolom template yang dibuat oleh datatables juga menggunakan referensi array javascript ini, maksudnya begini, jika kita membuat 4 object dalam array javascript tersebut, maka DataTables juga akan membuatkan sebanyak 4 kolom sebagai template tabelnya, jika kita membuatkan 3 object, maka Datatables juga membuatkan 3 kolom sebagai template tabelnya, dan seterusnya, dan ini dilakukan secara dinamis. Disinilah letak kekuatan datatables sebagai plugin jquery dalam bidang tabulasi.

Sampai disini implementasi datatables ke dalam sebuah halaman list pada aplikasi web kita telah selesai, silahkan anda tes hasil implementasi tersebut. Pada aplikasi web yang saya miliki untuk kegiatan ini, hasil dari saya seperti gambar berikut ini, dan jika tidak sama persis tampilannya dengan anda, saya memang menambahkan beberapa styling css yang ringan untuk menyesuaikan tampilan agar lebih enak dipandang mata. Dan styling css yang saya tambahkan tentunya saya letakkan pada file_datatables_script.ftl” yang ada pada foldersrc/main/resources/templates/include/”, sehingga tampilan ini tentu saja hanya berlaku untuk halaman-halaman yang menggunakan datatables saja.
Anda juga saya sarankan untuk menggali lebih dalam lagi penggunaan datatables dengan membaca dokumentasi datatables pada website resminya, banyak sekali yang bisa kita lakukan atau terapkan untuk mendapatkan tampilan tabulasi yang menarik yang bisa kita manfaatkan dalam halaman aplikasi web kita.
Saya rasa sampai disini dulu tutorial implementasi datatables untuk pembahasan kali ini, jika masih diberikan kesempatan kita akan terus belajar bersama melalui tulisan-tulisan dalam blog ini.

Semoga Bermanfaat
Depok, 26 Maret 2016



Josescalia.

1 comment:

Ace Maxs said...

izin menyimak gan, mas, mbak Ace Maxs