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.

BerkeleyDB Java Edition

Beberapa waktu yang lalu, ada posting menarik tentang Google yang menggunakan BerkeleyDB untuk mengelola user accountnya. Karena penasaran, saya lalu mencoba mendownload dan bermain-main dengan BerkeleyDB versi Java (Java Edition).

BerkeleyDB adalah produk embedded database open source yang populer. Belum lama ini dia diakuisisi oleh Oracle, sehingga membuat produk ini makin terkenal lagi.

Pada tulisan kali ini, kita akan mencoba menggunakan BDB Java Edition.

Tapi jangan salah paham dengan namanya. BerkeleyDB adalah database, tapi bukan relational database. Artinya, dia tidak memiliki fasilitas SQL. Walaupun demikian, dia mendukung ACID transaction. Salah satu contoh penggunaan BDB adalah pada aplikasi version control Subversion.

Kalau tidak ada SQLnya, bagaimana kita melakukan operasi CRUD? Jawabnya adalah, anggap saja BDB sebagai Map. Kita bisa menggunakan Map seperti ini:

    Map myMap = new HashMap();
    myMap.put(1, "Endy");

Maka object String akan disimpan dengan key 1. Object ini dapat diambil dengan kode:

    String data = myMap.get(1);

Bagi mereka yang sudah pernah mendengar Object Database tentunya sudah familiar dengan konsep seperti ini. Salah satu implementasi konsep ini adalah db40 atau Prevayler.

Sekarang, coba kita gunakan contoh kasus yang standar. Ada class Person yang akan kita buatkan operasi CRUD-nya. Berikut kodenya:

Person.java

    package tutorial.berkeleydb;
    
    import java.util.Date;
    
    import com.sleepycat.persist.model.Entity;
    import com.sleepycat.persist.model.PrimaryKey;
    
    @Entity
    public class Person {
            
            @PrimaryKey(sequence="ID")
            private Integer id;
            private String name;
            private Date birthdate;
            private String email;
            
            public Person(){
                    
            }
            
            public String getEmail() {
                    return email;
            }
            public void setEmail(String address) {
                    this.email = address;
            }
            public Date getBirthdate() {
                    return birthdate;
            }
            public void setBirthdate(Date birthdate) {
                    this.birthdate = birthdate;
            }
                    
            public Integer getId() {
                    return id;
            }
            public void setId(Integer id) {
                    this.id = id;
            }
            public String getName() {
                    return name;
            }
            public void setName(String name) {
                    this.name = name;
            }
    }

Perhatikan bahwa untuk menjadikan class Person persistent, kita hanya perlu menambahkan annotation, mirip dengan JPA atau Hibernate. Sekarang mari kita definisikan interface CRUD-nya.

PersonDao.java

    package tutorial.berkeleydb;
    
    import java.util.List;
    
    public interface PersonDao {
            public void save(Person p);
            public void delete(Person p);
            public Person getById(Integer id);
            public List<Person> getAll();
    }

Dan berikut adalah implementasinya.

PersonDaoBerkeleyDB

    package tutorial.berkeleydb;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.persist.EntityCursor;
    import com.sleepycat.persist.EntityStore;
    import com.sleepycat.persist.PrimaryIndex;
    
    public class PersonDaoBerkeleyDB implements PersonDao {
    
            private PrimaryIndex<Integer, Person> personPrimaryKey;
            
            public PersonDaoBerkeleyDB(EntityStore storage) {
                    try {
                            personPrimaryKey = storage.getPrimaryIndex(Integer.class, Person.class);
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }
            }
            
            public void delete(Person p) {
                    try {
                            personPrimaryKey.delete(p.getId());
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }
            }
    
            public List<Person> getAll() {
                    List<Person> result = new ArrayList<Person>();
                    try {
                            EntityCursor<Person> allPerson = personPrimaryKey.entities();
                            Iterator<Person> iter = allPerson.iterator();
                            while (iter.hasNext()) {
                                    result.add(iter.next());
                            }
                            allPerson.close();
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }
                    return result;
            }
    
            public Person getById(Integer id) {
                    try {
                            return personPrimaryKey.get(id);
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }
                    return null;
            }
    
            public void save(Person p) {
                    try {
                            personPrimaryKey.put(p);
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }		
            }
    
    
    }

