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.

Continuous Integration dengan Hudson

Pada artikel sebelumnya, kita sudah membahas penggunaan Luntbuild dan CruiseControl untuk menerapkan Continuous Integration (CI). Kali ini, kita akan mencoba Hudson, aplikasi CI lain yang tersedia.

Hudson dapat diunduh dari websitenya. Setelah mengunduh, kita akan mendapatkan satu file *war. File ini dapat langsung dijalankan standalone dengan perintah:

java -jar hudson.war

Ataupun dideploy ke servlet engine favorit Anda, seperti Tomcat atau sejenisnya.

Setelah dideploy, kita bisa melihat tampilan awalnya melalui browser ke alamat http://localhost:8080 (untuk standalone) atau http://localhost:8080/hudson (bila dideploy ke servlet engine)

Keunggulan pertama Hudson adalah kemudahan setupnya. Segera setelah dijalankan (baik standalone maupun dideploy), kita bisa segera mengunjungi halaman depannya.

Hudson Welcome Page

Hal pertama yang saya lakukan adalah konfigurasi email. Bila ini tidak dilakukan, Hudson akan gagal mengirim email laporan hasil build.

Klik Manage Hudson di sebelah kiri atas. Layar konfigurasi akan muncul.

Manage Hudson

Selanjutnya, pilih System Configuration, lalu scroll ke bagian bawah untuk mengatur email.

Email Configuration

Setelah selesai, klik OK.

Bila Ant belum ada di PATH komputer Anda, jangan lupa untuk menyebutkan folder instalasi Ant di halaman ini.

Setelah selesai, kita bisa langsung mendaftarkan job. Klik tombol New Job di kiri atas.

Create New Job

Project saya menggunakan Ant biasa, tanpa Maven. Jadi saya pilih free-style. Klik OK.

Selanjutnya, kita konfigurasi repository project. Isikan nilai yang sesuai di bagian Source Code Management.

Configure Subversion

Segera setelah kursor meninggalkan field Repository URL (on blur), Hudson akan memeriksa URL yang kita berikan. Bila URL tersebut membutuhkan otentikasi, Hudson akan mengeluarkan pesan error dengan link untuk mengkonfigurasi username dan password.

Subversion Authentication

Isikan nilai yang sesuai. Seperti kita lihat, Hudson mendukung beberapa modus otentikasi.

Bagian selanjutnya adalah jadwal build atau trigger. Hudson menggunakan format yang mirip dengan Cron.

Build Schedule

Bila kita ingin melakukan build setiap jam, hanya pada hari kerja, entrinya adalah sebagai berikut:

1 * * * 1-5

Agar build berjalan setiap jam 1 dini hari, hari Senin dan Rabu, entrinya sebagai berikut:

0 * 1 * 1,3

Setelah jadwal, kita mengkonfigurasi proses build itu sendiri. Di project saya, build dilakukan oleh Ant. Kita bisa mendaftarkan target yang akan dieksekusi.

Build Method

Terakhir, kita mengkonfigurasi post build. Ini adalah kegiatan yang dilakukan setelah build sukses dijalankan. Pada tahap ini, saya ingin Hudson mempublikasikan *.jar atau *.war yang dihasilkan agar siap didonlod.

Post Build

Selain itu, saya juga bisa menyuruh Hudson untuk memproses hasil unit test JUnit. Hudson mengerti file XML yang dihasilkan JUnit dan TestNG.

Hudson juga bisa disuruh mengirim email apabila terjadi kegagalan build. Di sini biasanya saya isi dengan alamat mailing list developer.

Setelah selesai, klik Save.

Selanjutnya, kita tinggal melihat-lihat hasilnya.

Di halaman depan, kita bisa lihat rangkuman status tiap project.

Build Status

Klik salah satu project, dan lihat detailnya

Build Result

Di situ kita bisa lihat artifact yang sudah dipublish. Dari semua build yang sudah dilakukan, kita bisa lihat trendnya.

Trend of Build Time

Selain itu, kita juga bisa lihat hasil JUnit test.

JUnit Result

Kesimpulan akhir, berikut adalah perbandingan ketiga tools ini.

Tools Setup Tampilan Aksesoris Tag Otomatis

CruiseControl

Sulit, semua harus pakai XML

Kurang bagus, terlihat kuno

Lengkap

