Posts tagged ‘JNDI’
JNDI: Akses Mudah Ke Layanan Direktori
Kali ini aku akan mencoba latihan mengakses LDAP server melalui JNDI. Karena JNDI bawaan dari JDK sudah menyertakan service provider untuk akses LDAP, aku tidak perlu mendownload library apapun. Yang aku perlukan hanya memiliki sebuah LDAP server dan LDAP client (optional). Untuk platform Windows, aku memilih memakai Apache Directory Server, sebuah LDAP server open-source berbasis Java. Selain dapat dijalankan standalone, ApacheDS juga dapat dijalankan dalam program Java lain (embedded), seperti pada server JBoss.
Setelah meng-install dan menjalankan ApacheDS, aku perlu memasukkan data ke dalam schema di partisi yang aktif. Cara paling gampang adalah dengan menginstall sebuah LDAP client yang mendukung import data. Dan pilihanku untuk LDAP client jatuh pada Apache Directory Studio. Catatan samping: Apache Directory Studio adalah tools berbasis Eclipse RCP. Tampilannya akan mirip “Eclipse“. Sebenarnya, “Eclipse” adalah sebuah platform yang lahir dari sebuah proyek IBM untuk menyamakan user interface di produk mereka sehingga user tidak perlu bingung beradaptasi dengan look & feel yang berbeda di tiap produk. Yang populer adalah Eclipse sebagai IDE untuk pemograman Java (Eclipse JDT), tapi “Eclipse” tidak hanya itu, ia bisa berupa apa saja yang memiliki “tampilan” serupa.
Aku membuat koneksi baru di Apache Directory Studio dengan memilih menu LDAP, New Connection. Lalu aku mengisi parameter yang ada dengan nilai default dari ApacheDS, dimana hostname adalah localhost, port adalah 10389, dan no encryption. Bind DN yang dipakai adalah “uid=admin, ou=system” dan default password-nya adalah “secret“. Setelah koneksi terjalin secara sukses, aku meng-import file %APACHEDS_HOME%\conf\example.ldif. Format file LDIF adalah format standar untuk bertukar data yang didukung oleh semua server LDAP. Setelah itu, aku dapat menemukan DN “ou=Users,dc=example,dc=com” yang berisi 6 data user (3 lagi tidak bisa dipakai saat ini). Sekarang aku siap untuk men-query data ini melalui program Java.
Langkah pertama yang aku lakukan adalah menyiapkan context, seperti pada program berikut:
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
try {
InitialDirContext ctx = new InitialDirContext(env);
...
} catch (NamingException e) {
e.printStackTrace();
}
Setelah itu, aku bisa mulai melakukan operasi, seperti menampilkan nama user (atribut cn) dan email (attribut mail) di setiap child dari “ou=Users, dc=example, dc=com“, seperti pada contoh berikut:
NamingEnumeration<NameClassPair> bindingEnum = ctx.list("ou=Users,dc=example,dc=com");
StringBuffer output = new StringBuffer();
while (bindingEnum.hasMore()) {
NameClassPair nameClass = bindingEnum.next();
Attributes attr = ctx.getAttributes(nameClass.getNameInNamespace());
if (attr.get("cn")!=null) {
output.append("Name = " + attr.get("cn").get() + "; ");
}
if (attr.get("mail")!=null) {
output.append("Email = " + attr.get("mail").get() + "; ");
}
output.append("\n");
}
System.out.println(output.toString());
Output dari program di atas adalah:
Name = Max Planck; Email = mplanck@example.com;
Name = Albert Einstein; Email = aeinstein@example.com;
Name = Neils Bohr; Email = nbohr@example.com;
Name = Max Born; Email = mborn@example.com;
Name = Wolfgang Pauli; Email = wpauli@example.com;
Name = Marie Curie; Email = mcurie@example.com;
Untuk melakukan pencarian melalui filter yang didefinisikan dalam RFC 2254, aku dapat membuat kode program seperti berikut:
InitialDirContext ctx = new InitialDirContext(env);
StringBuffer output = new StringBuffer();
String strNama = JOptionPane.showInputDialog("Masukkan nama yang akan dicari:");
if (strNama!=null && strNama.length()>0) {
SearchControls ctl = new SearchControls();
ctl.setReturningAttributes(new String[] {"cn","mail"});
NamingEnumeration<SearchResult> en =
ctx.search("ou=Users,dc=example,dc=com", "(&(cn=*" + strNama + "*)(mail=*))", ctl);
if (!en.hasMore()) {
System.out.println("Nama tidak ditemukan dalam server LDAP!");
System.exit(0);
}
while (en.hasMore()) {
Attributes attr = en.next().getAttributes();
output.append("Nama = " + attr.get("cn").get() + "; ");
output.append("Email = " + attr.get("mail").get() + "; ");
output.append("\n");
}
System.out.println(output.toString());
}
Apache Tomcat: Konfigurasi JNDI
Tomcat juga mendukung JNDI layaknya application server JEE lainnya, hanya saja konfigurasinya lebih tidak user-friendly. Kali ini aku akan mencoba membuat JNDI Resource yang berupa JDBC Data Sources sehingga aku dapat meng-akses database di kode program melalui nama JNDI. Keuntungannya, jika aku mengganti database, aku hanya perlu merubah konfigurasi JNDI Resource tanpa harus mengubah kode program sedikitpun.
Karena aku memakai Oracle Database 10g, aku men-copy file %ORACLE_HOME%\jdbc\lib\ojdbc14.jar (driver JDBC) ke lokasi %CATALINA_HOME%\lib (lokasi yang berisi library yang berlaku untuk seluruh aplikasi web). Lalu aku menambahkan baris berikut pada web.xml milik aplikasi web:
<resource-ref> <res-ref-name>jdbc/databaseDevelopment</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
Lalu, aku menambahkan baris berikut pada %CATALINA_HOME%\conf\context.xml:
<Resource name="jdbc/databaseDevelopment" auth="Container" type="javax.sql.DataSource" username="scott" password="tiger" driverClassName="oracle.jdbc.OracleDriver" url="jdbc:oracle:oci:@latihan" maxActive="1" maxIdle="10" />
Pada konfigurasi di atas, aku memakai data source standard dari Tomcat yang berdasarkan pada DBCP connection pool (salah satu bagian dari Apache Common project). Setelah itu, aku dapat memulai kode di servlet, misalnya:
Context initialContext = new InitialContext();
Context envContext = (Context) initialContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/databaseDevelopment");
cn = ds.getConnection();
Statement st = cn.createStatement();
ResultSet rs = st.executeQuery("SELECT ENAME FROM EMP");
while (rs.next()) {
output.print(rs.getString(1) + "<br>");
}
Jika tidak ingin mengatur konfigurasi JNDI dengan cara manual, melainkan dengan interface berbasis web layaknya application server lain, aku dapat menggunakan AMS dari SpringSource tc Server. Tentu saja kenyamanan ini diperoleh dengan biaya tertentu (tidak lagi gratis).