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.

Network Device menghilang di VMWare

Saya menggunakan VMWare secara intensif dalam proses development. Salah satu penggunaannya adalah untuk menginstal aplikasi atau database milik client. Beberapa merek database seperti Oracle relatif invasif terhadap sistem, misalnya mendikte jumlah swap ataupun mengharuskan mengedit kernel parameter. Tentunya ini membuat kotor sistem operasi saya.

Selain itu, kadangkala client menggunakan sistem operasi yang berbeda dengan yang saya gunakan. Ini juga dapat diselesaikan dengan menggunakan VMWare.

Saya menyimpan file-file VM di harddisk eksternal, untuk meningkatkan performance. Menurut Jeff Atwood, kinerja VM akan meningkat bila dia berada di harddisk yang berbeda dengan hostnya.

Penyimpanan di harddisk eksternal ini ternyata mengundang sedikit masalah. Kadangkala network interface VM saya menghilang. Masalah ini terjadi pada kombinasi host Ubuntu dan guest Ubuntu.

Setelah googling kesana kemari, ternyata ini disebabkan oleh beberapa hal :

  1. Ubuntu me-mount partisi harddisk eksternal secara acak. Kadang partisi 1 dimount ke /media/disk-1, kadang ke /media-disk-2

  2. Bila posisi mount berubah, VMWare akan menggenerate UUID (ID unik untuk guest VM) baru

  3. Setiap kali UUID berubah, MAC Address network interface guest VM juga berubah.

  4. Ubuntu di guest VM meng-cache MAC address, sehingga kalau MAC yang dia cache tidak ada, network interface tersebut tidak akan diload

Solusinya mudah, yaitu menghapus cache MAC address di guest Ubuntu, dan merestartnya. Caranya, login ke guest OS, lalu hapus file /etc/udev/rules.d/70-persistent-net.rules. Setelah itu restart.

sudo rm /etc/udev/rules.d/70-persistent-net.rules
sudo reboot

Setelah restart, guest VM akan kembali memiliki ethernet card.


Enkripsi JDBC Properties

Bila kita membuat aplikasi Java yang menggunakan database, pasti kita akan membuat satu file untuk konfigurasi koneksi database, biasanya diberi nama jdbc.properties. Isinya kira-kira sebagai berikut:

jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost/belajar
jdbc.username = belajar
jdbc.password = java

Cepat atau lambat, kita akan menemui kebutuhan untuk menyembunyikan nilai yang diisikan ke dalam file tersebut untuk alasan keamanan. Tentunya kita tidak ingin orang yang bisa membaca file tersebut login ke database dan melihat berbagai data rahasia dalam database.

Kita ingin mengenkripsi minimal variabel jdbc.password, supaya tidak bisa dibaca sembarang orang. Bila kita menggunakan Spring Framework untuk membaca file tersebut, kita bisa menggunakan Jasypt yang mampu menangani masalah enkripsi file tersebut.

Lanjut membaca ...


SVN Externals

Dalam membuat aplikasi, seringkali kita membutuhkan source-code dari aplikasi lainnya. Misalnya, jika kita sudah membuat cukup banyak aplikasi, maka fitur login dan logout pasti sudah sering kita buat.

Daripada menulis ulang fitur tersebut, alangkah lebih baiknya jika kita reuse kode programnya dalam aplikasi yang akan dibuat. Dengan demikian, setelah melewati beberapa project, kode program yang direuse tersebut akan bertambah kemampuannya dan semakin canggih.

Kita dapat melakukan hal ini dengan menggunakan fitur svn external. Misalnya struktur kode program kita terdiri dari modul berikut:

  • Master Data

  • Transaksi

  • Report

  • Security

Kita ingin me-reuse kode program security yang ada di aplikasi lain. Dengan demikian, kita perlu menambahkan folder tersebut ke dalam source-tree kita.

Untuk melakukan hal tersebut, kita mengedit property Subversion yang bernama svn:externals. Berikut cara menambah property tersebut :

  1. Checkout dulu seluruh trunk.

    svn co http://repo.server.com/svn/nama-project/trunk project-saya

  2. Tambahkan property svn:externals ke project yang sudah ada.

    svn propset svn:externals “modul-security http://repo.server.com/svn/project-lain/trunk/modul-security” project-saya

  3. Commit deh

    cd project-saya svn ci -m “tambahkan property svn:external”

  4. Untuk mengambil source code modul-security, lakukan svn update

    svn update

