Living life and Make it Better

life, learn, contribute

Endy Muhardin

Software Developer berdomisili di Jabodetabek, berkutat di lingkungan open source, terutama Java dan Linux.

Intro JSF

Pada postingan kemarin, kita telah melihat bagaimana membuat aplikasi web dengan ICEFaces, yang notabene dijalankan di atas framework JSF. Tapi JSF sendiri itu apa?

Java Server Faces (JSF) adalah salah satu teknologi terbaru dalam pengembangan aplikasi web. Teknologi ini distandarisasi oleh Sun sehingga dukungan terhadapnya akan disediakan para vendor server.

Sebenarnya apa itu JSF? Berdasarkan penjelasan dari Sun, JSF terdiri dari:

  • Kumpulan komponen UI (tentunya berbasis web)

  • Pengaturan flow navigasi

  • Mekanisme event handling (seperti layaknya aplikasi desktop)

  • Halaman web

  • Server side objects

Karena sifatnya yang merupakan spesifikasi resmi dari Sun, di masa depan akan banyak vendor yang menyediakan dukungan terhadap framework ini, sehingga kita bisa mengharapkan adanya:

  • Visual Editor untuk halaman web

  • Visual Editor untuk mengatur aliran navigasi

  • Komponen siap pakai yang sudah AJAX-enabled

Saat tulisan ini dibuat, sepertinya editor visual yang terbaik untuk JSF masih dipegang Netbeans. Sayangnya berdasarkan pengalaman sekilas saya, editor visual ini sangat ‘menjajah’. Agar kita bisa mengedit halaman web dan navigasi secara visual, kita harus banyak extends class Netbeans.

Mudah-mudahan di masa depan dukungan tools akan semakin banyak, terutama dari Eclipse atau IDEA.

Baiklah, para pembaca tentunya sudah tidak sabar ingin melihat, seperti apa kodenya. Pada artikel ini, kita hanya akan membahas tentang:

  1. konfigurasi awal

  2. membuat dua halaman, dan

  3. menghubungkan keduanya dengan konfigurasi navigasi

Kita akan menggunakan implementasi JSF yang disediakan Sun, saat artikel ini ditulis, rilis terbaru adalah 1.2.

Selain hasil karya Sun, kita juga bisa menggunakan JSF terbitan Apache.

Mari langsung coding.

Kita akan hanya akan membuat dua halaman:

  1. Registrasi User

  2. Konfirmasi Registrasi

tanpa business logic sama sekali. Halaman pertama berisi form registrasi, yang bila di-klik tombol Register-nya, user akan diarahkan ke halaman kedua. Untuk validasi dan akses database akan dibahas dalam artikel terpisah.

Halaman pertama tampak seperti ini.

Halaman Registrasi

Sedangkan halaman kedua tampak seperti ini.

Halaman Konfirmasi

Kode untuk halaman pertama adalah sebagai berikut.

register.jsp

<code><%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<!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=UTF-8">
        <title>:: Pendaftaran User ::</title>
    </head>
    <body>

    <h1>Silahkan masukkan data Anda di sini</h1>
    <h:form>
    <table border="0">        
        <tbody>
            <tr>
                <td>Nama Lengkap</td>
                <td><h:inputText value="name" /></td>
            </tr>
            <tr>
                <td>Username</td>
                <td><h:inputText value="name" /></td>
            </tr>
            <tr>
                <td>Email</td>
                <td><h:inputText value="name" /></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><h:inputSecret value="password"/></td>
            </tr>
            <tr>
                <td>Password (ulangi)</td>
                <td><h:inputSecret value="password2"/></td>
            </tr>
            <tr>
                <td> </td>
                <td><h:commandButton type="submit" value="Daftar" action="register"/></td>
            </tr>
        </tbody>
    </table>
    </h:form>
    
    </body>
</html>
</code>

Perhatikan kode program untuk menampilkan tombol. Di sana ada atribut action yang bernilai register. Atribut action ini nantinya akan digunakan di konfigurasi navigasi di bawah.