Bisa, menggunakan publisher

Luntbuild

Mudah, setup melalui web

Rumit dan kurang intuitif

Sangat sedikit

Bisa, dikonfigurasi melalui web

Hudson

Sangat Mudah

Bagus, intuitif, Web 2.0, AJAX

Eclipse plugin, Netbeans Plugin, Trac Plugin

Tidak bisa, harus manual

Demikianlah, semoga bermanfaat.


Dump Restore PostgreSQL

Pada tahap implementasi, fitur dump-restore database sangat penting. Dengan fitur ini, kita bisa melakukan migrasi data di mesin development, melakukan troubleshoot, data cleansing, dan sebagainya dengan tenang. Begitu sudah selesai, kita dump struktur tabel berikut datanya dari mesin development, kemudian buat database baru di mesin production, lalu restore.

Agar tidak lupa, berikut saya tulis rangkaian langkah-langkahnya. Diasumsikan kita sudah memiliki database development dengan parameter sebagai berikut:

  • Nama Database : buku_tamu
  • Username : belajar
  • Password : java
  • File hasil dump : buku_tamu-schema-20070925-2021.sql dan buku_tamu-data-20070925-2021.sql

Untuk melakukan dump skema tabel, berikut adalah perintahnya:

pg_dump --schema-only --no-owner -h localhost --username belajar buku_tamu | grep -v "^--"  > buku_tamu-schema.sql && sed -i '/^SET/d' buku_tamu-schema.sql && sed -i '/^SELECT/d' buku_tamu-schema.sql && mv buku_tamu-schema.sql buku_tamu-schema-`date +%Y%m%d-%H%M`.sql

Penjelasannya sebagai berikut:

  • --pg_dump : adalah aplikasi command line untuk melakukan import
  • --schema-only : hanya membuat DDL statement, tanpa data
  • --no-owner : tidak perlu mengatur kepemilikan tabel dan view
  • -h : supaya koneksi dilakukan melalui TCP/IP, bukan Unix socket
  • grep -v "^--" : menghilangkan baris-baris comment di file hasil backup
  • sed -i '/^SET/d' : menghilangkan command-command SET yang kita tidak perlukan
  • sed -i '/^SELECT/d' : menghilangkan command-command SELECT yang kita tidak perlukan

Untuk melakukan dump data dalam database, berikut adalah perintahnya:

pg_dump --column-inserts --data-only -h localhost -U belajar buku_tamu | grep -v "^--" > buku_tamu-data.sql  && sed -i '/^SET/d' buku_tamu-data.sql && sed -i '/^SELECT/d' buku_tamu-data.sql && mv buku_tamu-data.sql buku_tamu-data-`date +%Y%m%d-%H%M`.sql

Penjelasannya sebagai berikut:

  • --column-inserts : mencantumkan nama kolom dalam statement insert data
  • --data-only : hanya membuat INSERT statement

Selanjutnya, tiba saat melakukan restore. Parameternya sama dengan database development, kecuali nama databasenya adalah buku_tamu_prod. Bila database belum ada, buat dulu dengan user postgres.

$ sudo su - postgres
$ createdb buku_tamu_prod
CREATE DATABASE
$ exit

Baru setelah itu kita lakukan restore.

psql -h localhost -d buku_tamu_prod -U belajar -f buku_tamu-schema-20070925-2021.sql.sql
psql -h localhost -d buku_tamu_prod -U belajar -f buku_tamu-data-20070925-2021.sql.sql

Penjelasan opsinya adalah sebagai berikut:

  • -h : supaya connect melalui TCP/IP, bukan lewat Unix socket
  • -d : nama database yang akan direstore
  • -U : username yang digunakan untuk koneksi
  • -f : file dump

Bila tidak ada pesan error, struktur tabel dan data seharusnya sudah masuk ke database baru.


Lowongan Experd

Kemarin ada mbak-mbak yang kirim email ke saya, namanya mbak Hanna dari Experd, minta tolong dipostingkan lowongan. Entah kenapa, waktu saya cek websitenya, tulisannya Service Unavailable. Sedangkan www.experd.com bisa diakses. Entahlah, mungkin yang .org sedang bermasalah.

Begini katanya,

Sekedar share informasi lowongan, bahwa saat ini kami ada klien, sebuah konsultan IT yang berpusat di New Jersey, sedang membutuhkan JAVA/J2EE programmer. Nantinya kandidat yang dihired ini akan ditugaskan untuk proyek salah satu top bank di Malaysia. Status pekerjaan yang ditawarkan permanent employee. (selengkapnya di bawah ini).

Berikut detail lowongannya.

  • Has 2-7 years experience in Java/J2EE Development

  • Experience in DB2/Oracle and Unix is an advantage

  • Preferably with Banking Project Experience

  • Can join in 2-6 weeks

  • Willing to work in Kuala Lumpur, Malaysia

Mbak Hanna juga memberikan alamat kantornya, yaitu di:

Plaza 3 Pondok Indah Blok C2, Jl. T.B. Simatupang, Jakarta 12310

Telp. 62-21-75906448, Fax. 62-21-75906442

Email. hanna [at] experd [dot] org, http://www.experd.com

Jangan kirim lamaran ke saya, menurut mbak Hanna, kirimkan ke databank [at] experd [dot] org.

Disclaimer: Saya tidak kenal sama mbak Hanna. Artikel ini juga bukan anjuran kepada pembaca untuk mengirim lamaran

Saya juga sudah membaca bukunya Kevin Mitnick yang berjudul The Art of Deception, yang berisi tentang Social Engineering. Jadi, saran saya bagi pembaca yang berminat, luangkan waktu beberapa menit untuk melakukan cross-check ke alamat dan nomer telepon yang ada di atas untuk memastikan kesahihan info lowongan ini sebelum mengirim resume Anda.

Sekedar smoke-test, saya sudah lookup ke layanan whois, dan hasilnya experd.com dan experd.org diregistrasi oleh orang yang sama, dan alamatnya sama dengan alamat kantornya di atas.

Untuk mbak Hanna, mohon maaf ya … bukannya tidak percaya. Tapi baca sendiri deh The Art of Deception, nanti Anda akan mengerti kenapa saya terkesan paranoid. Anyway … terima kasih atas info lowongannya. Mudah-mudahan mendapatkan kandidat yang sesuai.

Kalau ada orang Experd yang membaca artikel ini, mohon konfirmasi atau sanggahannya.


Menggunakan PostgreSQL

Saya baru saja memporting project yang sedang saya kerjakan, dari menggunakan ikan lumba-lumba menjadi gajah. Sebetulnya saya pernah menggunakan database gajah ini pada tahun 2005, tapi setelah itu jarang digunakan sehingga butuh waktu agak lama untuk melakukan porting ini.

Agar lain kali tidak lupa lagi, baiklah saya tulis di sini saja. Mudah-mudahan bermanfaat juga untuk pembaca :D

Instalasi

Saya menggunakan Ubuntu, jadi instalasi tidak sulit. Cukup lakukan: sudo apt-get install postgresql Beres .. :D

Konfigurasi Akses Jaringan

Selanjutnya, konfigurasi Postgre agar meminta password setiap ada koneksi masuk, termasuk dari localhost. Ini dilakukan agar konfigurasi JDBCnya tidak terlalu berbeda dengan konfigurasi sebelumnya yang menggunakan MySQL.

Ganti otentikasi dalam pg_hba.conf menjadi

local   all         postgres                      peer
local   all         all                           password
host    all         all         127.0.0.1/32      password
host    all         all         ::1/128           password

Konfigurasi di atas artinya, koneksi ke semua database, dari local maupun remote, mintalah password. File pg_hba.conf ini lokasinya tergantung distro yang digunakan. Di tempat saya, ada di folder /etc/postgresql/9.3/main. Jangan lupa merestart PostgreSQL setelah memodifikasi file ini.

sudo /etc/init.d/postgresql restart

Menambahkan User

Untuk menambahkan user, kita perlu menyamar sebagai user postgres. Gunakan su. sudo su - postgres

Selanjutnya, jalankan perintah createuser dengan argumen --interactive agar diberikan form isian dan argumen -P agar kita bisa mengisi password.

createuser --interactive -P
Enter name of role to add: belajar
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n 

Perintah di atas menambahkan user dengan username belajar yang memiliki ijin untuk membuat database baru.

Selanjutnya, keluar dari user postgres dengan menggunakan perintah exit.

Membuat Database

Agar bisa menyimpan data, kita harus punya database. Mari kita buat database yang namanya buku_tamu. Gunakan perintah createdb dengan argumen U untuk menyebutkan username.

createdb -U belajar buku_tamu
Password: 
CREATE DATABASE

Setelah selesai, coba koneksi ke database tersebut.

psql -U belajar -d buku_tamu

Konfigurasi JDBC

Kalau sudah OK, berikut adalah konfigurasi JDBC untuk mengakses database tersebut.

jdbc.driver      = org.postgresql.Driver
jdbc.url         = jdbc:postgresql://localhost/buku_tamu
jdbc.username    = belajar
jdbc.password    = java

Saya menggunakan Hibernate, sehingga butuh satu parameter lagi, yaitu dialek SQL yang digunakan.

hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Dengan menggunakan Hibernate, maka porting database hanyalah perkara mengganti lima baris konfigurasi (bukan source code), dari seperti ini:

jdbc.driver      = com.mysql.jdbc.Driver
jdbc.url         = jdbc:mysql://localhost/buku_tamu
jdbc.username    = belajar
jdbc.password    = java
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

Menjadi seperti ini:

jdbc.driver      = org.postgresql.Driver
jdbc.url         = jdbc:postgresql://localhost/buku_tamu
jdbc.username    = belajar
jdbc.password    = java
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Demikian setup PostgreSQL agar bisa diakses dari Java.


Membuat validasi dalam aplikasi

Pertanyaan berikut muncul di milis netbeans-indonesia, “Di mana sebaiknya kita menulis aturan validasi? Di database, di business layer, atau di presentation layer?”

Saya pikir, pasti banyak juga yang memiliki kebimbangan serupa. Oleh karena itu, jawaban saya tulis di artikel ini.

Menurut saya, validasi itu idealnya di semua layer, mulai dari database, business logic, dan presentation layer (UI).

Kenapa di database harus ada validasi (dengan menggunakan database constraint) adalah karena data umurnya akan lebih panjang dari aplikasi. Front end bisa ditulis ulang dengan apapun teknologi/framework yang sedang populer, sedangkan data sekali sudah disimpan, biasanya akan terus ada dalam waktu yang lama.

Kalau kita tidak pakai constraint di database, begitu aplikasi kita usang dan diganti (misal tadinya desktop jadi web) maka databasenya jadi ‘telanjang’ tanpa validasi, sehingga rawan kemasukan data kotor. Dan siapa yang bisa memastikan database kita tidak diakses aplikasi lain? Mungkin sekarang tidak … tapi tahun depan ketika ada kebutuhan baru, bisa saja ada orang lain yang mengembangkan aplikasi di atas database kita tersebut.

Di sisi lain, validasi di presentation layer juga penting, supaya round-trip nya tidak terlalu panjang. Katakanlah kita punya layer seperti ini: presentation –> business –> data access

Kalau cuma ada validasi database, maka kita perlu meng-catch SQLException untuk kemudian diteruskan ke depan, entah itu as-is SQLException ataupun dienkapsulasi menjadi DataAccessException dan kemudian dibungkus lagi menjadi BusinessLayerException. Apalagi kalau aplikasinya ada di mesin berbeda. Ongkos perjalanan Exceptionnya jadi mahal. Itu makanya penting validasi di presentation layer.

So … idealnya validasi ada di semua layer.

Tapi ini tidak berarti saya menganjurkan untuk menulis kode validasi di semua layer lho. Kode program itu idealnya tidak boleh terduplikasi. Logika validasi hanya ditulis sekali. Kalau aturan yang sama ditulis berkali-kali nanti pasti akan datang masanya kita (atau orang lain yang mewarisi kode program kita) mengganti aturan di satu tempat, dan lupa mengganti di tempat lain. Jadi, untuk setiap aturan, harus satu kali saja menulisnya.

Banyak cara agar codingnya cukup satu kali saja, misalnya mendefinisikan constraint dengan Hibernate, dan biarkan dia yang menggenerate DDL. Biasanya constraint unique, required, dan semacamnya akan langsung dibuatkan database constraintnya.

Kemudian di presentation layer, buat aturan validasi yang dinamis, yang bisa membaca hibernate annotation dan kemudian menggenerate rutin validasi baik itu JavaScript (kalau aplikasinya web), atau pemanggilan method Java (kalau itu Swing).

Demikian pendapat saya tentang validasi. Bagaimana menurut Anda?