Kode program modul-security siap digunakan. Ingat, kalau kita melakukan perubahan di dalamnya dan melakukan commit, maka perubahan akan dikirim ke repository asalnya, yaitu http://repo.server.com/svn/project-lain/trunk/modul-security

Lalu bagaimana kalau kita tidak ingin mengikuti perkembangan modul-security? Bisa saja ada programmer lain yang mengubah modul-security dan menyebabkan kode kita rusak.

Caranya, referensikan modul-security ke tags, jangan ke trunk.

Demikian cara berbagi kode program lintas project. Semoga bermanfaat.


Membuat Mirror Repository Ivy

Pada rangkaian artikel sebelumnya, kita telah membahas tentang:

  1. Instalasi Ivy

  2. Build Management dengan Ivy

  3. Otomasi Build Process dengan Ant

  4. Publish Modul ke Repository

  5. Deklarasi internal dependency

  6. Deklarasi external dependency

  7. Ivy Configuration

Semua konsep dan pengetahuan di atas memungkinkan kita untuk menggunakan Ivy secara efektif untuk mengelola pembuatan aplikasi. Tetapi ada sedikit hal yang masih mengganjal, yaitu borosnya bandwidth yang digunakan selama build process dilakukan.

Pada artikel kali ini, kita akan membahas cara membuat mirror repository, sehingga pengambilan artifak dapat dilakukan dari server internal maupun harddisk lokal, sehingga tidak memboroskan bandwidth.

Di artikel sebelumnya, kita telah membahas tentang deklarasi resolver. Resolver adalah konfigurasi yang menyatakan lokasi repository. Ada beberapa jenis resolver yang disediakan Ivy:

  • Filesystem : repository Ivy di harddisk lokal

  • URL : repository Ivy yang diakses melalui protokol http

  • SSH : repository Ivy yang diakses melalui protokol scp/ssh

  • SFTP : repository Ivy, diakses melalui protokol sftp

  • VFS : repository Ivy, kompatibel dengan file system yang didukung oleh Apache Commons VFS, diantaranya WebDAV, FTP, ZIP, dan sebagainya

  • Ibiblio : repository Maven 2, diakses melalui protokol http

Sebagai contoh kasus, kita akan membuat mirror dari repository ivy milik SpringSource dan repository Maven2 di Ibiblio.

Pertama, kita deklarasikan dulu resolver untuk kedua repository sumber. Konfigurasi ini dibuat dalam ivysettings.xml.

SpringSource memiliki dua repo berbeda, untuk artifak yang dihasilkannya sendiri (Spring Portfolio) disebut dengan release, dan untuk pustaka external (Hibernate, JSF, dsb; disebut dengan external. Berikut konfigurasi untuk kedua repo SpringSource, sesuai dengan dokumentasinya:

<url name="springsource.release.repo.resolver">
	<ivy pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
	<artifact pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>

<url name="springsource.external.repo.resolver">
	<ivy pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
	<artifact pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>

Dan ini adalah resolver untuk Ibiblio.

<ibiblio name="maven2" m2compatible="true" />

Repository SpringSource akan kita mirror di http://repo.artivisi.com/ivy/springsource/ dengan struktur folder nama-organisasi/nama-modul/nomer-revisi/[artifak]-[revisi].[extension]. Folder tersebut berada di mesin repo.artivisi.com dalam folder /var/www/repo.artivisi.com/ivy/springsource. Berikut konfigurasi repo mirror-springsource.

<ssh name="springsource.mirror.resolver" keyFile="${user.home}/.ssh/id_rsa" host="repo.artivisi.com" user="${mirror.host.user}">
	<ivy pattern="/var/www/repo.artivisi.com/ivy/springsource/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
	<artifact pattern="/var/www/repo.artivisi.com/ivy/springsource/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</ssh>

Repository Ibiblio akan kita mirror di http://repo.artivisi.com/ibiblio dengan struktur folder berbeda, untuk metadata sebagai berikut: [nama-organisasi]/[nama-modul]/ivys/ivy-[nomer-revisi].xml, dan untuk artifak sebagai berikut: [nama-organisasi]/[nama-modul]/[jenis]s/[artifak]-[nomer-revisi].[extension]. Folder tersebut berada di mesin repo.artivisi.com dalam folder /var/www/repo.artivisi.com/ibiblio. Berikut konfigurasinya:

<ssh name="ibiblio.mirror.resolver" keyFile="${user.home}/.ssh/id_rsa" host="repo.artivisi.com" user="${mirror.host.user}">
	<ivy pattern="/var/www/repo.artivisi.com/ibiblio/[organisation]/[module]/ivys/ivy-[revision].xml"/>
	<artifact pattern="/var/www/repo.artivisi.com/ibiblio/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</ssh>

Setelah kita memiliki dua repository sumber dan dua repository tujuan, kita buat target untuk melakukan mirroring. Di Ivy, kegiatan mirroring ini disebut dengan istilah install. Kita memiliki tiga target install, untuk ibiblio, SpringSource release, dan SpringSource external. Berikut deklarasi targetnya, kita masukkan di ivybuilder.xml bersama dengan target untuk resolve dan publish.

<target name="install-springsource-release" description="--> install dependency from springsource repo">
	<ivy:install 
		organisation="${organisation}" 
		module="${module}" 
		revision="${revision}"
		from="${springsource.release.repo.resolver}" 
		to="${springsource.mirror.resolver}" 
		transitive="true"
		overwrite="true"
	/>	
</target>

<target name="install-springsource-external" description="--> install dependency from springsource repo">
	<ivy:install
		organisation="${organisation}" 
		module="${module}" 
		revision="${revision}"
		from="${springsource.external.repo.resolver}" 
		to="${springsource.mirror.resolver}" 
		transitive="true"
		overwrite="true"
	/>

</target>

<target name="install-ibiblio" description="--> install dependency from ibiblio maven2 repo">
	<ivy:install 
		organisation="${organisation}" 
		module="${module}" 
		revision="${revision}"
		from="${ibiblio.repo.resolver}" 
		to="${ibiblio.mirror.resolver}" 
		transitive="true"
		overwrite="true"
	/>
</target>

Seperti kita lihat di atas, deklarasi target install cukup generik, dengan menggunakan variabel yang bisa di-override pada saat runtime. Untuk target install-springsource-external, kita gunakan repo external SpringSource sebagai sumber, dan mirror-springsource sebagai tujuan. Target install-springsource-release dan install-ibiblio juga mirip.

Sekarang saatnya kita coba. Mari kita install Hibernate Annotations versi 3.3.1.GA. Modul ini ada di repository SpringSource external.

Langkah pertama, cari dulu modul yang kita inginkan. Kita bisa gunakan halaman search yang telah disediakan. Dari hasil pencarian, kita menemukan modul yang diinginkan, berikut dengan deklarasi dependensinya. Sekarang kita telah mengetahui nama organisasi, nama modul, dan nomer revisinya.

ant install-springsource-external -Dorganisation="org.hibernate" -Dmodule="com.springsource.org.hibernate.annotations" -Drevision="3.3.1.ga"

Ivy akan melakukan resolve dan melihat semua dependensi dari Hibernate Annotations versi 3.3.1.GA. Setelah itu, Ivy akan mendonlodnya ke cache lokal, untuk kemudian diupload melalui scp ke lokasi mirror.

Terakhir, tentunya mirror repository ini akan diakses orang menggunakan http, bukan ssh. Jadi kita harus buatkan resolver untuk mengakses http://repo.artivisi.com/ivy/springsource dan http://repo.artivisi.com/ibiblio. Berikut konfigurasinya, kita satukan menggunakan chain-resolver.

Demikianlah rangkaian tutorial tentang penggunaan Ivy. Mungkin banyak pembaca yang membatin,

Buat apa repot-repot, pakai Netbeans atau Eclipse kan juga bisa bikin jar/war.

Biar saya kasih bocoran sedikit tentang dapur ArtiVisi. Kami akan mengadopsi SOA (Service Oriented Architecture) dalam semua produk dan project kami. Adopsi ini dilakukan di level mikro dengan menggunakan platform OSGi. Karakteristik utama aplikasi SOA dengan OSGi adalah aplikasi akan terdiri dari banyak modul-modul kecil yang saling berinteraksi. Contohnya bisa dilihat di diagram modul yang disajikan di awal artikel.

Memecah aplikasi besar menjadi modul-modul kecil tidak terlalu sulit. Siapapun yang mengenal keyword import dan konsep CLASSPATH di Java bisa melakukannya. Yang sulit adalah mengelola kegiatan development dan integrasi antar modul. Oleh karena itu, penggunaan dependency management seperti Ivy atau Maven2 adalah hal yang wajib.

Pembaca bisa memilih apakah akan menggunakan Maven2 ataupun Ivy. Konsep dasarnya mirip, tapi implementasinya berbeda. Jadi, kalau sudah menguasai Ivy, Maven2 tidak sulit. Demikian juga sebaliknya. Silahkan mencari yang sesuai dengan kebutuhan tim Anda.


Ivy Configuration

Rangkaian artikel sebelumnya telah memberikan kita pemahaman yang memadai untuk menggunakan Ivy. Pada artikel ini, kita akan membahas satu fitur Ivy yang walaupun tidak wajib dikuasai, tapi sangat penting, karena dapat membuat konfigurasi modul kita menjadi fleksibel. Fitur ini dalam dunia Ivy dikenal dengan istilah configuration.

Sebagai paket standar kualitas di ArtiVisi, kami menggunakan Cobertura untuk melakukan coverage test. Sayangnya Cobertura dan Hibernate tidak kompatibel. Hibernate menggunakan pustaka asm dengan versi 1.5.3. Sedangkan Cobertura juga menggunakan asm, dengan versi 2.2.1. Bila kedua versi kita campur, maka akan terjadi error karena Java VM kebingungan menentukan versi mana yang akan digunakan.

Untuk mengatasi masalah ini, kita menggunakan fitur configuration Ivy. Kita membuat konfigurasi bernama test yang membawa asm versi 2.2.1 sesuai kebutuhan Cobertura. Selain itu, kita juga membuat konfigurasi bernama runtime dengan asm versi 1.5.3 untuk digunakan Hibernate. Hal ini dimungkinkan karena Cobertura hanya kita gunakan pada saat test.

Contoh lain penggunaan configuration adalah kombinasi modul untuk merakit aplikasi. Misalnya, kita memiliki modul-modul berikut dalam aplikasi kita:

  • model

  • dao.api

  • dao.hibernate

  • dao.jdbc

  • ui.web

  • ui.desktop

Kita dapat menggunakan konfigurasi Ivy untuk membentuk 4 kombinasi aplikasi, yaitu:

  • Desktop dengan JDBC

  • Desktop dengan Hibernate

  • Web-based dengan JDBC

  • Web-based dengan Hibernate

Fitur configuration juga bisa digunakan untuk mengatur rilis artifak, sehingga dari satu paket source-code, kita bisa membuat rilis:

  • Hanya source-code (source only)

  • Hanya hasil kompilasi (binary only)

  • Paket dokumentasi (javadoc, reference)

  • Paket komplit (source, binary, dokumentasi)

Kombinasi rilis ini umum kita temui dalam pustaka open-source populer seperti Spring Framework atau Hibernate.

Masih banyak lagi skenario penggunaan configuration. Silahkan kembangkan imajinasi Anda untuk penggunaannya. Pada artikel ini, kita akan membahas skenario kombinasi aplikasi seperti ilustrasi di atas.

Kita telah memiliki modul person-model, dengan deklarasi dependensi (ivy.xml) sebagai berikut:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-model"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>

	<publications>
		<artifact name="${ant.project.name}" conf="api"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
</ivy-module>

Daftar konfigurasi yang kita miliki didefinisikan dalam file ivyconfigurations.xml dan di-include dari masing-masing ivy.xml. Berikut isi ivyconfigurations.xml.

<configurations>
	<conf name="compile"            description="dependency for compile time only" />
	<conf name="api"     description="Domain Model and API only"/>
	<conf name="impl"    description="implementation of APIs"/>
	<conf name="source"  description="source code only"/>
</configurations>

Kita juga punya modul person-dao, interface yang digunakan sebagai patokan implementasi akses database, dengan dependensi sebagai berikut:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-dao-api"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>

	<publications>
		<artifact name="${ant.project.name}" conf="api"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
    <dependencies>
        <dependency name="person-model" rev="latest.integration" conf="api"/>
    </dependencies>
</ivy-module>

Modul person-dao ini memiliki dua jenis implementasi, yaitu dengan JDBC:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-dao-jdbc"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>

	<publications>
		<artifact name="${ant.project.name}" conf="impl"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
        <dependency name="person-dao-api" rev="latest.integration" conf="api"/>
        
    </dependencies>
</ivy-module>

dan dengan Hibernate:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-dao-hibernate"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>

	<publications>
		<artifact name="${ant.project.name}" conf="impl"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
        <dependency name="person-dao-api" rev="latest.integration" conf="api"/>
    </dependencies>
</ivy-module>

Dengan memisahkan interface dan implementasi DAO, kita bisa langsung membuat dua jenis user interface, yaitu yang berbasis web sebagai berikut:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-ui-springmvc"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>
	
	<publications>
		<artifact name="${ant.project.name}" conf="impl"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
        <dependency name="person-dao-api" rev="latest.integration"  conf="api"/>
    </dependencies>
</ivy-module>

dan berbasis desktop sebagai berikut:

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-ui-swing"/>
    
    <configurations>
		<include file="${basedir}/../person-build/ivy/ivyconfigurations.xml" />
	</configurations>
	
	<publications>
		<artifact name="${ant.project.name}" conf="impl"/>
		<artifact name="${ant.project.name}-sources" conf="source" type="src" ext="jar"/>
	</publications>
    
        <dependency name="person-dao-api" rev="latest.integration"  conf="api"/>
    </dependencies>
</ivy-module>

Seperti kita lihat, untuk bisa membuat UI, kita hanya membutuhkan modul dao saja.

Untuk merangkai aplikasi ini, kita membuat satu modul yang tidak berisi source-code Java sama sekali, melainkan hanya deklarasi dependensi saja.

Berikut konfigurasi untuk aplikasi desktop dengan JDBC.

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-apps"/>
    
    <configurations>
		<conf name="person-app-desktop-jdbc" description="Application with desktop UI and JDBC backend"/>
	</configurations>
    
    <dependencies>
    	
        <dependency name="person-dao-jdbc" rev="latest.integration" 
        conf="person-app-desktop-jdbc->impl"/>
        
        <dependency name="person-ui-swing" rev="latest.integration" 
        conf="person-app-desktop-jdbc->impl"/>
        
    </dependencies>
    
</ivy-module>

dan ini adalah konfigurasi untuk aplikasi web dengan Hibernate.

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-apps"/>
    
    <configurations>
		<conf name="person-app-web-hibernate" description="Application with web-based UI and Hibernate backend"/>
	</configurations>
    
    <dependencies>
    	        
        <dependency name="person-dao-hibernate" rev="latest.integration" 
        conf="person-app-web-hibernate->impl"/>
        
        <dependency name="person-ui-springmvc" rev="latest.integration" 
        conf="person-app-web-hibernate->impl"/>
        
         
    </dependencies>
    
</ivy-module>

Deklarasi lengkap konfigurasi dan dependensi untuk keempat kombinasi aplikasi sebagai berikut.

<ivy-module version="1.0">
    <info organisation="com.artivisi" module="person-apps"/>
    
    <configurations>
		<conf name="person-app-web-jdbc" description="Application with web-based UI and JDBC backend"/>
		<conf name="person-app-desktop-jdbc" description="Application with desktop UI and JDBC backend"/>
		<conf name="person-app-web-hibernate" description="Application with web-based UI and Hibernate backend"/>
		<conf name="person-app-desktop-hibernate" description="Application with desktop UI and Hibernate backend"/>
	</configurations>
    
    <dependencies>
    	
        <dependency name="person-model" rev="latest.integration" conf="*->api"/>

        <dependency name="person-dao-api" rev="latest.integration" conf="*->api"/>
		
        <dependency name="person-dao-jdbc" rev="latest.integration" 
        conf="person-app-web-jdbc->impl;person-app-desktop-jdbc->impl"/>
        
        <dependency name="person-dao-hibernate" rev="latest.integration" 
        conf="person-app-web-hibernate->impl;person-app-desktop-hibernate->impl"/>
        
        <dependency name="person-ui-swing" rev="latest.integration" 
        conf="person-app-desktop-jdbc->impl;person-app-desktop-hibernate->impl"/>
        
        <dependency name="person-ui-springmvc" rev="latest.integration" 
        conf="person-app-web-jdbc->impl;person-app-web-hibernate->impl"/>
        
         
    </dependencies>
    
</ivy-module>

Kita dapat merakit aplikasi dengan ant sebagai berikut

ant resolve

Nanti pada folder lib akan terbentuk empat folder sesuai konfigurasi. Isi dari masing-masing folder mencerminkan paket aplikasi sesuai kombinasi yang kita inginkan.

Seperti kita lihat, dengan menggunakan fitur configuration, kita dapat merangkai empat kombinasi aplikasi dengan mudah. Tentunya aplikasi kita harus dirancang secara modular supaya mudah dikombinasikan seperti cerita di atas.

Artikel berikutnya akan menutup seri Ivy ini dengan cara membuat repository dalam organisasi kita. Dengan adanya repository lokal, kita dapat menghemat bandwidth internasional karena kebutuhan dependensi dapat ditangani oleh server internal.

Kita akan melihat kemampuan Ivy untuk mengadaptasi repository baik yang memiliki metadata Ivy, maupun Maven.