Sedangkan halaman kedua isinya HTML biasa, sebagai berikut.

confirmation.jsp

<code><%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>


<!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=UTF-8">
        <title>:: Konfirmasi Pendaftaran ::</title>
    </head>
    <body>

    <h1>Registrasi Berhasil !!</h1>
    
    </body>
</html>
</code>

Kedua halaman tersebut akan diakses dengan URL :

  1. http://localhost:8080/HelloJSF/register.jsf

  2. http://localhost:8080/HelloJSF/confirmation.jsf

Perhatikan bahwa kita mengakses halaman tersebut dengan URL *.jsf, padahal nama file sebenarnya adalah *.jsp.

Jadi, yang terjadi di sini adalah, kita menyerahkan pemrosesan semua URL berakhiran jsf kepada servlet JSF.

Oleh karena itu, kita perlu mendefinisikan Servlet JSF dan URL Mapping tersebut pada web.xml.

web.xml

<code><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>
</code>

Isi web.xml sudah dijelaskan pada artikel sebelumnya tentang ICEFaces.

Selanjutnya, mari kita lihat konfigurasi navigasinya, yang menyatakan:

bila tombol Daftar ditekan, bukalah halaman confirmation.jsp

Konfigurasi tersebut ditulis di dalam file faces-config.xml sebagai berikut.

faces-config.xml

<code><?xml version='1.0' encoding='UTF-8'?>

<faces-config version="1.2" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
        <navigation-rule>            
            <from-view-id>/register.jsp</from-view-id>
            <navigation-case>
                <from-outcome>register</from-outcome>
                <to-view-id>/confirmation.jsp</to-view-id>
            </navigation-case>
        </navigation-rule>
</faces-config>
</code>

Pada konfigurasi di atas, kita mendefinisikan view bernama register.jsp, yaitu halaman registrasi kita. Kemudian ada navigation case, yang merupakan aturan navigasi untuk halaman register.jsp tersebut. Bila dihasilkan action register, tampilkan halaman confirmation.jsp.

Action register ini didapat dari nilai atribut action pada komponen tombol Daftar di dalam file register.jsp.

Di masa yang akan datang, nantinya konfigurasi navigasi ini akan diedit dengan visual editor. Sehingga kita bisa langsung drag-and-drop halaman, kemudian menggambar panah dari halaman register.jsp ke confirmation.jsp dengan tulisan ‘register’.

Aplikasi HelloJSF siap dideploy. Struktur folder lengkapnya tampak seperti ini.

Struktur Folder Aplikasi HelloJSF

Pembaca yang teliti akan segera bertanya,

Apa tidak kurang? Mana *.jar nya? Tidak ada *.jar apa-apa di sana!

Itu karena saya mendeploy ke Sun Application Server yang terbundle bersama Netbeans Enterprise Pack. Kalau saja kita deploy ke Tomcat atau Jetty, tentu lain ceritanya. Kita harus melihat dokumentasi masing-masing merek server.

Demikian perkenalan kita dengan JSF. Lain waktu kita akan sambung dengan kemampuan JSF yang lainnya.


Intro ICEFaces

Beberapa waktu terakhir ini, framework Java Server Faces terlihat semakin matang. Orang-orang sudah mulai menggunakan, memberi feedback, dan menemukan best-practices cara penggunaannya. Oleh karena itu, saya pikir sudah tiba waktunya untuk saya mempelajari framework tersebut.

Berdasarkan pengalaman rekan Samuel, dia menganjurkan penggunaan JSF dengan menggunakan stack:

Spring dan Hibernate sudah sering saya gunakan. Integrasinya dengan JSF juga tidak terlalu sulit. Hanya butuh registrasi bean di dalam konfigurasi JSF.

