Tuesday, February 21, 2006

Pengalaman pertama menggunakan web testing framework

Beberapa hari ini saya sibuk dengan testing web application. Functional testing tidak rumit karena kebanyakan adalah operasi CRUD (Create Read Update Detele).

Untuk mempermudah testing saya mencoba menggunakan aplikasi/framework yaitu MaxQ dan Solex.

Dibawah ini beberapa fitur yang penting pada kedua aplikasi tersebut.

  • Instalasi yang mudah. [Keduanya]
  • Proxy based recording. [Keduanya]
  • Recording dapat dimatikan dan proxy tetap hidup (runs). [MaxQ]
  • Menggunakan dokumen teks sebagai test case untuk mempermudah perubahan. [Keduanya, Solex menggunakan format dokumen XML]
  • Menggunakan script sebagai test case untuk memudahkan penambahan fungsi otomatisasi misalnya looping, operasi aritmatika, dll. [MaxQ]
  • Script yang mudah/familiar. [Tidak keduanya, mengapa MaxQ menggunakan Python?]
  • Test case dapat disimpan. [Keduanya]
  • Editor yang baik untuk mengubah script. [Solex]
  • Integrasi dengan IDE. [Solex]
  • Maturity (Stabil). [Solex]
  • Hasil HTTP request & response dapat dilihat. [Solex]
  • Fungsi XQuery/Xpath/Regular Expression untuk pencarian string pada response. [Solex]
Saya kira Solex sangat bagus, tapi saya kesulitan mengulang-ulang test case berkali-kali (misalnya pada saat stress test atau input data banyak). Hal ini karena saya harus mengklik tombol untuk menjalankan test case dan tidak bisa menambahakan operasi looping pada test case.

Bagaimana dengan Selenium atau Sahi yang merupakan web testing tool yang terintegrasi pada browser?

Thursday, February 16, 2006

Modeling Maturity Levels: Dilevel mana saat ini disain software anda terdokumentasi?

Dalam buku MDA Explained, Anneke Kleppe dan Jos Warmer, memperkenalkan beberapa level pemodelan software yang mereka sebut Modeling Maturity Levels (MML).

MML ini memiliki enam level pemodelan. Tiap level disa dibilang menunjukan maturity dari tipe-tipe model yang ada. Suatu model dalam hal ini merupakan spesifikasi dari software yang (akan) dibuat dapat berupa dokumentasi abstrak (masih dalam pikiran) ataupun dalam bentuk tulisan ataupun dambar/diagram.

Level-level tersebut yaitu:

  1. MML 0: No Specification
    Tanpa spesifikasi (tidak didokumentasikan)
  2. MML 1: Textual Specification
    Dispesifikasikan dengan bahasa natural (bahasa Indonesia misalnya)
  3. MML 2: Text with Models
    Spesifikasi tekstual dengan ditambah model (diagram) secara garis besar (tidak detail)
  4. MML 3: Models with Text
    Spesifikasi software dengan banyak model yang lebih berperan dengan penambahan deskripsi untuk model tersebut
  5. MML 4: Precise Models
    Spesifikasi dijelaskan dengan model dan bahasa natural. Dengan model lebih dekat dengan source code, perubahan model dapat menyentuh langsung ke perubahan source code. MDA (Model Driven Architecture) mengarah pada level pemodelan ini.
  6. MML 5: Models Only
    Model sangat komplit sehingga bisa membuat source code yang lengkap. Saat ini tidak ada pemodelan yang berdara pada level ini.
Detailnya bisa dibaca di sini

Dokumentasi kode sumber (source code)

Suatu aplikasi atau program harus memiliki dokumentasi yang baik. Membuat dokumentasi tidaklah mudah, apalagi dokumentasi pada API yang mungkin akan digunakan oleh orang lain.

Kita tidak hanya dituntut untuk mengerti bagaimana menuliskan suatu komentar didalam source code, tapi lebih dari itu kita perlu mengerti bagaimana cara mendesripsikan suatu package, class, atau method. Mendeskirpsikan yang baik berarti memberi penjelasan kepada pembaca sehingga pembaca mudah mengerti. Mendeskripsikan suatu bagian dari source code berarti memberikan penjelasan tentang karakteristik dasi suatu bagian source code tersebut. Karakteristik suatu bagian source code dapat berarti menjelaskan:
  • Tujuan atau fungsi
  • Algoritma spesifik yang digunakan
  • Dependencies (Ketergantungan terhadap hal lain misalnya sistem operasi, library, dll)
  • Karakteristik input atau output
  • Informasi exception, security, deployment
  • Penjelasan implementasi (misalnya pada dokumentasi Interface)
  • Referensi ke dokumen lain