Sebagai perbandingan, berikut kode CRUD menggunakan Hibernate dengan bantuan Spring.

    public class PersonDaoHibernate extends HibernateDaoSupport implements PersonDao{
        public void save(Person p){
            getHibernateTemplate().save(p);
        }
        
        public void delete(Person p){
            getHibernateTemplate().delete(p);
        }
        
        public Person getById(Integer id){
            Person result = null;
            try {
                    result = (Person) getHibernateTemplate().load(Person.class, id);
                    getHibernateTemplate().initialize(result);
            } catch (ObjectRetrievalFailureException e) {
                    log.log(Level.WARNING, "no object with id:"+id+" in database");
            }
            return result;
        }
        
        public List<Person> getAll(){
            return getHibernateTemplate().find("from Person p");
        }
    }

Oh iya, contoh kode BDB di atas dapat diujicoba dengan membuat Main class sebagai berikut:

Main.java

    package tutorial.berkeleydb;
    
    import java.io.File;
    
    public class Main {
            private static EntityStore store;
            private static Environment env;
            
            public static void main(String[] args) throws Exception {
                    openDatabase();
                    
                    Person endy = new Person();
                    endy.setName("Endy Muhardin");
                    endy.setBirthdate(new SimpleDateFormat("dd-MM-yyyy").parse("17-08-1945"));
                    endy.setEmail("endymuhardin@yahoo.com");
                    
                    PersonDao dao = new PersonDaoBerkeleyDB(store);
                    dao.save(endy);		
                    System.out.println("======== Create one person with ID:"+endy.getId()+" ========");
                    
                    System.out.println("======== Display all person from database ========");
                    List<Person> all = dao.getAll();
                    for (Person person : all) {
                            displayPerson(person);
                    }
                    
                    System.out.println("======== Add one more person to database ========");
                    Person khalisa = new Person();
                    khalisa.setName("Khalisa Alayya");
                    khalisa.setBirthdate(new SimpleDateFormat("dd-MM-yyyy").parse("31-12-2000"));
                    khalisa.setEmail("me@khalisa.web.id");
                    dao.save(khalisa);
                    
                    System.out.println("======== Display all person from database ========");
                    all = dao.getAll();
                    for (Person person : all) {
                            displayPerson(person);
                    }
                    
                    System.out.println("======== Get person by ID "+endy.getId()+" from database ========");
                    Person endyFromDb = dao.getById(endy.getId());		
                    displayPerson(endyFromDb);
                    
                    System.out.println("======== Change person data with ID "+endy.getId()+" from database ========");
                    endyFromDb.setEmail("endy.muhardin@gmail.com");
                    dao.save(endyFromDb);
                    
                    System.out.println("======== Display person with ID "+endy.getId()+" after update ========");
                    Person endyFromDb2 = dao.getById(endy.getId());		
                    displayPerson(endyFromDb2);
                    
                    closeDatabase();
            }
            
            private static void displayPerson(Person person) {
                    System.out.println("ID : "+person.getId());
                    System.out.println("Name : "+person.getName());
                    System.out.println("Birthdate : "+person.getBirthdate());
                    System.out.println("Address : "+person.getEmail());
            }
            
            private static void openDatabase(){				
                    try {			
                            EnvironmentConfig config = new EnvironmentConfig();
                            config.setAllowCreate(true);
                            config.setTransactional(true);
                            
                            env = new Environment(new File("database"), config);
                            
                            StoreConfig storeConfig = new StoreConfig();
                            storeConfig.setAllowCreate(true);
                            storeConfig.setTransactional(true);
                            
                            store = new EntityStore(env, "PersonDatabase", storeConfig);			
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }			
            }
            
            private static void closeDatabase() {
                    try {
                            store.close();
                            env.close();
                    } catch (DatabaseException e) {
                            e.printStackTrace();
                    }
            }
    }

Selain contoh kode yang ditampilkan di sini, sebetulnya BDB juga mendukung asosiasi One to One, One to Many, dan Many to Many. Sayang sekali saya belum sempat coba.

Dari percobaan sederhana ini, kita dapat menarik beberapa sisi positif dan negatif dari BerkeleyDB, juga kemungkinan kasus yang tepat dan tidak tepat untuk menggunakan BDB.