Facelets adalah template engine untuk JSF. Dalam dunia JSF, template engine sering disebut juga dengan istilah View Renderer. Sebenarnya View Renderer default JSF adalah JSP, tapi saya tidak suka JSP. Jadilah akhirnya kita pakai JSF dengan Facelets sebagai ViewRenderer-nya. Facelets ini mirip dengan Freemarker atau Velocity. Kalau di dunia PHP kira-kira padanannya adalah Smarty.

Keuntungan menggunakan Facelets dibanding JSP adalah dengan Facelets, desain tampilan dapat dikerjakan oleh web designer. JSF dengan JSP akan banyak sekali menggunakan taglib yang tidak akan muncul di Macromedia Dreamweaver atau editor HTML lainnya. Facelets menggunakan pendekatan yang mirip dengan Tapestry, yaitu memasukkan komponen ke dalam elemen HTML biasa, sehingga dapat dilihat secara normal oleh editor HTML.

ICEFaces adalah kumpulan komponen JSF. Dia memiliki teknologi Direct to DOM Rendering sehingga kita dapat membuat tampilan ber-AJAX dengan mudah.

Seperti halnya teknologi lainnya di dunia Java, JSF hanyalah berupa spesifikasi. Kita dapat menggunakan implementasi yang dikeluarkan Sun (sering disebut dengan Reference Implementation - RI), atau menggunakan implementasi orang lain. Selain Sun, Apache mengeluarkan MyFaces dan Oracle mengeluarkan ADF sebagai implementasi JSF.

Pada artikel ini, kita akan lihat Hello World dengan menggunakan JSF, Facelets, dan ICEFaces. Karena ini hanya perkenalan saja, requirementnya tidak rumit. Saya hanya ingin membuktikan kecanggihan teknologi Direct to DOM Rendering yang dimiliki ICEFaces. Konon teknologi ini memungkinkan kita mengupdate tampilan di sisi client dari server dengan mudah.

Aplikasi yang ingin kita buat sangat sederhana, tapi sering menjadi pertanyaan di berbagai milis pemrograman web. Kita akan membuat satu halaman yang menampilkan waktu server. Waktu server ini harus berjalan secara real-time.

Dalam bahasa pemrograman lain, menampilkan jam server secara real time di browser bukanlah suatu hal yang mudah. Programmer harus memilih satu di antara beberapa teknik berikut:

  • Menggunakan meta refresh untuk request ke server setiap beberapa detik

  • Mengambil jam server sekali saja di awal loading page, kemudian increment nilainya di sisi client dengan JavaScript

  • Menggunakan streaming HTML

  • Menggunakan AJAX Push

Atau berbagai teknik lainnya. Yang jelas tidak mudah untuk melakukan hal ini.

Dengan menggunakan JSF + ICEFaces, hal ini menjadi mudah. ICEFaces adalah salah satu implementasi JSF yang menggunakan teknologi Direct to DOM Rendering. Artinya, server bisa seenaknya mengubah HTML yang ada di sisi client (browser). Dengan teknik ini, menampilkan jam server secara real time menjadi mudah.

Berikut adalah langkah-langkahnya:

  1. Buat halaman HTML yang akan menampilkan waktu server

  2. Buat kode Java yang bertugas menyediakan waktu server

  3. Gunakan JSF + ICEFaces untuk menghubungkan keduanya

  4. Aktifkan partial rendering agar tidak menimbulkan flicker

Mari kita bahas satu persatu.

Halaman HTML

Halaman ini adalah halaman dinamis yang berisi nilai yang dikeluarkan oleh server. Bedakan dengan halaman dinamis yang dikendalikan oleh JavaScript, di mana pada kasus tersebut tidak dibutuhkan sisi server yang menyediakan data.

Kode tampilan ini sederhana saja. Dibuat dalam format XHTML, karena begitulah keinginan Facelets.

whattimeisit.xhtml

<code><!-- <?xml version="1.0" encoding="UTF-8"?> -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>:: Menampilkan Jam Server ::</title>
    </head>
    <body>
        <p>
                <b>Waktu Server Saat Ini : #{serverClock.currentTime}</b>
        </p>
    </body>
