13 February 2016

Spring-boot, MVC, Freemarker, dan Twitter-Bootstrap (bag 2)

Baiklah pembaca, sekarang kita sampai pada tutorial yang ke dua dari rangkaian pembuatan aplikasi web dengan menggunakan spring-boot. Setelah pada tulisan lalu kita belajar bagaimana membuat sebuah aplikasi web yang mampu mengeluarkan output berupa format json, sekarang kita akan mencoba melanjutkan dengan cara memodifikasi aplikasi web tersebut agar mampu terintegrasi dengan halaman html, sehingga bisa menggunakan twitter-bootstrap nantinya sebagai styling halaman html tersebut.
Pada latihan ini kita akan memilih Apache Freemarker sebagai viewer aplikasi web kita, freemarker adalah sebuah framework dalam development java yang berisi library yang mampu menghasilkan output berupa text, halaman web, email, file konfigurasi, dan lain-lain, berdasarkan template yang telah ditentukan. Template ini dibuat menggunakan Freemarker Template Language (FTL) yang sederhana dan khusus. Dengan freemarker kita bisa lebih fokus dalam tampilan data dan 'kosmetik' halaman aplikasi web. Secara flow aplikasi, template freemarker ini akan dipanggil oleh controller dalam aplikasi web kita, dimana data-data yang akan ditampilkan di-set di dalam fungsi-fungsi controller ini.
Langkah pertama yang akan kita lakukan dalam tutorial ini adalah menambahkan library freemarker ke dalam classpath development aplikasi web kita. Silahkan tambahkan baris baris ini di dalam file pom.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>
Kita akan membuat sebuah tampilan aplikasi web berupa tabel yang berisi daftar Author, buka file AuthorController dan tambahkan fungsi ini ke dalam class AuthorController tersebut.
@RequestMapping(value = "/author/list", method = RequestMethod.GET)
public String getList(Map<String, Object> objectMap) {
    objectMap.put("authorList", (List<Author>) authorRepository.findAll());
    return "author/list";
}
Perhatikan baris kode-kode di atas, disana kita membuat sebuah fungsi yang nantinya bisa dipanggil di browser dengan alamat url : http://localhost:8080/author/list, dan url ini dipanggil menggunakan metode http GET. Fungsi ini memiliki parameter berupa object Map, nah object Map inilah yang nanti akan menjadi perantara pertukaran data antara controller dengan template freemarker. Semua data yang ingin kita bawa dan ditampilkan dalam halaman html, harus dimasukkan ke dalam object Map ini. Dan nantinya di template freemarker, identifier (key) dari object Map tersebut yang akan kita extract.
Kemudian dalam fungsi tersebut bisa kita lihat bahwa kita mengambil data seluruh Author dari database kemudian dimasukkan dalam object Map. Identifier (Key) dari data seluruh Author ini kita definisikan sebagai authorList dalam object Map. Dan yang terakhir adalah fungsi tersebut mengembalikan String yang berfungsi menunjuk lokasi template freemarker yang akan dipakai, dalam hal ini template freemarker untuk fungsi tersebut ada pada folderauthor” dan file-nya bernama “list.ftl”.

Dalam spring-boot, secara default semua viewer yang berupa templating ditempatkan dalam foldersrc/main/resources/templates”,  dalam folder inilah spring-boot akan mencari template-template yang dirujuk oleh controller. Oleh karena itu buatlah folder template tersebut di dalam foldersrc/main/resources/”, selain itu sekalian kita buat juga folder static sejajar dengan folder template tersebut. Folder static ini nantinya juga dibaca langsung oleh spring-boot sebagai static-content tanpa melalui controller. Dalam folder ini nantinya kita akan meletakkan static content seperti javascript, css, images, dan lain-lain.
Kemudian dalam folder template tersebut, supaya lebih teratur kita buat lagi folder-folder yang lain yang merupakan representasi dari model-model kita yaitu author, book dan publisher. Lalu buat juga dua buah folder dalam folder static dengan nama js dan css, seperti gambar dibawah ini:
Oleh karena kita sudah membuat fungsi getList pada class AuthorController dan fungsi tersebut memiliki kembalian yang merujuk pada lokasi “author/list”, maka buatlah sebuah file dengan nama “list.ftl” dan letakkan dalam foldertemplates/author”, adapun isi filelist.ftl” ini adalah sebagai berikut:
<html>
<link rel="stylesheet" href="../css/style.css">
<head>
    <title>Simple Spring Boot Web Application</title>
