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.

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?


Menggunakan HermesJMS

Kalau kita ingin membuat aplikasi menggunakan database, tentunya hal pertama yang kita lakukan adalah menginstal server database. Selanjutnya, langkah kedua adalah menginstal aplikasi untuk mengelola database. Paling tidak, kita harus bisa membuat tabel, melihat isi tabel, mengisi ataupun menghapus data ke dalam tabel.

Demikian juga kalau kita membangun aplikasi menggunakan JMS (Java Messaging Service). Sebelum membuat Hello JMS, terlebih dulu kita harus menginstal JMS server dan aplikasi yang dapat melihat isi JMS Server tersebut.

Pada artikel kali ini, kita akan menginstal JMS Server ActiveMQ dan aplikasi pengelolaan JMS yang bernama HermesJMS.

ActiveMQ dan HermesJMS dapat diunduh di websitenya masing-masing.

Setelah diunduh, terlebih dulu kita instal ActiveMQ. Caranya sangat gampang, cukup diekstrak saja. Saya meletakkannya di folder /opt

<code>cd /opt
sudo tar xvzf apache-activemq-4.1.1.tar.gz
</code>

Setelah diekstrak, kita bisa langsung jalankan dari folder instalasinya.

<code>cd /opt/apache-activemq-4.1.1
bin/activemq</code>

Kalau sukses, akan muncul log message seperti ini:

<code>INFO  TransportServerThreadSupport   - Listening for connections at: tcp://sweetdreams:61616
INFO  TransportConnector             - Connector openwire Started
INFO  TransportServerThreadSupport   - Listening for connections at: ssl://sweetdreams:61617
INFO  TransportConnector             - Connector ssl Started
INFO  TransportServerThreadSupport   - Listening for connections at: stomp://sweetdreams:61613
INFO  TransportConnector             - Connector stomp Started
INFO  NetworkConnector               - Network Connector default-nc Started
INFO  BrokerService                  - ActiveMQ JMS Message Broker (localhost, ID:sweetdreams-32991-1188983887811-1:0) started
</code>

Server kita sudah siap diakses di port 61616.

Sekarang kita akan menginstal HermesJMS. Inipun instalasinya tidak sulit, cukup jalankan saja installernya.

<code>java -jar hermes-installer-1.12.jar</code>

Nantinya akan muncul layar instalasi. Klik saja Next … Next … seperti biasa sampai selesai.

Setelah Hermes berhasil diinstal, jalankan Hermes. Berikut adalah tampilan awalnya. Hello Hermes

Selanjutnya, kita akan menambahkan koneksi ke server ActiveMQ kita. Buka menu Options - Preferences, kemudian pilih tab Classpath di sisi bawah panel. Belum ada classpath group

Selanjutnya, klik kanan di panel kosong tersebut dan masukkan classpath group baru bernama ActiveMQ. Tambah Classpath Group

Nanti akan muncul entri ActiveMQ dengan tab dibawahnya yang bertulisan Library. Klik kanan tepat pada tulisan Library dan pilih Add Jar. Kita harus menambahkan beberapa jar berikut:

  • apache-activemq-4.1.1.jar

  • backport-util-concurrent-2.1.jar

  • geronimo-j2ee-management_1.0_spec-1.0.jar

Semua file tersebut dapat ditemukan di lokasi instalasi ActiveMQ.

Setelah konfigurasi dilakukan, layar tampilannya akan tampak seperti ini: Classpath ActiveMQ

Tutup layar Preference, dan buka lagi. Entah kenapa kalau tidak ditutup dulu, pilihan ActiveMQ tidak akan keluar.

Di layar Preference tab Session, ketikkan nama Session yang baru, yaitu ActiveMQ. Klik Apply, nantinya Hermes akan menanyakan apakah ini session baru atau bukan. Jawab saja, “Ya, ini adalah session baru”.

Selanjutnya, ganti pilihan Loader menjadi ActiveMQ, dan pilih ActiveMQ Connection Factory pada pilihan Class. Hasilnya akan nampak seperti ini: Session Baru ActiveMQ

Setelah selesai, session ActiveMQ akan muncul di panel sebelah kiri. Konfigurasi Session ActiveMQ

Kita bisa membuat queue baru di session tersebut. Gunakan tombol Create New Queue. Membuat Queue

Pembuatan queue pada layar ini bersifat sementara. Artinya, bila HermesJMS dimatikan, Queuenya akan hilang. Untuk membuat Queue yang permanen, kita dapat mendefinisikannya pada layar konfigurasi session.

Queue yang sudah dibuat dapat dilihat di panel sebelah kiri. Queue Browser

Pada queue yang sudah terbentuk, kita bisa mengirim Text Message. Gunakan menu Messages - Send TextMessages. Kita harus memilih satu text file untuk dikirim.

Setelah pengiriman selesai dilakukan, refresh tampilan sehingga message baru tersebut muncul. Browse Message

Kita dapat mengambil message tersebut dengan menggunakan kode program Java sebagai berikut.

<code>package tutorial.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class HelloQueueReceiver {
	public static void main(String[] args) throws Exception {
		ConnectionFactory factory = new ActiveMQConnectionFactory(
				ActiveMQConnection.DEFAULT_USER,
				ActiveMQConnection.DEFAULT_PASSWORD,
				ActiveMQConnection.DEFAULT_BROKER_URL);
		System.out.println("Connecting to: "+ActiveMQConnection.DEFAULT_BROKER_URL);
		System.out.println("With username : "+ActiveMQConnection.DEFAULT_USER);
		System.out.println("and password : "+ActiveMQConnection.DEFAULT_PASSWORD);
		
		Connection conn = factory.createConnection();
		System.out.println("Connected");
		
		Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
		System.out.println("Session created");
		
		Queue destination = sess.createQueue("coba");
		System.out.println("Queue created");
		
		MessageConsumer consumer = sess.createConsumer(destination);
		System.out.println("Consumer created");
		
		System.out.println("Fetching message");
		conn.start();
		int counter = 1;
		while(true) {			
			Message msg = consumer.receive(1000);
			if (msg == null) break;
			System.out.println("Retrieving message #"+counter++);
			System.out.println("Message fetched");
			if (msg instanceof TextMessage) {
				TextMessage txtmsg = (TextMessage) msg;
				System.out.println("Message ID: "+txtmsg.getJMSMessageID());
				System.out.println("Message Content: "+txtmsg.getText());
			}
		}
		
		
		System.out.println("Closing connections");
		consumer.close();
		sess.close();
		conn.close();
		System.out.println("All closed");
	}
}
</code>

Setelah kode program di atas dijalankan, refresh queue browser di Hermes. Harusnya pengambilan message tersebut akan menghapus message di server.

Kita juga bisa mengirim message menggunakan kode program berikut.

<code>package tutorial.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class HelloQueueSender {
	public static void main(String[] args) throws JMSException {
		ConnectionFactory factory = new ActiveMQConnectionFactory(
				ActiveMQConnection.DEFAULT_USER,
				ActiveMQConnection.DEFAULT_PASSWORD,
				ActiveMQConnection.DEFAULT_BROKER_URL);
		System.out.println("Connecting to: "+ActiveMQConnection.DEFAULT_BROKER_URL);
		System.out.println("With username : "+ActiveMQConnection.DEFAULT_USER);
		System.out.println("and password : "+ActiveMQConnection.DEFAULT_PASSWORD);
		
		Connection conn = factory.createConnection();
		System.out.println("Connected");
		
		Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
		System.out.println("Session created");
		
		Queue destination = sess.createQueue("coba");
		System.out.println("Queue created");
		
		MessageProducer prod = sess.createProducer(destination);
		TextMessage msg = sess.createTextMessage();
		msg.setText("Hello JMS");
		
		prod.send(msg);
		System.out.println("Message sent");
		
		prod.close();
		sess.close();
		conn.close();
	}
}
</code>

Setelah kode program di atas dijalankan, kita dapat merefresh queue browser di Hermes untuk memastikan bahwa kode program kita berhasil mengirim message.

Demikianlah, dengan menggunakan HermesJMS, kita dapat memeriksa secara visual apakah kode program kita dapat mengakses JMS Server dengan benar.


Network Address Translation

Pada artikel kali ini, kita akan membahas penggunaan NAT untuk memungkinkan aplikasi kita yang jalan di laptop bisa diakses orang dari internet. NAT adalah singkatan dari Network Address Translation.

Gunanya supaya kita bisa mempublish aplikasi yang berjalan komputer di jaringan internal. Misalnya kita menjalankan aplikasi web di port 8080 di laptop dengan IP private : 192.168.0.10. Kita ingin aplikasi ini bisa diakses dari orang di internet. Laptop kita terhubung ke router yang memiliki IP public 202.159.11.11.

Normalnya, orang di internet tidak bisa langsung mengakses aplikasi kita melalui dengan alamat http://192.168.0.10:8080 dari internet. Karena alamat IP 192.168.0.10 adalah alamat internal, yang tidak dikenali di luar.

Untuk itu, kita harus mengkonfigurasi gateway internet kita agar bisa meneruskan request dari internet ke laptop kita. Ini bisa dilakukan dengan memasang konfigurasi NAT di gateway internet kita. Berikut cara kerjanya.

Request http dilakukan dari komputer asal ke komputer tujuan, dengan menuliskan alamat pengirim dan alamat penerima. Mirip dengan kalau kita kirim surat. Pesannya ditulis di kertas, masukkan amplop, tulis alamat penerima dan alamat pengirim.

Contoh paketnya kira-kira seperti ini.

Dari  : 202.159.22.22
Untuk : 202.159.11.11
Pesan : halo

Pesan di atas akan bisa sampai ke gateway, karena 202.159.11.11 adalah IP public yang dikenal semua orang di internet.

Bila gateway ingin meneruskan pesan ini ke komputer internal, maka dia akan membungkus paket tersebut dengan amplop baru, alamat tujuannya diganti dengan IP internal, agar bisa mencapai laptop yang alamat IPnya internal. Proses ini dinamakan DNAT (Destination NAT).

Bila alamat tujuan tidak diganti, maka paket tidak akan sampai ke komputer internal.

Di Linux, ini dilakukan dengan perintah iptables. Perintahnya adalah sebagai berikut:

iptables -t nat -A PREROUTING -d 202.159.11.11 -p tcp --dport 8080 -j DNAT --to-destination 192.168.0.10:8080

Setelah diDNAT, paketnya menjadi seperti ini:

Dari  : 202.159.22.22
Untuk : 192.168.0.10
Pesan : halo

Setelah itu, amplop lewat proses routing di gateway. Router akan bisa menyampaikan paket tersebut ke laptop, karena dia kenal 192.168.0.10 itu adalah laptop.

Akhirnya paket sampai di tujuan.

Dengan menggunakan DNAT ini, kita bisa mempublikasikan laptop kita di jaringan internal agar bisa diakses dari luar.

Bagaimana kalau laptop kita ingin mengirim balasan data?

Prosesnya kira-kira sama. Dia masukkan ke amplop, menaruh alamat pengirim menjadi alamat tujuan, dan menaruh alamat laptop menjadi alamat pengirim. Kemudian data tersebut dikirim ke router.

Paketnya kira-kira seperti ini:

Dari  : 192.168.0.10
Untuk : 202.159.22.22
Pesan : halo juga

Laptop kita akan mengalami kebingungan untuk mengirim paket tersebut. Karena dia tidak kenal 202.159.22.22. Dia hanya kenal teman-temannya sesama anggota jaringan 192.168.0.0. Paket balasan ini tidak akan berhasil terkirim.

Untuk itu, gateway perlu melakukan satu perubahan lagi. Sebelum dia mengirim paket tadi ke laptop kita, dia perlu mengganti alamat pengirim menjadi alamat internalnya sendiri (biasanya nomor terkecil, yaitu 192.168.0.1). Jadinya kira-kira seperti ini

Dari  : 192.168.0.1
Untuk : 192.168.0.10
Pesan : halo

Proses ini dinamakan SNAT (Source NAT). Perintahnya adalah sebagai berikut:

iptables -t nat -A POSTROUTING -p tcp --dport 8080 -j SNAT --to-source 192.168.0.1

Setelah diSNAT pesan tersebut bisa dibalas oleh aplikasi di laptop kita seperti ini:

Dari  : 192.168.0.10
Untuk : 192.168.0.1
Pesan : halo juga

Pesan ini akan diterima oleh gateway, dan kemudian akan diteruskan ke pengirim aslinya yaitu 202.159.22.22

Dengan menggunakan SNAT, kita juga bisa mengimplementasikan Internet Connection Sharing, yaitu satu koneksi internet dibagi beramai-ramai.

Ada satu kasus khusus untuk SNAT, namanya Masquerade. Ini digunakan apabila IP public yang digunakan berubah-ubah. Misalnya kalau kita pakai dialup connection.

Kalau kita nekat pakai SNAT, nanti akan repot, karena harus update rule setiap dial ke internet dan mendapatkan IP public yang berbeda.

Solusinya, kita gunakan masquerade. Berikut perintahnya:

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE

Dengan menggunakan masquerade, kita tidak perlu menyebutkan --to-source karena alamat IP asal (IP publik gateway kita) berubah-ubah.

Perhatian: Jangan lupa untuk mengaktifkan IP Forwarding di gateway dengan perintah

cat 1 > /proc/sys/net/ipv4/ip_forward

Rangkaian perintah ini akan hilang pada saat reboot. Jadi harus ada usaha tambahan agar konfigurasi ini jadi permanen. Caranya, tergantung masing-masing distro. Biasanya, kita simpan dulu ke file menggunakan perintah iptables-save

iptables-save > /etc/iptables/rules.v4

Kemudian file tersebut kita load menggunakan perintah iptables-restore

iptables-restore < /etc/iptables/rules.v4

Agar berjalan setiap kali booting, panggil perintah iptables-restore dari script rc.local. Lokasi script ini berbeda antar distro, untuk keluarga Debian terletak di folder /etc.

Sayangnya saat ini iptables hanya ada di Linux, dan nampaknya tidak akan ada versi Windowsnya. Karena iptables sangat tightly-coupled dengan kernel linux.

Untuk Windows, kita dapat gunakan fitur Internet Connection Sharing apabila ada. Beberapa versi Windows (misalnya XP Home), tidak punya fitur ini. Jadi solusinya adalah dengan menggunakan aplikasi tambahan seperti misalnya WinGate atau WinRoute.