Dokumen Requirements for Writing Java API Specifications dianjurkan untuk dibaca karena memberikan penjelasan yang baik dan memberikan contoh-contoh dalam menuliskan dokumentasi.

Dalam perograman Java tentu kita dituntut untuk mengetahui bagaimana menggunakan tool javadoc, dan menuliskan dokumentasi pada source code yang 'javadoc friendly'. Untuk itu kita perlu baca How to Write Doc Comments for the Javadoc Tool

Saturday, February 11, 2006

Pentingnya template

Aku baru saja melihat seorang teman memiliki beberapa template file bahkan file-file (jamak) dalam suatu direktori. Direktori tersebut juga sebuah template, template dari suatu proyek. Jadi terbersit hati ingin menulis betapa pentingnya template. Kadang kita secara sadar membuat template tapi kadang kita lupa hal-hal yang hampir selalu terjadi dikemudian hari tidak terpikir untuk dibuatkan template-nya.

Template bisa berupa file (dokumen, source code), folder/directory, database schema, script yang harus dijalankan dll.

Beberapa tips untuk membut tempalate:
  • Sebaiknya perbaiki terus template yang kita punya.
  • Seperti juga source code, ada baiknya membuat versi-versi dari template.
  • Buatlah isi template selengkap mungkin sehingga pada saat diperlukan, bagian yang tidak diperlukan dapat dengan mudah dihilangkan.
  • Berilah deskrispsi dari masing-masing bagian yang perlu diisi pada tempalte.
  • Kalo perlu beri contoh isi pada bagian-bagian yang harus diisi/di-customize.

Ganti java.util.Properties dengan Preferences API

Tujuan utama dibuatnya Preferences API:

Kebutuhan untuk mengatur (menyimpan, mengambilnya kembali dan memodifikasi) preference pengguna (user) dan data konfigurasi dari suatu aplikasi. Data seperti itu biasanya memiliki sifat:
  • Data yang kecil (Spesifikasi API menyaratkan maximum 8192 bytes per value)
  • Data yang jarang diakses
  • Bukan data penting (critical)
  • Data yang penting untuk fungsi dari suatu aplikasi
Untuk memenuhi kebutuhan tersebut biasanya programmer menggunakan file properties (file text) yang diakses lewat API java.util.Properties. Dengan adanya API ini, java.util.Properties menjadi tergantikan.

Tipe data yang dapat disimpan menggunakan Preferences API adalah:
  • String
  • boolean
  • double
  • float
  • int
  • long
  • byte array
API ini terdiri dari:

  • 3 Interfaces
    • NodeChangeListener
    • PreferenceChangeListener
    • PreferencesFactory
  • 4 Classes
    • AbstractPreferences
    • NodeChangeEvent
    • PreferenceChangeEvent
    • Preferences
  • 2 Exceptions
    • BackingStoreException
    • InvalidPreferencesFormatException
- API ini ada mulai pada Java versi 1.4 pada package java.util.prefs
- API yang didesain sederhana
- Spesifikasi tidak mendefinisikan di tempat mana data akan disimpan (backing store)
- Memiliki dua kategori preference yaitu User dan System
- Data merupakan pasangan key-value
- Struktur pohon (tree): Tiap node dapat menyimpan data dan atau node lain
- Support callback pada saat ada perubahan pada node (penambahan/penghapusan) atau pada data
- Tidak support transaksi pada saat mengubah data (update bersifat atomic)