</head>
<body>
<a href="#" class="tblAddNew">Add New</a>
<table>
    <thead>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Address</th>
    </tr>
    </thead>
    <tbody>
    <#list authorList as author>
        <tr>
            <td style="text-align:center;"><a href="edit?id=${author.id}">${author.id}</a></td>
            <td>${author.authorName}</td>
            <td>${author.authorAddress}</td>
        </tr>
    </#list>
    </tbody>
</table>
<p><a href="/">Back to Index</a> </p>
</body>
</html>
Perhatikan kode-kode dalam file list.ftl ini, jika kita familiar dengan syntax html, isi dari file ini tentunya tidak sulit untuk dipahami bukan, hanya saja ada sedikit syntax freemarker template language (ftl) pada baris ke-18 sampai dengan baris ke-24. Syntax freemarker template language (ftl) pada baris tersebut merupakan syntax yang berfungsi me-loop sebuah list yaitu “authorList”, ingat kita mendefinisikan data author di dalam object Map sebagai “authorList” pada fungsi getList di class AuthorController sebelumnya.  Inilah yang saya sebut dengan meng-ekstrak data berdasarkan indentier (key) object Map
Adapun pengertian dari loop tersebut adalah seperti ilustrasi berikut ini, “Setiap data dalam object authorList  diwakilkan sebagai author, kemudian author tersebut ditampilkan id-nya, authorName-nya, dan authorAddress-nya pada kolom-kolom dalam tabel”. Id, authorName, dan authorAddress adalah properti-properti dari object author.
Sekarang silahkan jalankan kembali aplikasi web tersebut dengan mengeksekusi perintah maven berikut ini:
mvn clean install exec:java -DskipTests -Pdefault
Kemudian buka kembali browser kesayangan anda dan tuliskan alamat ini pada url browser anda tersebut, http://localhost:8080/author/list”, hasil ditempat saya seperti gambar di bawah ini, bagaimana dengan anda?
Dengan sedikit sentuhan styling css, maka tabel kita inipun bisa tampak seperti gambar dibawah ini:

Mudah bukan?. Silahkan anda buat lagi list-list lainnya dengan cara mengikuti langkah-langkah di atas, seperti publisher list, book list, dan silahkan tambahkan juga styling css sesuai dengan yang an/span>
Pada baris-baris kode tersebut bisa kita lihat object Author yang sebagai paramater dari fungsi juga merupakan paramater lemparan dari form, itulah sebabnya kenapa file _form.ftl yang sebelumnya kita buat memiliki input type text dengan nama “authorName” dan “authorAddress” sebab dengan cara demikian secara tidak langsung fungsi controller ini akan mempasangkan nama-nama dari parameter yang dilempar lewat http post ke dalam properti-properti object Author. Kita juga melihat dalam baris kode tersebut, fungsi yang kita buat ini memiliki kembalian berupa String yang berbentuk format json, perhatikan anotasi @ResponseBody disana. Didalam fungsi tersebut logikanya sangatlah sederhana, parameter yang ditangkap dari form akan diteruskan ke object repository untuk disimpan ke dalam database, jika tidak ada kesalahan dalam penyimpanan maka akan mengembalikan StringSave Suceed” dan jika ada kesalahan maka akan mengembalikan StringSave Failed “ ditambah dengan keterangan penyebab dari kesalahan penyimpanan tersebut.

Untuk bisa membuat tombol “Save” dalam form bisa berfungsi, dan oleh karena form tersebut di-include dalam file list.ftl maka yang kita modifikasi adalah file list.ftl tersebut, kali ini kita akan menggunakan teknik ajax dalam form tersebut, caranya adalah dengan menambahkan beberapa baris kode javascript seperti di bawah ini, pada file list.ftl:

da inginkan. 
Langkah selanjutnya kita akan mengimplementasi framework css twitter-bootstrap ke dalam aplikasi web kita ini agar tampilan halaman aplikasi web kita menjadi lebih menarik. Saat ini bootstrap banyak digunakan oleh developer aplikasi web  ataupun designer website sebagai sebuah framework css karena memiliki keuntungan dari sisi efisiensi waktu pembuatan. Tampilan-tampilan yang dihasilkan dengan menggunakan bootstrap memang fix dan memiliki standard yang sama, namun pengguna aplikasi web maupun website sudah cukup puas dengan tampilan-tampilan yang dihasilkan oleh framework css tersebut.
Untuk bisa mengimplementasikan bootstrap dalam aplikasi web kita ini, langkah pertama yang akan kita lakukan adalah meng-copy file-file yang dimiliki bootstrap ke dalam folder static yang sudah kita buat sebelumnya pada src/main/resources/, silahkan copy file-file distribusi bootstrap ke dalam folder static sesuai dengan yang kita buat sebelumnya, seperti contoh gambar dibawah ini.
Kemudian tambahkan beberapa baris kode pada file list.ftl yang terletak pada folder src/main/templates/author yang sudah kita buat sebelumnya tadi menjadi seperti contoh berikut ini:
<html>
<link rel="stylesheet" href="../css/bootstrap.min.css">
<head>
    <title>Simple Spring Boot Web Application</title>
</head>
<body>
Langkah selanjutnya adalah tambahkan class-class yang dimiliki oleh bootstrap tersebut ke dalam tag table pada halaman html kita seperti contoh berikut ini:
<a href="#" class="btn btn-info btn-sm ">Add New</a>
<table class="table table-bordered table-striped table-condensed">
    <thead>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Address</th>
    </tr>
Dapat kita lihat pada kode-kode diatas, kita menambahkan class-class table, table-bordered, table-striped, dan table-condensed dalam tag table kita, dan kita juga menambahkan beberapa class pada tag a untuk membuat tag tersebut menjadi sebuah tombol, class-class yang kita tambahkan itu merupakan class-class milik bootstrap. Dengan tersedianya class-class css seperti ini, maka akan sangat mudah bagi kita untuk mendapatkan tampilan aplikasi web yang bagus. Kemudian jalankan lagi aplikasi web tersebut, dan buka kembali browser anda dengan url yang sama seperti sebelumnya, maka hasil ditempat saya seperti gambar dibawah ini:

Tampilan aplikasi web kita pun sekarang lebih cantik dengan sentuhan twitter-bootstrap. Coba anda  rubah ukuran (resize) browser anda, maka tabel tersebut akan menyesuaikan diri dengan ukuran browser kita. Itulah salah satu keunggulan bootstrap yang mengusung konsep responsive terhadap semua element html yang kita implementasikan.
Sekarang kita akan mencoba fitur lain dari bootstrap yang juga sangat menarik dan banyak dipakai, tapi sebelumnya kita rancang dulu skenario flow aplikasi web kita seperti ini. "Jika user mengklik tombol Add New, maka form author akan tampil melayang di atas table tersebut (on the fly), ketika form tersebut diisi kemudian di submit datanya dengan menekan tombol save, maka data yang diinputkan dalam form tersebut akan di kirim ke controller, kemudian controller menyimpannya ke dalam database, lalu jika data berhasil tersimpan lalu controller akan memberikan konfirmasi “Save Succeed” yang berupa format json yang harus ditangkap oleh halaman aplikasi web, dan ketika user mengklik tombol Ok pada konfirmasi tersebut, maka serta merta halaman aplikasi web akan me-refresh (reload), sehingga data yang tersimpan dapat langsung tampil dalam table tersebut".

Mari kita wujudkan skenario tersebut, langkah pertama adalah menyiapkan form yang akan ditampilkan di atas tabel ketika tombol Add New diklik. Modifikasilah file list.ftl dengan menambahkan baris-baris kode seperti contoh dibawah ini:
<body>
<div class="container">
<a href="#modalForm" class="btn btn-info btn-sm" data-toggle="modal" data-placement="top" >Add New</a>
<table class="table table-bordered table-striped table-condensed">
    <thead>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Address</th>
    </tr>
    </thead>
    <tbody>
    <#list authorList as author>
        <tr>
            <td style="text-align:center;"><a href="edit?id=${author.id}">${author.id}</a></td>
            <td>${author.authorName}</td>
            <td>${author.authorAddress}</td>
        </tr>
    </#list>
    </tbody>