</html>
</code>

Perhatikan bahwa satu-satunya dynamic code di atas adalah #{serverClock.currentTime}. Sisanya HTML biasa. Bagi yang belum tahu, dynamic code tersebut ditulis dalam Expression Language (EL) yang didukung oleh JSF. Kalau di dalam Java, kode tersebut sama dengan serverClock.getCurrentTime(). Sekarang mari kita lihat kode Java yang membekingi template whattimeisit, yaitu ServerClock.java.

ServerClock.java

<code>package tutorial.icefaces;

import com.icesoft.faces.async.render.IntervalRenderer;
import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class ServerClock implements Renderable {
    private DateFormat formatter;
    private PersistentFacesState state;
    private IntervalRenderer renderer;
    private static final int renderInterval = 1000; // render setiap 1 detik

    public ServerClock() {
        formatter = new SimpleDateFormat("EEE, HH:mm:ss");
        state = PersistentFacesState.getInstance();
    }
    
    public String getCurrentTime() {
        return formatter.format(Calendar.getInstance().getTime());
    }

    public PersistentFacesState getState() {
        return state;
    }

    public void renderingException(RenderingException renderingException) {
        if(renderer != null) {
            renderer.remove(this);
            renderer = null;
        }
    }
    
    public void setRenderManager(RenderManager manager) {
        renderer = manager.getIntervalRenderer("whattimeisit");
        renderer.setInterval(renderInterval);
        renderer.add(this);
        renderer.requestRender();
    }
}            
</code>

Constructor dan method getCurrentTime tidak terlalu istimewa. Isinya hanya inisialisasi DateFormat dan kegiatan memformat waktu saat ini menjadi String.

Selain constructor, setter, dan getter, kode lainnya berkaitan dengan pengelolaan internalnya ICEFaces. Dalam method setRenderManager, kita menyuruh ICEFaces untuk mengupdate browser setiap 1 detik. RenderManager adalah object yang bertugas merender tampilan. Dia beroperasi ke sekumpulan Renderable, yang salah satunya adalah class kita ServerClock.

Bila kita mengimplementasikan Renderable, ada dua method yang harus kita sediakan, yaitu renderingException dan getState. Method ini dengan mudah dapat kita buat. Selain kedua method ini, ICEFaces tidak butuh tambahan kode lagi.

Saatnya kita siapkan konfigurasi. JSF membutuhkan dua konfigurasi, yaitu web.xml (seperti aplikasi web biasa) dan faces-config.xml. Mari kita lihat web.xml sedikit demi sedikit.

<code>    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>
</code>

Kode di atas adalah konfigurasi untuk JSF. Konfigurasi ini berlaku umum, terlepas dari kita menggunakan Facelets dan ICEFaces ataupun library lainnya. Selanjutnya adalah konfigurasi Facelets.

<code>    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>
</code>

Pada konfigurasi di atas, kita mengganti default ekstensi file template, yang tadinya jsp atau jspx menjadi xhtml. Kita juga memberitahu Facelets bahwa kita sedang dalam tahap development. Dengan demikian, pesan error yang dikeluarkan akan lebih lengkap sehingga memudahkan debugging.

Selanjutnya, mari kita lihat konfigurasi ICEFaces.

<code>    <context-param>
        <param-name>com.icesoft.faces.uploadDirectory</param-name>
        <param-value>upload</param-value>
    </context-param>
    <context-param>
        <param-name>com.icesoft.faces.uploadMaxFileSize</param-name>
        <param-value>4048576</param-value>
    </context-param>
    <context-param>
        <param-name>com.icesoft.faces.concurrentDOMViews</param-name>
        <param-value>true</param-value>
    </context-param>
</code>

Dua konfigurasi pertama sudah cukup jelas, mengatur tentang di mana harus meletakkan file hasil upload dan berapa maksimal ukuran file yang dapat diterima. Konfigurasi ketiga menyuruh ICEFaces berhati-hati agar dapat melayani request berbarengan ke satu halaman yang sama.

Setelah selesai dengan konfigurasi context param, mari kita masuk ke bagian servlet. JSF membutuhkan satu servlet yang harus dijalankan pada saat aplikasi diaktifkan.

<code>    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
</code>

Servlet ini tidak perlu dimapping ke URL, karena nantinya kita akan menggunakan servlet ICEFaces.

ICEFaces membutuhkan beberapa servlet, terlihat pada konfigurasi berikut.

<code>    <servlet>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>Blocking Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>uploadServlet</servlet-name>
        <servlet-class>com.icesoft.faces.component.inputfile.FileUploadServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
</code>

Selain itu, ICEFaces juga membutuhkan satu listener, dideklarasikan diatas deklarasi servlet.

<code>    <listener>
        <listener-class>com.icesoft.faces.util.event.servlet.ContextEventRepeater</listener-class>
    </listener>
</code>

Servlet ICEFaces dimapping sebagai berikut.

<code>    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>/xmlhttp/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>*.iface</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Blocking Servlet</servlet-name>
        <url-pattern>/block/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>uploadServlet</servlet-name>
        <url-pattern>/uploadHtml</url-pattern>
    </servlet-mapping>
</code>

Terakhir untuk web.xml, kita perlu mendefinisikan session timeout.

<code>    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</code>

Hasil akhirnya adalah seperti ini.

web.xml

<code><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>com.icesoft.faces.uploadDirectory</param-name>
        <param-value>upload</param-value>
    </context-param>
    <context-param>
        <param-name>com.icesoft.faces.uploadMaxFileSize</param-name>
        <param-value>4048576</param-value>
    </context-param>
    <context-param>
        <param-name>com.icesoft.faces.concurrentDOMViews</param-name>
        <param-value>true</param-value>
    </context-param>
    
    
    <listener>
        <listener-class>com.icesoft.faces.util.event.servlet.ContextEventRepeater</listener-class>
    </listener>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>Blocking Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>uploadServlet</servlet-name>
        <servlet-class>com.icesoft.faces.component.inputfile.FileUploadServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>/xmlhttp/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>*.iface</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Blocking Servlet</servlet-name>
        <url-pattern>/block/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>uploadServlet</servlet-name>
        <url-pattern>/uploadHtml</url-pattern>
    </servlet-mapping>


    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>
</code>

Selanjutnya, mari kita buat konfigurasi JSF. File konfigurasinya bernama faces-config.xml. Ini diletakkan di dalam folder WEB-INF, di sebelah web.xml. Berikut adalah kodenya.

faces-config.xml

<code><?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">

    <application>
        <view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>
    </application>
    
    
    <managed-bean>
        <managed-bean-name>renderManager</managed-bean-name>
        <managed-bean-class>com.icesoft.faces.async.render.RenderManager</managed-bean-class>
        <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>
    
    <managed-bean>
        <managed-bean-name>serverClock</managed-bean-name>
        <managed-bean-class>tutorial.icefaces.ServerClock</managed-bean-class>        
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>renderManager</property-name>
            <value>#{renderManager}</value>
        </managed-property>
    </managed-bean>
</faces-config>
</code>

Pada blok paling atas, kita mengkonfigurasi JSF agar menggunakan View Renderer Facelets yang sudah dilengkapi dengan ICEFaces. Di blok kedua, kita mendeklarasikan bean renderManager yang dibutuhkan oleh object kita serverClock pada blok ketiga.

Bagi yang sudah biasa menggunakan Spring, konfigurasi ini tidak jauh berbeda dengan konfigurasi Dependency Injection Spring. Nantinya bila kita menggunakan Spring, kita juga bisa mendeklarasikan Spring bean kita di dalam faces-config.xml tersebut.

Terakhir, jangan lupa lengkapi jar yang dibutuhkan agar kode kita bisa dikompilasi dan dideploy dengan mulus. Kombinasi jar yang dibutuhkan relatif bervariasi tergantung application server yang kita gunakan. Kadangkala ada jar yang sudah disediakan oleh application server tertentu, sehingga kita tidak perlu lagi menyediakan. Sebagai contoh, bila dideploy di Sun Application Server (Glassfish) yang terbundle bersama Netbeans 5.5, daftar jar yang dibutuhkan adalah:

  • backport-util-concurrent.jar

  • commons-collections.jar

  • commons-digester.jar

  • commons-fileupload.jar

  • commons-logging-1.0.4.jar

  • el-api.jar

  • icefaces-comps.jar

  • icefaces-facelets.jar

  • icefaces.jar

  • krysalis-jCharts-1.0.0-alpha-1.jar

  • xercesImpl.jar

  • xml-apis.jar

Struktur folder akhir dari aplikasi ini adalah sebagai berikut.

Struktur Folder Aplikasi JSF

Untuk Eclipse, daftar pustaka yang dibutuhkan sedikit berbeda. Demikian gambarnya. Daftar pustaka ICEFaces untuk Eclipse

Setelah semua file dibuat dan dipaket sesuai dengan aturan aplikasi web Java, kita bisa mendeploynya ke application server. Lalu, silahkan mengakses http://localhost:8080/HelloICE/whattimeisit.iface atau URL lain sesuai setting deployment.

Hasilnya akan tampak seperti ini.

Tampilan Akhir Server Time

Namun demikian, ternyata halaman tersebut masih melakukan refresh setiap satu detik sehingga mengganggu pandangan. Oleh karena itu, mari kita aktifkan fitur partial submit yang dimiliki ICEFaces. Dengan fitur ini, halaman HTML akan diupdate secara parsial sehingga tidak perlu me-reload seluruh halaman.

Buka file whattimeisit.xhtml dan cari baris berikut.

<code><body>
        <p>
                <b>Waktu Server Saat Ini : #{serverClock.currentTime}</b>
        </p>
    </body>
</code>

Ubah menjadi seperti ini.

<code><body>
        <p>
		<ice:form partialSubmit="true">
                <b>Waktu Server Saat Ini : #{serverClock.currentTime}</b>
		</ice:form>
        </p>
    </body>
</code>

Jangan lupa untuk mendeklarasikan komponen di awal halaman, dengan menggunakan tag sebagai berikut.

<code><f:view xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ice="http://www.icesoft.com/icefaces/component"></code>

Keseluruhan file whattimeisit.xhtml akan terlihat seperti ini.

<code><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ice="http://www.icesoft.com/icefaces/component">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>What time is it</title>
</head>
<body>
<ice:form>
<p>
                <b>Waktu Server Saat Ini : #{serverClock.currentTime}</b>
        </p>
</ice:form>
</body>
</html>
</f:view></code>

Redeploy aplikasi, dan lihat hasilnya. Tidak ada lagi flicker (kedipan).

Eclipse project untuk contoh di atas dapat didownload di sini.

Selamat mencoba, semoga bermanfaat.


Virtual Box

Oom Sindu beberapa hari ini berisik sekali membahas Virtual Box. Sudah beberapa artikel dia tulis, sehingga akhirnya saya tertarik untuk mencoba.

Virtual Box adalah aplikasi virtualization. Gunanya untuk menjalankan OS (Operating System) di dalam OS. Misalnya komputer kita berisi Linux, kemudian kita ingin mencoba berbagai ‘distro’ Windows seperti Vista atau 2003 server. Agar kita tidak repot, gunakan aplikasi virtualization sehingga kita bisa menjalankan OS lain seperti layaknya menjalankan aplikasi biasa. Dalam satu virtual machine, kita bisa menjalankan banyak OS lain.

Saya adalah penggemar berat aplikasi virtualization. Alasannya, saya menggunakan Linux sebagai OS utama, tapi masih harus menggunakan Windows untuk membuat dokumen untuk orang lain. Selain itu, saya juga butuh beberapa versi browser untuk mengetes aplikasi web yang saya buat.

Aplikasi virtualization juga sangat bermanfaat untuk project software development. Kita bisa buat satu virtual machine untuk menghosting Subversion repository server, bugtracker, aplikasi project management, dan build server. Backupnya juga mudah. Cukup copy file virtual machine tersebut ke DVD. Biasanya saya gunakan VM berukuran 8 GB, sehingga butuh 2 DVD sekali backup. When disaster strike, cukup copy file backup, server langsung up kembali tanpa butuh waktu lama untuk instal dan konfigurasi.

Dalam dunia virtualization, dikenal istilah host OS (OS tuan rumah) dan guest OS (OS tamu). Host OS adalah sistem operasi utama kita, sedangkan guest OS adalah OS yang berjalan di atas virtual machine.

Sebelum ini, saya sudah mencoba beberapa aplikasi lain, seperti VMWare, Qemu, dan Xen. Notebook saya memiliki spesifikasi Centrino 1.8GHz dan 512 (shared) RAM. Hasilnya, Xen tidak berhasil diinstal dengan pesan error ‘something about unsupported kernel and processor’. VMWare Server (gratis) dan Qemu (open source) berhasil diinstal dengan mulus. Pada waktu dijalankan, Qemu sedikit lebih ringan daripada VMWare. Dengan VMWare, pada saat guest OS Windows 2000 saya nyalakan, guest OS berjalan seperti keong racun abis kena garam. Sangat pelan. Padahal belum ada aplikasi yang dijalankan di guest OS. Praktis guest OS berikut host OS (Ubuntu Dapper) tidak dapat digunakan, karena ke-lemot-annya sudah mencapai taraf unusable.

Dengan Qemu, guest OS berjalan lambat, tapi host OS masih bisa digunakan dengan nyaman.

Ok, sekarang kita bahas virtualbox. Dari sisi instalasi, tidak ada masalah berarti. Ada beberapa petunjuk instalasi di blog Ubuntu Indonesia dan blog Oom Sindu yang bisa diikuti.

Khusus untuk saya, setelah langkah-langkah pada tutorial di atas dilakukan, virtualbox masih belum jalan. Saya harus menjalankan perintah berikut

$ sudo make -C /opt/VirtualBox-1.3.6/src install

karena ada sedikit masalah dengan kernel module.

Setelah itu, Virtual Box dapat dijalankan dengan sempurna.

Setelah saya instal Windows 2000 Professional (tahu diri gak berani install Vista dengan spec pas-pasan ;p), saya sangat terkesan. Guest OS berjalan dengan mulus dan cukup responsif tanpa mengganggu Host OS. Saat mengetik artikel ini, saya sedang menginstal Service Pack 4 di Guest OS. Di Host OS, saya sedang mendengarkan podcast David Maister, browsing Firefox dengan 6 tab terbuka, 2 diantaranya GMail dan Google Calendar -dua aplikasi web yang terkenal rakus memori karena terlalu ‘ajax’.

Hebatnya, tidak patah sedikitpun. Baik guest OS dan host OS dapat dijalankan dengan nyaman. Good luck trying the same using VMWare. Hmm .. saya jadi teringat iklan DVD player di TV yang diperankan Basuki.

Bravo Virtual Box. Best things in the world available for free. :D


Membuat aggregator dengan MagpieRSS

Pada artikel ini, kita akan belajar cara menambahkan feed aggregator di website kita. Untuk mudahnya, kita gunakan pustaka Magpie RSS. Dengan library ini, kita bisa membuat website yang berisi rangkuman dari website-website lain (web-based aggregator).

Penjelasan tentang apa itu RSS dapat dilihat di artikel ini.

Cara penggunaan Magpie RSS

Setelah donlod dan extract, copy empat file magpie:

  • rss_cache.inc

  • rss_fetch.inc

  • rss_parse.inc

  • rss_utils.inc

Berikut file dependensinya yang ada di folder extlib.

Selanjutnya, untuk mengolah RSS feed, hanya dibutuhkan tiga baris kode:

require_once('inc/rss_fetch.inc');
$url = "http://www.php.net/news.rss";
$rss = fetch_rss($url);

Variabel $rss tinggal dilooping dan ditampilkan sesuai keinginan. Sebagai contoh, saya tampilkan isi feed dalam tabel.

<table border="1">
    <tr><th>No</th><th>Judul</th><th>Ringkasan</th></tr>
    <? $i=0; foreach ($rss->items as $item) { $i++; ?>
    <tr>
        <td><?=$i ?></td>
        <td><a href="<? echo($item[link]); ?>"><? echo($item[title]); ?></a></td>
        <td><? echo($item[description]); ?></td>
    </tr>
    <? } ?>
</table>

Hasilnya dapat dilihat di sini. Sedangkan source codenya dapat didownload di sini.

Demikian … cukup mudah bukan? Selamat menampilkan rangkuman website orang di website anda sendiri. Jangan lupa memperhatikan etika dan hak cipta.


Apa itu RSS ?

Sudah tau RSS?

Jika Anda bukan programmer, wajar jika tidak tahu. Tapi jika Anda programmer … jangan sampai tidak tahu. Apalagi bilang,

RSS itu kan sama dengan CSS …

RSS itu banyak kepanjangannya, beberapa diantaranya antara lain:

  • Really Simple Syndication

  • Rich Site Summary

  • RDF Site Summary

RSS berisi rangkuman dari isi suatu website. Misalnya kita mengunjungi website yang berisi banyak artikel. Kita bisa mengambil data RSSnya, yang berisi :

  • Judul Artikel

  • Tanggal Publish

  • Pengarang

  • Potongan isinya

Sebagai contoh, misalnya kita ingin selalu mengikuti perkembangan terbaru di dunia PHP. Cukup masukkan URL http://www.php.net/news.rss di aplikasi aggregator. Nanti aplikasi aggregator akan menampilkan RSS feed tersebut dengan antarmuka yang mudah dibaca.

Ada beberapa versi format data RSS, yaitu versi 0.9, 0.91, 1.0, dan 2.0. Selain itu, juga ada format lain yang namanya Atom. Data ini (baik RSS maupun Atom) tersebut dikemas dalam format XML, yang nantinya dapat dibaca oleh aplikasi yang namanya aggregator. Ulasan tentang berbagai jenis aplikasi aggregator berbasis desktop dapat dilihat di sini.

Aplikasi aggregator juga ada yang berbasis web. Misalnya Google Reader dan Bloglines. Kita juga bisa membuat sendiri dengan menggunakan library Magpie RSS atau menggunakan plugin di berbagai aplikasi Content Management System populer. Biasanya aplikasi populer seperti Wordpress, Drupal, atau Joomla sudah memiliki plugin untuk itu. Contoh nyatanya bisa dilihat di website Pak Cipi. Website ini dibuat dengan Drupal.

Cara kerja aplikasi aggregator sama dengan aplikasi mail client (Outlook Express, Evolution, atau Thunderbird). Bedanya, kalau aplikasi mail client mengambil data email dari mail server, aplikasi aggregator mengambil data RSS dari website yang menyediakan. Kita bisa memasukkan website sebanyak-banyaknya sesuai keinginan kita. Nantinya, kalau website yang kita daftarkan merilis artikel/berita baru, rangkumannya akan muncul di aggregator kita. Di aplikasi aggregator akan muncul entri Unread Items seperti halnya Unread Mails. Aplikasi aggregator ini berguna agar kita tidak perlu mengunjungi setiap website satu persatu. Cukup lihat judul dan ringkasan artikel baru. Jika menarik, kita kunjungi websitenya. Jika tidak menarik, diabaikan saja.

Demikianlah penjelasan singkat tentang RSS. Jangan salah lagi membedakan antara RSS dan CSS.

They are different !!