Positif

  • Ukuran jar kecil. Hanya butuh 1.1 MB untuk jar-nya BDB. Bandingkan jika kita gunakan MySQL + Hibernate. Jar mysql-connector 430KB, hibernate.jar 2MB, hibernate-annotation.jar 300KB, dependensi lainnya seperti ehcache, jta, cglib, asm, dan lainnya bisa mencapai 7MB total.
  • Tidak perlu berkutat dengan SQL. Object oriented 100%
  • Karena embedded, sangat cepat. Akses data instan langsung ke sumbernya. Bandingkan dengan rantai MySQL-network-hibernate-spring-aplikasi. Bagaikan langit dan bumi.

Negatif

  • Karena embedded, sulit dimanipulasi dengan tools lain. Berbeda dengan database RDBMS yang bisa diakses menggunakan command line, web-based interface, atau database management tools.
  • Karena tidak support SQL, tidak bisa dimanipulasi aplikasi lainnya. Misalnya aplikasi reporting.
  • Untuk sharing data dengan aplikasi lain, kita harus buatkan API via Java atau XML.
  • BDB mengandalkan Serialization untuk menyimpan object ke dalam database. Siapapun yang sudah pernah belajar Serialization pasti tahu bahwa penyakitnya ada pada class evolution. Kalau class kita berubah –misalnya menambah atau mengurangi field, apalagi rename class– BDB akan bingung, dan kita harus menulis kode program untuk melakukan migrasi.

Kapan menggunakan BDB

  • Data yang disimpan hanya digunakan sendiri. Misalnya penyimpanan data session HTTP, cache untuk username dan password, dsb.
  • Butuh kecepatan extra tinggi dan pemrograman yang mudah. Misalnya kita membuat server SMS gateway atau message processing. Butuh kecepatan tinggi, dan datanya kecil kemungkinan digunakan aplikasi lain.
  • Anda termasuk orang yang living on the edge. Selalu menggunakan tools yang aneh dan terbaru.

Kapan menggunakan RDBMS

  • Data harus bisa diakses aplikasi lain seperti reporting.
  • Data berjumlah besar, sehingga sulit untuk dimigrasi apabila terjadi refactoring. (Ingat masalah Serialization)
  • Perusahaan sudah terlanjur beli Oracle atau DB2.

Demikianlah .. semoga bermanfaat. :D


Menggunakan Eclipse BIRT [bagian 1]

Programmer beraliran komersial tentunya sudah tidak asing dengan perlengkapan reporting seperti Crystal Report. Reporting tools ini berguna untuk membuat laporan dari sumber data yang sudah ada.

Cara kerjanya sederhana. Bagi yang belum pernah menggunakan aplikasi reporting dan ingin memahaminya secara sederhana, dapat menggunakan fasilitas mail merge yang dimiliki aplikasi office seperti Microsoft Word atau OpenOffice Writer.

Intinya, kita membuat satu template. Di dalam template tersebut kita isikan variabel-variabel yang kita ingin tampilkan. Pada saat dijalankan (runtime), variabel ini akan digantikan oleh template processor dengan data yang diambil dari sumber data eksternal.

Contoh umum penggunaan fasilitas mail merge adalah untuk mencetak label alamat pada undangan. Kita definisikan variabel yang akan tampil, misalnya:

  • Nama
  • Alamat
  • Kota

Kemudian, kita sediakan file lain di spreadsheet (MS Excel atau OO Calc) yang memuat data tersebut. Data yang disimpan bisa saja ratusan atau ribuan. Untuk Open Office, database yang digunakan tidak hanya dari spreadsheet, tapi bisa juga dari database betulan seperti MySQL atau Oracle.

Setelah template dan data siap, aplikasi dijalankan untuk melakukan merge. Hasilnya adalah ratusan label yang sudah terisi dengan data dari database.

Logika yang sama digunakan oleh perlengkapan reporting seperti Crystal Report dan kompetitor lainnya. Biasanya template dibuat dalam format XML. Selanjutnya, prosesnya sama. Desain templatenya, kemudian siapkan datanya.

Saya tidak akan membahas Crystal Report di sini. Kita akan membahas aplikasi reporting yang gratis, yaitu Eclipse BIRT. Sebagai bagian dari Eclipse, aplikasi ini gratis dan berkualitas tinggi.

Fitur BIRT juga tidak kalah dengan aplikasi reporting lain, diantaranya adalah:

  1. Berbagai pilihan datasource; RDBMS, XML, Text File, dan lain-lain. Lain-lain maksudnya di sini adalah sumber lain yang dapat diakses melalui scripting language BIRT.
  2. Berbagai pilihan output; PDF, XLS, CSV, HTML, XML adalah format yang didukung. Untuk format lain, asalkan berbasis text, bisa menggunakan output XML yang kemudian diproses lagi menggunakan XSLT.
  3. Berbagai pilihan integrasi. BIRT dapat dijalankan sebagai standalone report server, atau juga diembed (digabungkan) dengan aplikasi kita. Bila dijalankan sebagai standalone server, BIRT dapat berkomunikasi dengan aplikasi dengan bahasa pemrograman yang berbeda, misalnya PHP, Ruby, .Net, atau yang lainnya.
  4. Visual Designer. Eclipse sudah melengkapi BIRT dengan database explorer, drag-and-drop query builder, dan fitur canggih lainnya. Kita akan lihat fitur ini dalam screenshot di bawah.
  5. Integrated dengan IDE. Bila kita menggunakan Java, kita bisa coding di Eclipse, dan membuat report di Eclipse juga. Jadi tidak perlu menggunakan beberapa tools yang berbeda.

Baiklah, mari kita coba saja.

Pertama, kita harus donlod dulu dari homepagenya. Ukurannya relatif besar, sekitar 200 MB. Tapi jangan khawatir, ada mirrornya di server Universitas Indonesia. Kalau kita sudah punya Eclipse terbaru, bisa langsung gunakan fitur updatenya. Jalankan downloadnya sebelum pulang kantor. Dengan demikian, besok pagi ketika kita datang, BIRT sudah terinstal.

Setelah terinstal, kita bisa langsung menggunakannya. BIRT terinstal lengkap bersama contoh database. Tutorial cara penggunaannya juga cukup jelas dan lengkap. Sayangnya tidak ada screenshotnya. Jangan khawatir, pada artikel ini, saya akan sediakan screenshotnya.

Berikut adalah tampilan Eclipse pada saat sudah dijalankan.

Eclipse Interface

Selanjutnya, kita langsung membuat project baru. Klik File > New, kemudian pilih Report Project

Create Report Project

Beri nama projectnya. Kemudian klik Next. Eclipse akan menanyakan apakah kita ingin bekerja dalam Report Perspective. Jawab saja Yes.

Report perspective tampil seperti screenshot berikut

Report Perspective

Perhatikan di sebelah kiri ada tiga tab : Pallete, Data Explorer, dan Library. Kita akan gunakan tab ini untuk mendesain report.

Kemudian, mari kita buat report pertama kita. Datasource yang akan digunakan sudah disediakan Eclipse sebagai database sample. Sesuai tutorial Eclipse, kita akan membuat laporan yang berisi daftar nama pelanggan, dikelompokkan berdasarkan provinsi (State) dan kota (City).

Untuk membuat report baru, klik File > New > Report. Kalau pilihan Report belum ada, pilih Others dan cari di daftar yang tersedia, dalam kategori Business Intelligence and Reporting Tools.

Create Report

Beri nama reportnya

Define Report

Kemudian pilih templatenya. Supaya lebih seru, kita akan gunakan Blank Template

Blank Template

Selanjutnya, template report kita tampil di layar dalam Design View. Kita dapat berganti ke berbagai view melalui tab di bawah editor report.

Setelah report tampil, kita dapat menambahkan label. Tambahkan saja satu label untuk judul, yaitu Laporan Data Pelanggan. Jenis huruf, rata tengah, dan setting lainnya dapat dilakukan melalui toolbar yang ada di bagian bawah.

Add Label

Sebelum melangkah lebih jauh, kita perlu mendefinisikan Data Source untuk report ini. Buat Data Source baru melalui panel sebelah kiri.

Create DataSource

Pilihan datasource akan muncul. Kita akan menggunakan database sample yang sudah ada. Untuk project betulan, kita dapat gunakan database atau sumber data yang lainnya.

Select DataSource

Beri nama Sample di kolom Data Source Name, kemudian klik Finish.

Dari datasource yang ada, kita dapat mendefinsikan Data Set. Data Set ini adalah sebagian dari isi Data Source yang akan kita gunakan dalam report.

Create Dataset

Muncul pilihan datasource dan jenis data set. Kita bisa menggunakan lebih dari satu datasource dalam satu report. Untuk kali ini, cuma ada satu data source. Pilih tipe data set SQL Select Query. Jangan lupa beri nama yang deskriptif untuk dataset yang dibuat.

Create Dataset

Setelah kita tekan Next, akan muncul database explorer di panel kiri, dan SQL editor di kanan. Kita dapat melakukan drag and drop pada layar ini.

Database Explorer

Edit SQL menjadi seperti ini:

select * 
from

Kemudian drag-and-drop tabel Customer ke sebelah kanan from, sehingga kodenya menjadi seperti ini:

select * 
from CLASSICMODELS.CUSTOMERS

Klik Next. Selanjutnya muncul Data Set Editor.

DataSet Editor

Kita tidak melakukan perubahan apa-apa di sini. Tapi bila ingin tahu apa isi tabelnya, kita dapat melihat Preview Result seperti ini:

Preview DataSet

Klik OK. Dataset siap digunakan.

Selanjutnya, kita akan tampilkan data pelanggan dalam bentuk tabel. Pilih Table di Pallete, dan letakkan di report. Kita akan tampilkan 4 kolom dan 1 baris detail. Kolom yang nantinya akan ditampilkan adalah:

  1. Provinsi
  2. Kota
  3. Nama Pelanggan
  4. Nomer Telepon

Tampilan yang dihasilkan adalah seperti ini:

Initial Table

Dari seluruh data pelanggan yang ada, kita akan kelompokkan berdasarkan provinsi, kemudian kota. Untuk itu, kita tambahkan Group di tabel. Caranya, klik tombol pemilih tabel, kemudian klik kanan di baris detail.

Insert Group

Group Editor akan muncul. Beri nama State, kemudian klik OK.

Group Editor

Hasilnya akan tampak seperti ini

Group by State

Untuk mengisikan State ke Group Row tersebut, drag-and-drop dari panel kiri ke kolom paling kiri di baris Group Header Row. Layar Select Data Binding akan muncul, langsung saja klik OK.

State Data Binding

Kita perlu memasukkan Group Row satu lagi untuk City. Caranya sama, yaitu dengan menambahkan Group Row di bawah Group Header State.

Insert Group Below

Beri nama City, kemudian klik OK. Lalu pilih field city dari Data Explorer di sebelah kiri, dan pasang di kolom kedua di Group Header Row 2. Hasilnya seperti ini:

Group by City

Terakhir, masukkan field CUSTOMERNAME dan PHONE ke Detail Row. Kolom judul CUSTOMERNAME kurang enak dibaca, jadi kita bisa ganti labelnya di baris paling atas menjadi Customer Name. Hasil akhirnya adalah seperti ini:

Final Design

Report kita sudah selesai. Silahkan disave, kemudian lihat previewnya. Kalau semua dilakukan dengan benar, kita akan melihat tampilan seperti ini:

Report Preview

Kita akan lihat bahwa data pelanggan sudah diurutkan dan dikelompokkan berdasarkan State dan City.

Kalau kita tekan menu File, kita akan menemui pilihan View Report in Web Viewer, as HTML, dan as PDF. Silahkan gunakan sesuai kebutuhan.

Export Format HTML PDF

Selamat mencoba.


Membuat Gantt Chart dengan JFreeChart

JFreeChart adalah library untuk menghasilkan chart dengan Java. Berbagai chart bisa dihasilkan, dari Pie Chart, Bar Chart, dan sebagainya.

Pada artikel ini, kita akan mencoba membuat Gantt Chart. Gantt chart adalah diagram yang menunjukkan rangkaian task, tanggal mulai, selesai, dan persentase kemajuannya. Bagi mereka yang pernah menggunakan aplikasi manajemen proyek pasti tau apa itu Gantt Chart.

Berikut output yang kita inginkan Gantt Chart

Diagram di atas dihasilkan dari sumber data sebagai berikut

Aktivas Tanggal Mulai Tanggal Selesai Persentase Selesai
UML Design 01-01-2006 03-01-2006 100 %
Coding 02-01-2006 03-01-2006 75 %
Testing 03-01-2006 14-01-2006 50 %
Integrate 04-01-2006 25-01-2006 25 %

Untuk mengubah data tersebut menjadi chart, berikut langkah-langkah dan kode yang digunakan.

Pertama, kita harus buat data tersebut menjadi Task object.

Task design = new Task("UML Design", toDate("01-01-2006"), toDate("03-01-2006"));
Task coding = new Task("Coding", toDate("02-01-2006"), toDate("03-01-2006"));
Task test = new Task("Testing", toDate("03-01-2006"), toDate("14-01-2006"));
Task commit = new Task("Integrate", toDate("04-01-2006"), toDate("25-01-2006"));

Untuk memudahkan konversi tanggal, saya buat method seperti ini

private static Date toDate(String date) throws ParseException {
    return formatter.parse(date);
}

kemudian, kita set persentase kemajuan task.

design.setPercentComplete(1);		
coding.setPercentComplete(0.75);
test.setPercentComplete(0.50);
commit.setPercentComplete(0.25);

Task dapat dikelompokkan menjadi TaskSeries.

TaskSeries codingTasks = new TaskSeries("Coding Activities");
codingTasks.add(design);
codingTasks.add(coding);
codingTasks.add(test);
codingTasks.add(commit);

Dan kumpulan TaskSeries disebut TaskCollection

TaskSeriesCollection allTasks = new TaskSeriesCollection();
allTasks.add(codingTasks);

TaskCollection ini digunakan untuk membuat chart.

JFreeChart chart = ChartFactory.createGanttChart("Coba Gantt Chart", "Task", "Tanggal", allTasks, false, false, false);

Terakhir, kita gambar chart menjadi file PNG

ChartUtilities.saveChartAsPNG(new File("output/gantt.png"), chart, 400, 300);

Selain menjadi PNG, kita juga bisa menghasilkan file JPEG

ChartUtilities.saveChartAsJPEG(new File("output/gantt.jpg"), chart, 400, 300);

Demikianlah cara membuat chart dengan JFreeChart. Selain Gantt chart masih banyak lagi fitur JFreeChart yang bagus. Silahkan download dan coba


Membuat Installer dengan IzPack

Menggunakan izPack

Setelah kita selesai membuat aplikasi, what next? Tentunya mendistribusikan pada orang yang membutuhkan. Bagaimana caranya agar aplikasi kita mudah digunakan? Langkah pertama adalah dengan cara memudahkan proses instalasi. Dalam tulisan ini, kita akan mempelajari cara menggunakan izPack, framework untuk membuat installer aplikasi, sehingga menginstal aplikasi akan semudah menekan tombol Next.

Para programmer tentunya sudah familiar dengan berbagai framework installer. Ada yang komersil seperti InstallShield, dan ada juga yang gratis seperti NSIS dan izPack. Kelebihan izPack adalah dia berbasis Java, tidak seperti NSIS yang cuma bisa jalan di Windows.

Langkah pertama, mari kita download izPack. IzPack disediakan sebagai installer, sehingga kita harus menginstalnya dulu sebelum bisa digunakan.

Selanjutnya, mari kita lihat struktur folder project kita yang ingin dibuatkan installernya. Struktur folder saya seperti ini:

Struktur folder project

Setelah terinstal di komputer pengguna, saya ingin foldernya seperti ini:

Hasil yang diinginkan

Perhatikan bahwa folder src tidak perlu diikutkan. Pengguna dapat memilih apakah mau menginstal source code atau tidak. Jadi, folder source code adalah optional. Folder dokumentasi dan plugin tambahan juga biasanya diinstal secara optional.

Berikutnya, tentukan screen yang akan tampil selama proses instalasi, biasanya adalah :

  1. Salam pembukaan, menyatakan kepada pengguna bahwa proses instalasi akan dimulai.
  2. Informasi aplikasi, menjelaskan tentang aplikasi dan kegunaannya.
  3. License Agreement
  4. Pemilihan paket yang akan diinstal. Di sini pengguna dapat memilih apakah dia akan menginstal paket optional atau tidak.
  5. Tujuan instalasi. Pengguna menentukan di folder mana dia akan menginstal.
  6. Proses instalasi. Menunjukkan kemajuan proses instalasi. Biasanya menggunakan progress bar.
  7. Instalasi selesai. Menampilkan pesan sukses atau gagal.

Kerangka dari konfigurasi installer kita adalah sebagai berikut :

    <installation version="1.0">
        <info> </info>
        <guiprefs> </guiprefs>
        <locale> </locale>
        <resources> </resources>
        <panels> </panels>
        <packs> </packs>
    </installation>

Isi dari tag info adalah sebagai berikut

    <info>
        <appname>PlayBilling</appname>
        <appversion>1.1-RC3</appversion>
        <authors>
            <author name="Endy Muhardin" email="endy@artivisi.com"/>
            <author name="Anton Raharja" email="anton@ngoprek.org"/>
        </authors>
        <url>http://playbilling.sourceforge.net</url>
        <javaversion>1.5.0</javaversion>
    </info>

Bagian guiprefs menjelaskan tampilan yang akan digunakan. Kita akan pakai native saja, sesuai OS, supaya tampak alami. Kalau mau, kita dapat memilih beberapa tampilan Look & Feel yang tersedia.

    <guiprefs width="800" height="600" resizable="yes"/>

Berikutnya, pilihan bahasa instalasi. Untuk mudahnya, gunakan bahasa Inggris saja.

    <locale>
        <langpack iso3="eng" />
    </locale>

Untuk bagian resource, kita perlu mendefinisikan file-file yang dibutuhkan installer. File-file ini harus sudah ada.

    <resources>
        <res src="installer/application-description.html" id="HTMLInfoPanel.info"/>
        <res src="installer/gpl.txt" id="LicencePanel.licence"/>
    </resources>

Tentukan urutan screen seperti sudah dijelaskan di atas.

    <panels> 
        <panel classname="HelloPanel"/>
        <panel classname="HTMLInfoPanel"/>
        <panel classname="LicencePanel"/>
        <panel classname="PacksPanel"/>
        <panel classname="TargetPanel"/>
        <panel classname="InstallPanel"/>
        <panel classname="SimpleFinishPanel"/>
    </panels>

Bagian packs menentukan folder-folder yang akan diinstal. Sintaksnya mirip dengan Ant.

    <packs>
        <pack name="Base" required="yes">
            <description>Base System files</description>
            <fileset dir="." targetdir="$INSTALL_PATH">
                <include name="ext/jetty/*"/>
                <include name="webapp/**/*"/>
                <include name="*.sh"/>
                <include name="*.bat"/>
            </fileset>
        </pack>
        
        <pack name="Source" required="no">
            <description>Source code and test files</description>
            <fileset dir="." targetdir="$INSTALL_PATH">
                <include name="src/**/*"/>
                <include name="lib/**/*"/>
                <include name="*.xml"/>
            </fileset>
        </pack>
    </packs>

Variabel $INSTALL_PATH akan diisikan sesuai folder tujuan yang dipilih pengguna.

Ok, file konfigurasi installer kita sudah selesai. Sekarang tinggal diotomasi sehingga bisa dipanggil lewat Ant. Ada beberapa informasi yang dibutuhkan oleh izPack, yaitu:

  • lokasi konfigurasi instalasi (file xml yang baru saja kita buat)
  • nama file installer yang akan dihasilkan (misalnya MyProject-installer.jar)
  • jenis instalasi (desktop atau web)
  • base folder (folder acuan untuk menentukan lokasi relatif folder yang lain)
  • lokasi instalasi izPack

Berikut adalah target untuk Ant

    <taskdef name="izpack" 
             classpath="${izpack_install_dir}/lib/compiler.jar"
             classname="com.izforge.izpack.ant.IzPackTask"
    />
    <target name="build-installer">
        <izpack input="installer/playbilling-installer.xml"
                output="dist/playbilling-installer.jar"
                installerType="standard"
                basedir="."
                izPackDir="${izpack_install_dir}"
        />
    </target>

Setelah Ant target dijalankan, kita akan mendapatkan file playbilling-installer.jar di dalam folder dist. Mari kita coba jalankan file installer tersebut.

java -jar dist/playbilling-installer.jar

Kita akan disodori tampilan selamat datang

Screen Selamat Datang

Klik Next, dan kita akan melihat keterangan tentang PlayBilling. Keterangan ini langsung dicopy-paste dari homepage PlayBilling

Deskripsi Aplikasi

Next lagi, dan muncullah license agreement, yaitu GPL, yang diambil langsung dari website GPL.

GPL License

Screen selanjutnya adalah pilihan paket yang akan diinstal. Perhatikan bahwa paket wajib diburamkan dan tidak bisa diklik.

Pilihan paket instalasi

Setelah itu, kita akan ditanya lokasi instalasi.

Pilihan lokasi instalasi

Pilih lokasi yang sesuai, kemudian Next. Instalasi akan segera dimulai.

Proses Instalasi

Sukses … !

Sukses

Sebagai bonus, izPack juga akan membuatkan Uninstaller. Coba jalankan

java -jar /home/endy/PlayBilling/Uninstaller/uninstaller.jar

Uninstall

Klik OK, dan aplikasi akan dihilangkan dari komputer Anda.

Selamat mencoba. Semoga bermanfaat.


Tapestry vs Spring MVC

Dalam beberapa project terakhir, saya menggunakan Spring MVC untuk membuat presentation layer. Spring sangat fleksibel dan mudah dipelajari. Ini menambah fleksibilitas dalam menyusun tim programmer. Dengan kemudahannya, programmer yang sudah pernah membuat aplikasi web –baik menggunakan Struts, PHP, Ruby on Rails, atau bahkan yang cuma mengerti servlet– dapat beradaptasi dalam hitungan hari dan langsung produktif.

Di lain pihak, saya sering sekali mendengar kehebatan Tapestry. Para pendukungnya menggembar-gemborkan peningkatan produktifitas (baca: kecepatan membuat aplikasi) yang signifikan. Harga yang harus dibayar untuk produktifitas tersebut adalah kompleksitas. Tapestry terkenal sulit. Dia menggunakan paradigma event-driven. Jadi kita harus berpikir seolah-olah kita membangun aplikasi desktop dengan Swing atau VB. Kompleksitas ini menyebabkan kita tidak bisa sembarangan menyusun tim programmer. Butuh orang yang pemahaman Java-nya menengah ke atas agar aplikasi dapat diselesaikan dengan baik.

Setelah merasa nyaman menggunakan Spring di beberapa project terakhir, saya putuskan untuk keluar dari zona aman dan belajar Tapestry. Masa depan aplikasi web nampaknya adalah component-mania. Berbagai komponen siap pakai yang tersedia di pasaran (baik gratis maupun bayar) yang tinggal kita tempelkan di aplikasi kita, akan menjadi trend. Terutama dengan maraknya penggunaan Ajax belakangan ini. Pasti akan banyak orang yang membuat komponen Ajax-ready yang bisa langsung digunakan.

Prediksi ini diperkuat dengan presentasi Chuk Mun Lee di Sun Developer Day 2006 kemarin. Dia menunjukkan bagaimana cepatnya orang bisa membuat aplikasi web. Cukup mendownload kumpulan komponen dari jMaki, dan langsung menggambar di IDE. Kalau para pesaing bekerja seperti ini, sementara kita masih secara manual memparsing request, wah … kita akan ketinggalan.

Sebagai titik awal pelajaran, saya akan mulai dari Spring Framework. Ada beberapa kegiatan utama dalam pembangunan aplikasi web yang terjadi berulang-ulang. Dalam membandingkan Spring vs Tapestry, kegiatan-kegiatan ini akan menjadi kriteria penilaian. Dalam setiap kegiatan, saya akan memberi nilai dan menyatakan pemenangnya. Masing-masing kegiatan bobotnya berbeda, tergantung frekuensi kemunculannya dalam aplikasi.

Berikut adalah kriteria penilaiannya :

  1. Hello World. Yaitu kegiatan setup pertama kali sampai Hello World muncul. Bobotnya cuma 5%, karena kegiatan ini cuma dilakukan sekali saja di awal.
  2. Form binding. Bagaimana semua variabel dalam form bisa diambil sebagai satu domain object. Bobotnya 20%, karena ini adalah kegiatan wajib, inti dari aplikasi.
  3. Validasi form. Bagaimana mencegah invalid input, baik secara server-side maupun client-side. Bobotnya 20%, saudara kembar dengan Form Binding.
  4. Web Asset. Bagaimana penanganan image, css, javascript. Bobotnya 10%.
  5. Security. Bagaimana kemudahan mengaktifkan otentikasi dan otorisasi. Bobotnya 20%. Ini juga bagian yang penting. Kalau penanganan di sisi ini tidak elegan, akan banyak duplikasi kode bertebaran di dalam kode program.
  6. Ajax readiness. Bobotnya 10%.
  7. Reusability. Bagaimana kemudahan menggunakan komponen/library yang sudah ada. Bobotnya 10%.

Disclaimer: dalam kegiatan membandingkan ini, tidak ada tujuan untuk menjelekkan yang satu terhadap yang lainnya. Ini murni adalah pekerjaan harian software designer, yaitu memilih framework dan teknologi. Berbagai saran dan masukan dari pendukung masing-masing framework sangat diharapkan.

Hello World akan dibahas di artikel selanjutnya.