</table>
<p><a href="/">Back to Index</a> </p>
</div>
<#--author form, hidden by default-->
<div class="modal fade" id="modalForm" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"
     style="overflow-y:auto">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header" style="background-color:rgba(173, 216, 230, 0.17)">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true"
                        style="margin:3px">&times;</button>
                <h4 class="text-center">Add New Author</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal">
                <#include "_form.ftl">
                </form>
            </div>
            <div class="modal-footer">
                <a href="#" id="btnSave" class="btn btn-info btn-sm"><span
                        class="glyphicon glyphicon-floppy-disk"></span> Save</a>
                <a href="#" id="btnCancel" data-dismiss="modal" class="btn btn-danger btn-sm"><span
                        class="glyphicon glyphicon-step-backward"></span> Cancel</a>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript" src="../js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="../js/bootstrap.min.js"></script>
Ok, mari kita bahas kode-kode diatas. Modifikasi yang pertama ada pada penambahan blok div tepat sesudah tag body, blok div ini kita beri classcontainer” milik bootstrap yang akan membuat tampilan halaman web aplikasi akan menjadi proporsional, dengan membuat margin pada sisi kanan dan sisi kiri seluruh halaman web. Modifikasi selanjutnya kita merubah tag a yang akan berfungsi sebagai pemicu tampilnya form melayang (on the fly form) diatas tabel author tadi. Modifikasi kita lanjutkan dengan menambah tag div dengan id modalForm, tag inilah yang akan tampil pada saat tombol Add New diklik nantinya, dalam tag div ini kita bisa melihat, ada modal-dialog dan modal-content disana, modal-modal ini merupakan class milik bootstrap yang sudah tersusun sedemikian rupa. Modifikasi terakhir yang kita lakukan adalah menambahkan tag script javascript jquery, dan bootstrap.min.js pada 2 baris terakhir kode-kode diatas. Bootstrap membutuhkan javascript jquery untuk bisa membuat fungsi-fungsi javascript yang ada dalam bootstrap.min.js berjalan, jangan lupa untuk meng-copy jquery ke dalam folder js, untuk contoh ini saya menggunakan jquery.1.9.1.

Perhatikan juga isi dari div dengan class modal-body, kita memiliki sebuah tag freemarker yang berarti meng-include sebuah file dengan nama _form.ftl. Form inilah yang akan kita desain menjadi field-field isian data author. Sekarang kita coba dulu jalankan aplikasi web kita ini. Kemudian kita eksekusi halaman aplikasi web tersebut dengan mengklik tombol Add New, jika kita belum membuat file _form.ftl ini maka akan ada error dalam konsol web aplikasi kita seperti ini:
freemarker.core._MiscTemplateException: Error reading included file "author/_form.ftl":
Template "author/_form.ftl" not found.
Terjadinya error tersebut memang karena kita belum membuat file _form.ftl, sehingga Apache Freemarker tidak bisa menemukan file tersebut. Sekarang kita buat file _form.ftl dengan meletakkannya di dalam folder src/main/resources/templates/author/ sejajar dengan file list.ftl tersebut. Adapun isi dari file _form.ftl ini adalah sebagai berikut:
<div class="form-group">
    <label for="authorName" class="col-lg-4 col-md-6 col-sm-12">Author Name</label>
    <div class="col-lg-8 col-md-6 col-sm-12">
        <input type="text" class="form-control" id="authorName" name="authorName">
    </div>
</div>
<div class="form-group">
    <label for="authorAddress" class="col-lg-4 col-md-6 col-sm-12">Address</label>
    <div class="col-lg-8 col-md-6 col-sm-12">
        <textarea id="authorAddress" name="authorAddress" class="form-control"></textarea>
    </div>
</div>
Sekarang coba kembali eksekusi halaman aplikasi web tersebut, maka seharusnya tampil seperti gambar di bawah ini:
Dan voila, form tersebut pun tampil diatas tabel secara melayang, cobalah klik tombol Cancel atau tombol dengan icon x pada header form tersebut, seharusnya form tersebut kembali tersembunyi, muncul dan tersembunyinya form tersebut merupakan salah satu fungsi dari javascript bootstrap.