- Class terpenting yang sering digunakan adalah class Preferences (Sempatkan untuk membaca dokumentasinya)
- Untuk menyimpan data digunakan method putXXX(key, value) pada class Preferences
- Untuk menggambil data digunakan method getXXX(key, default-value) pada class Preferences
- Jika backing store tidak ada, mengakses data atau mengimport preferences akan menghasilkan BackingStoreException
- Gunakan Preferences.systemNodeForPackage(Class) untuk menyimpan data per-system
- Gunakan Preferences.userNodeForPackage(Class) untuk menyimpan data per-user
- Dibalik layar, class Preferences yang merupakan impleentasi dari AbstractPreferences akan dihasilkan dari class PreferencesFactory
- Class Preferences bertanggung jawab terhadap penyimpanan data
- Pada Windows biasanya default Preference akan menggunakan java.util.prefs.WindowsPreferences yang menggunakan native mothod untuk menyimpan data pada registry
- Pada sistem operasi UNIX-like digunakan java.util.prefs.FileSystemProperties yang menyimpan data pada file
- JVM akan menggunakan PreferencesFactory sesuai dengan property java.util.prefs.PreferenceFactory yang ada pada JVM
- PreferencesFactory dapat diubah dengan cara
  • Memberikan command line argument pada saat menjalankan JVM, contoh

    java -Djava.util.prefs.PreferencesFactory=com.ejlp.perf.TestPreferencesFactory
  • Menambahakan kode sebelum Preferences digunakan:

    System.setProperty("java.util.prefs.PreferencesFactory", "DisabledPreferencesFactory");

- Support export-import ke format XML dengan menggunakan method exportNode() atau exportSubtree() dan importPreferences()


- Media penyimpanan:

Pada sistem operasi windows biasaya preferences data disimpan pada Windows Registry yaitu pada:

HKEY_CURRENT_USER\Software\JavaSoft\Prefs (untuk system preferences)
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs (untuk user preferences)

Pada sistem operasi lain dapat berada pada file di direktori home user atau ditempat lain.



Contoh penggunaan:

package net.ejlp.test.prefs;
import java.io.IOException;
import java.util.prefs.*;

public class TestPreferences {
// Preference key
private static final String FONT = "font";

// Membuat Preferences instance menggunakan User Preferences
private static Preferences prefs =
Preferences.userNodeForPackage(TestPreferences.class);

public static void main(String[] args) {
TestPreferences.ambil();

// Simpan data pada Preferences
prefs.put(FONT, "Courier New");

TestPreferences.ambil();

// Tambahkan listerner untuk mengangani perubahan yang terjadi
prefs.addPreferenceChangeListener(new PreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent evt) {
System.out.println(
"Perubahan preference terdeteksi pada key = " + evt.getKey() +
", new value = " + evt.getNewValue());
}
});

// Ubah value pada key font sekali lagi
prefs.put(FONT, "Courier");

// Export ke format XML dan tampilkan di layar
try {
prefs.exportNode(System.out);
} catch (IOException e) {
} catch (BackingStoreException e) {
}

}

public static void ambil() {
String font = prefs.get(FONT, "Arial");
System.out.println("Data: Key = " + FONT + ", value = " + font);
}
}


- Bahan bacaan:
JSR-10
Dokumentasi Java API > 1.4
How to Completely Disable Sun Java's 1.4.x Preferences Subsystem

Thursday, February 09, 2006

Menggunakan Shutdown Hook: Bersihkan dosa sebelum mati :)

Pada saat aplikasi mati, baik itu diinginkan ataupun tidak (misalnya karena ada error), kadang perlu dilakukan proses akhir sehingga tidak menimbulkan sesuatu hal yang tidak diingankan, misalnya hilangnya data, tidak ter-commit-nya suatu transaction dan lain-lain. Beberapa contoh proses pada saat aplikasi mati diantaranya:
  • Mematikan koneksi jaringan
  • Menyimpan session state
  • Menghapus file sementara (temporary)
  • Menutup file handle

Untuk melakukan proses akhir tersebut kita bisa menggunakan solusi dengan cara:
  • Buat suatu fungsi yang akan dipanggil disetiap baris yang membuat aplikasi mati atau disetiap baris sebelum memanggil System.exit()

Tapi solusi tersebut tentu saja tidak efektif karena kita harus menuliskan kode pemanggil fungsi tersebut disetiap bagian dimana memungkinkan aplikasi mati.

Solusi yang baik adalah menggunakan shutdown hook yang ada pada standar Java API.

Shutdown hook:
  • Meknisme shutdown hook sudah ada sejak Java 1.3.
  • Sebelumnya kita dapat menggunakan Runtime.runFinalizersOnExit(), yang sekarang ini sudah deprecated.
  • Dengan shutdown hook pemberhentian suatu aplikasi dengan sengaja (voluntary) tau tidak sengaja dapat ditangani dengan baik.
  • Sebuah shutdown hook adalah sebuah class Thread dengan method run() yang kita isi dengan kode yang akan dipanggil sebelum JVM mati.
  • Kita dapat meregistrasi beberapa shoutdown hook dalam suatu aplikasi.
  • 3 Method pada class java.lang.Runtime yang berhubungan dengan mekanisme 'exit' suatu aplikasi yang perlu dipelajari (baca dokumentasi Java API)
    • addShutdownHook
    • removeShutdownHook
    • halt
  • Tips:
    • Gunakan kode yang thread-safe pada shutdown hook
    • Buat kode yang sederhana dan cepat dieksekusi sehingga mempercepat waktu shutdown
  • Contoh dibawah ini memperlihatkan penggunaan shutdown hook:
package com.ejlp.test.shutdownhook;

import java.io.*;

public class TestShutdownHook {
private BufferedWriter bw_log;

public TestShutdownHook() throws IOException {
// Buat file log.txt
bw_log = new BufferedWriter(new FileWriter("log.txt"));

// Register sebuah shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
// Tutup log file
bw_log.close();
}
catch (IOException e) {
System.err.println(e);
}
}
});;
}

// Tulis sesuatu ke file log.txt
public void processApp1() throws IOException {
bw_log.write("Jika tidak ada shutdown hook yang menutup bw_log, tulisan ini tidak adakan ada di log.txt");
bw_log.newLine();
}

public static void main(String args[]) {
try {
TestShutdownHook demo = new TestShutdownHook();
demo.processApp1();
} catch (IOException e) {
e.printStackTrace();
}

// Simulasikan program error
throw new RuntimeException();
}
}

Thursday, February 02, 2006

Hati-hati mengadopsi aplikasi baru (tool) untuk software development

Kita yang bergelut di dunia IT selalu tidak mau ketinggalan dengan teknologi baru. Enhancment di dunia IT bisa terjadi setiap waktu, setiap detik. Aplikasi-aplikasi baru pun bermunculan sehingga semakin banyak alternatif. Ditabah dengan maraknya/banyaknya tools yang GRATIS, kita semakin mudah mendapatkannya.

Munculnya tools baru membuat kita tergoda untuk menggunakannya. Tapi kadang penggunakan tools atau aplikasi baru hasilnya tidak membuat kita lebih efektif bekerja. Bisa jadi penggunaan tools baru tersebut hanya menghambat pekerjaan kita, sedangkan benefitnya tidak kita dapatkan.

Contoh ini terjadi: Saya dan tim bisa menggunakan CVS sebagai aplikasi SCM atau versioning system. Dengan adanya Subversion (SVN) yang katanya memperbaiki kekurangan-kekurangan yang terdapt di CVS, kita menjadi tertarik untuk menggunakannya pada saat development. Karena tim terbiasa menggunakan CVS lewat GUI yang ada pada IDE, saat tim menggunakan SVN yang tidak disupport oleh IDE maka yang terjadi adalah tim kesulitan untuk melakukan sinkronisasi dengan repositori. Semua bisa dilakukan dan diatasi tetapi produktifitas berkurang. Waktu untuk update, commit, dan sinkronisasi pada repositori menjadi lebih lama sedangkan kemampuan baru dari SVN yang lebih baik dari CVS tidak digunakan atau bahkan memang tidak diperlukan.

Oleh karena itu penggunakan aplikasi/tools perlu pertimbangan yang matang. Perimbangan hal-hal sperti:

- Kemudahan pemakaian (baik jika ada plugin yang terintegrasi dengan IDE yang digunakan)
- Maturity dari aplikasi
- Waktu/lamanya mempelajari aplikasi baru
- Kebutuhan (requirement) development
- Jangan gunakan aplikasi baru (untuk coba-coba) pada running project

Wednesday, February 01, 2006

JCA (J2EE Connector Architecture)

JCA (J2EE Connector Architecture)

JCA merupakan solusi untuk EAI (enterprise application integration).
JCA adalah standar/spesifikasi untuk koneksi antara aplikasi J2EE dengan enterprise information systems (EIS).
EIS dapat berupa mainframe transaction processing (TP), database systems, dan legacy applications (misalnya ERP, CMS) yang dibuat mungkin-tidak menggunakan Java.

Versi JCA:
  • Versi awal adalah versi 1, memiliki kelemahan:
    • Tidak support komunikasi asinkron (asynchronous)
    • Tidak support (built-in) pertukaran data XML
    Tidak suport komunikasi dari EIS ke aplikasi (inbound)
  • Versi 1.5

Komponen dari JCA:

* Resource adapter (disingkat disini sebagai RA)
  • Resource adapter ini mirip dengan JDBC, spesifik untuk suatu EIS (misalnya SAP atau PeopleSoft).
  • Berupa sebuah file disebut Resource Adapter Archive (RAR) file yeng berisi file-file jar dan native library yang diperlukan oleh J2EE container.
  • File resource adapter dengan ekstensi .rar memiliki deployment descriptor bernama ra.xml. File rar ini kemudian di-deploy ke sebuah application server sehingga bisa digunakan oleh aplikasi Web, EJB atau aplikasi lain yang terkoneksi ke application server
  • RA adapter biasanya bisa kita dapatkan dari vendor pembuat EIS.
  • RA dapat memiliki beberapa macam cara komunikasi antar EIS dan aplikasi:
    1. Outbound communication: Hanya support koneksi dari aplikasi ke EIS dan mengkeskusi pekerjaan EIS.
    2. Inbound communication: Hanya support koneksi dari EIS ke aplikasi dan mengkeskusi pekerjaan di aplikasi.
    3. Bi-directional communication: SUpport kedua jenis koneksi diatas.
* Kontrak (contracts)
  • Adalah pendefinisian cara suatu J2EE server dengan JCA adapter untuk saling berinteraksi/berkolaborasi.
  • Ada 7 macam (hanya 3 macam pada JCA versi 1) system contrancts yaitu:
    1. Manajemen koneksi (Connection management), memberikan kemampuan AS untuk mem-pool koneksi ke EIS
    2. Manajemen transaksi (Transaction management), memberikan kemampuan akses transaksional ke EIS
    3. Keamanan (Security), memberikan kemampuan akses yang aman ke EIS
    4. Manajemen siklus hidup (LIfecycle management), memberikan kemampuan AS untuk memajemen siklus hidup suatu RA
    5. Manajemen kerja (Work Management), EIS dapat mengirimkan suatu pekerjaan (Work) yang dieksekusi AS
    6. Inflow transaction (Transaction Inflow), RA dapat mengirimkan transaksi dari EIS ke AS
    7. Inflow pesan (Message Inflow), kolaborasi pengiriman pesan asinkron

* Common Client Interface (CCI)
  • Standar API yang "common" untuk mengakses EIS oleh aplikasi klien.
  • Package javax.resource.cci / javax.resource.spi
  • API (connector-api.jar) dapat di download di http://java.sun.com/j2ee/connector/download.html

  • Bagian dari CCI API yaitu:
    • Yang berhubungan dengan koneksi ke EIS (Connection Interfaces)
    • Eksekusi perintah pada EIS (Interaction Interfaces)
    • Enkapsulasi hasil query dari EIS (Record/ResultSet Interfaces)
    • Metadata pada EIS yang dapat di-query (Metadata Interfaces)
    • Service Endpoint Message Listener Interface
    • Exception Interface
Contoh kode penggunaan CCI (kode ini mirip query ke database menggunakan JDBC):
       int count;
try {
// Buat koneksi
ConnectionSpec spec = new CciConnectionSpec(user, password);
Connection con = cf.getConnection(spec);

// Buat interaksi, seperti membuat statement pada JDBC
Interaction ix = con.createInteraction();
CciInteractionSpec iSpec = new CciInteractionSpec();
iSpec.setSchema(user);
iSpec.setFunctionName("EMPLOYEECOUNT");
RecordFactory rf = cf.getRecordFactory();
IndexedRecord iRec = rf.createIndexedRecord("InputRecord");

// Eksekusi
Record rec = ix.execute(iSpec, iRec);

// Proses hasil eksekusi
Iterator iter = ((IndexedRecord)rec).iterator();
while(iter.hasNext()) {
Object obj = iter.next();
if(obj instanceof Integer) {
count = ((Integer)obj).intValue();
}
}

// Tutup koneksi
con.close();
}
catch(Exception e) {
e.printStackTrace();
}
System.out.println("Employee count is: " + count);

Referensi:
- J2EE Connector Architecture Overview
- J2EE Connector Architecture Specification
- Introduction to the J2EE Connector Architecture

Followers