Sejauh ini bagaimana pembaca?, apakah akan kita lanjutkan?, jika anda adalah pembaca baru blog saya ini, silahkan subscribe pada facebook fans page yang terdapat disebelah kiri blog ini untuk mendapatkan update tutorial-tutorial soal komputer, pemrograman dan lain-lain dari blog saya. Dan jika anda sudah pernah subscribe pada fans page tersebut, saya pastikan akan selalu meng-update link-link tulisan terbaru pada fans page tersebut (iklan dikit :P).
Selanjutnya kita akan membuat fungsi dalam controller agar tombol Save dalam form tersebut bisa berfungsi. Adapun fungsi yang akan kita buat dalam controller ini adalah sebuah fungsi simpan dalam database dan memiliki kembalian berupa format json. Tambahkan baris-baris kode berikut ini dalam class AuthorController.
@RequestMapping(value = "/service/json/author/save", method = RequestMethod.POST)
public @ResponseBody String saveAuthor(Author author) {
    try {
        authorRepository.save(author);
        return "Save Succeed";
    } catch (Exception e) {
        logger.error(e.getMessage());
        return "Save Failed : " + e.getMessage();
    }
}
Pada baris-baris kode tersebut bisa kita lihat object Author yang sebagai paramater dari fungsi juga merupakan paramater lemparan dari form, itulah sebabnya kenapa file _form.ftl yang sebelumnya kita buat memiliki input type text dengan nama “authorName” dan “authorAddress” sebab dengan cara demikian secara tidak langsung fungsi controller ini akan mempasangkan nama-nama dari parameter yang dilempar lewat http post ke dalam properti-properti object Author. Kita juga melihat dalam baris kode tersebut, fungsi yang kita buat ini memiliki kembalian berupa String yang berbentuk format json, perhatikan anotasi @ResponseBody disana. Didalam fungsi tersebut logikanya sangatlah sederhana, parameter yang ditangkap dari form akan diteruskan ke object repository untuk disimpan ke dalam database, jika tidak ada kesalahan dalam penyimpanan maka akan mengembalikan StringSave Suceed” dan jika ada kesalahan maka akan mengembalikan StringSave Failed “ ditambah dengan keterangan penyebab dari kesalahan penyimpanan tersebut.

Untuk bisa membuat tombol “Save” dalam form bisa berfungsi, dan oleh karena form tersebut di-include dalam file list.ftl maka yang kita modifikasi adalah file list.ftl tersebut, kali ini kita akan menggunakan teknik ajax dalam form tersebut, caranya adalah dengan menambahkan beberapa baris kode javascript seperti di bawah ini, pada file list.ftl:
<script type="text/javascript">
    $(function(){
        $("#btnSave").click(function(){
            $.post("/service/json/author/save", $("#modalForm").find("form").serialize(), function(jsonString){
                if(jsonString == "Save Succeed"){
                    alert(jsonString);
                    window.location.reload();
                }else{
                    alert(jsonString);
                }
            })
        })
    })
</script>
Letakkan baris-baris kode tersebut tepat diatas tag </body> pada filelist.ftl”. Disini kita memanfaatkan fungsi ajax post jquery untuk melakukan http post ke url/service/json/author/save” yang kita definisikan pada fungsi save di class AuthorController. Nilai kembalian dari eksekusi http post tersebut kita tampung dalam sebuah alert javascript, dimana jika penyimpanan berhasil, kita reload halaman web-nya, dan jika gagal hanya menampilkan pesan dari kembalian fungsi penyimpanan tersebut. 

Silahkan jalankan aplikasi web tersebut dan cobalah lakukan penyimpanan data, gambar-gambar berikut ini adalah gambar-gambar ketika saya melakukan penginputan data.

Gambar kedua merupakan gambar dimana saya gagal memasukkan data author ke dalam database, pesan dari kegagalan tersebut merupakan pesan bahwa tabel author tidak bisa menyimpan data dengan nama yang sudah ada sebelumnya. Saya sengaja memodifikasi sedikit class Author agar saya mendapatkan efek seperti ini jika authorName ada duplikasi. Andapun bisa melakukannya juga dengan cara menambahkan baris kode seperti dibawah ini pada class Author.
@Column(name = "AUTHOR_NAME", length = 100,nullable = false, unique = true)
    public String getAuthorName() {
        return authorName;
    }

Dan pembaca, sampai disini saya rasa cukup sekian dulu tutorial bagian ke dua untuk pembahasan spring-boot ini, ditutorial selanjutnya kita akan membahas lebih lanjut pemanfaatan freemarker sebagai template layout web aplikasi. Anda juga bisa mendownload source-code dua tutorial terakhir tentang spring-boot pada link ini.

Akhir kata saya ucapkan semoga tulisan ini bisa bermanfaat buat para pembaca semua.


Depok, 13 Februari 2016


Josescalia 

No comments: