20 July 2013

Spring Remoting dengan Http Invoker

Hallo pembaca, rupanya lumayan lama juga saya tidak meng-update blog ini dengan tulisan-tulisan tentang java programming. Terakhir saya menulis di blog ini seputar masalah Java Swing yang kebetulan saat itu saya sedang sibuk-sibuknya coding java menggunakan Swing Framework. Baiklah, untuk tulisan kali ini saya ingin berbagi tentang bagaimana menjadikan Spring Framework sebagai sebuah aplikasi back-end yang bisa di remote melalui HTTP
Spring Framework adalah sebuah framework yang memiliki fitur yang sangat kaya dengan kemudahan pemanfaatannya. Sebagai sebuah framework yang saat ini banyak dipakai di dunia, Spring Framework juga melengkapi diri dengan fitur remote. Fitur ini dapat di implementasi dengan berbagai cara misalnya lewat HTTP Invoker,  Burlap, dan Hessian. Tentu saja masing-masing implementasi memiliki kelebihan dan kekurangan tersendiri.
Kali ini kita akan mencoba mengimplementasi Spring Remoting dengan HTTP Invoker. Sebelum kita melakukan percobaan ini ada baiknya kita memahami apa yang dimaksud dengan Spring remoting itu sendiri. Spring remoting adalah sebuah cara pengaksesan method atau fungsi yang ada dalam sebuah aplikasi. Pengaksesan method atau fungsi ini dilakukan oleh aplikasi lain yang berada diluar aplikasi yang sedang berjalan. Bisa juga dikatakan bahwa implementasi Spring remote merupakan sebuah implementasi aplikasi client server, dimana client dan server merupakan dua aplikasi yang berbeda namun client mampu mengakses method atau fungsi yang ada dalam aplikasi server secara remote. Implementasi HTTP Invoker adalah sebuah cara yang dilakukan oleh Spring Framework dalam meng-ekspos method-method yang dimilikinya lewat protocol HTTP agar nantinya method-method ini bisa di remote oleh client-client yang membutuhkan.
Sekarang mari kita coba membuat aplikasi yang mampu mengimplementasi HTTP Invoker tersebut. Buatlah sebuah project dengan struktur seperti gambar berikut ini:
Saya menggunakan maven sebagai automatisasi development dalam project ini. Sementara jika kita lihat dari gambar diatas kita memiliki sebuah package yaitu : org.josescalia.springremote, package ini terdiri dari 2 package di bawahnya yaitu package service dan package client. Package service ini berisi class yang memiliki fungsi/method yang nantinya akan bisa di remote oleh client-client yang menggunakannya. Dan untuk package client, didalamnya saya membuat sebuah aplikasi client yang akan me-remote fungsi/method yang ada dalam class yang terletak di package service.
Untuk library yang digunakan dalam pom.xml saya menambahkan 2 library seperti dibawah ini :

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

Sekarang mari kita lihat masing-masing code yang ada pada project tersebut:
File: HelloWorldService.java

package org.josescalia.springremote.service;

public interface HelloWorldService {
    String helloWorld(String name);
}

Oleh karena ini hanya interface maka hanya seperti itu code-nya :P
File : HelloWorldServiceImpl.java

package org.josescalia.springremote.service;

import org.springframework.stereotype.Service;

@Service
public class HelloWorldServiceImpl implements HelloWorldService {
    @Override
    public String helloWorld(String name) {
        System.out.println("Method Called with parameter = " + name);
        if (name != null) {
            return "Hello " + name;
        } else {
            return "Hello World";
        }
    }
}


File ini merupakan file implements dari file HelloWorldService.java, dalam file ini fungsi helloWorld di proses sebagai sebuah fungsi yang memiliki kembalian berupa String "Hello " + parameter, jika tidak ada paramater yang di suplai ketika mengakses fungsi tersebut, maka ia hanya akan mengembalikan String "Hello World".
Dua file diatas adalah file-file yang menjadi inti dari aplikasi server project kita ini, tinggal langkah selanjutnya adalah membungkus dua file ini menjadi remotable (bisa di remote) oleh aplikasi client dari luar aplikasi ini sendiri. Cara membungkusnya adalah dengan memberikan deklarasi Spring bean pada Spring Config yang ada, dalam hal ini adalah file serverApplicationContext.xml. Dibawah ini isi dari file Spring Config tersebut:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans      
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="helloWorldService" class="org.josescalia.springremote.service.HelloWorldServiceImpl"/>
    <bean name="/remote/HelloWorld.http" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="helloWorldService"/>
        <property name="serviceInterface" value="org.josescalia.springremote.service.HelloWorldService"/>
    </bean>

</beans>


Mari kita perhatikan bean-bean yang ada dalam deklarasi Spring config di atas, class HelloWorldServiceImpl di register sebagai bean dengan nama "helloWorldService". Kemudian ada bean lain bernama "/remote/HelloWorld.http", bean ini adalah sebuah bean URL yang bisa dipanggil melalui protokol HTTP karena class-nya adalah class HttpInvokerServiceExporter milik Spring framework. Class ini memiliki 2 buah properti yang harus di isi, properti pertama bernama service, properti inilah yang kita gunakan untuk mereferensikan bean helloWorlService yang diatasnya, kemudian properti yang kedua adalah serviceInterface, properti ini harus kita isi dengan nilai yang merupakan interface dari bean yang akan kita remote dalam hal ini  adalah interface HelloWorldService.
Oleh karena aplikasi yang kita buat ini menggunakan protokol HTTP sebagai media container-nya maka sudah barang tentu kita akan membuatkan deployment descriptor agar nantinya bisa di-deploy ke dalam application server seperti tomcat, jetty atau yang lainnya. Sekarang mari kita lihat deployment descriptor untuk aplikasi ini, perhatikan file web.xml dibawah ini:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <display-name>Spring Remote Using Http Invoker</display-name>
    <servlet>
        <servlet-name>spring-remote-http-invoker</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:serverApplicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-remote-http-invoker</servlet-name>
        <url-pattern>*.http</url-pattern>
    </servlet-mapping>
</web-app>


Yap, file diatas adalah sebuah deployment descriptor yang memanfaatkan Spring Framework sebagai dispatcher servlet-nya, sehingga semua request yang ber-ekstensi .http akan di-forward ke dalam Spring Bean management.
Sampai disini aplikasi server yang remotable (bisa di remote) kita sudah selesai silahkan deploy aplikasi tersebut ke dalam web-container favorit anda, oleh karena saya menggunakan maven, maka saya mengintegrasikan jetty-server sebagai  servlet container-nya berikut ini screenshot ketika aplikasi tersebut berjalan diatas jetty:
Yes, our server application run smooth on jetty server. Sekarang mari kita lihat code aplikasi client side yang sudah saya buat sebelumnya, perhatikan source-code dibawah ini:
package org.josescalia.springremote.client;

import org.josescalia.springremote.service.HelloWorldService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloWorldClient {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-client.xml");
        HelloWorldService service = (HelloWorldService) context.getBean("helloWorldService");
        String fromServer = service.helloWorld("MOJO");
        System.out.println("Text From Server : " + fromServer);
    }
}
Ok, aplikasi client side ini sangat sederhana, yaitu mencoba memanggil fungsi helloWorld yang ada pada interface HelloWorldService dengan paramater nama saya :P. Yang dilakukan pertama kali pada aplikasi ini adalah me-register ApplicationContext dengan mengambil file spring-client.xml sebagai referensi ClassPathXmlApplicationContext-nya, kemudian dari context tersebut didaftarkan service yang bisa digunakan. langkah selanjutnya adalah meng-invoke method helloWorld yang ada dalam service tersebut dengan paramater yang di suplai.
Agar aplikasi client ini mengetahui dimana letak service yang ter-ekspose dalam jaringan yang ada, maka kita harus mengkonfigurasi lagi Spring Bean yang akan digunakan oleh aplikasi client ini, perhatikan Spring bean berikut ini.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloWorldService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8080/remote/HelloWorld.http"/>
        <property name="serviceInterface" value="org.josescalia.springremote.service.HelloWorldService"/>
    </bean>
</beans>

Dari konfigurasi Spring Config di atas kita bisa melihat bahwa bean "helloWorldService" bisa diakses di alamat : http://localhost:8080/remote/HelloWorld.http, sehingga nanti jika aplikasi client ini dijalankan maka target yang di tuju tidak akan nyasar-nyasar,:P. Satu hal yang harus kita perhatikan, URL yang dituju pada konfigurasi client side ini harus sama dengan URL yang kita konfgurasi pada sisi server sebelumnya.
Setelah itu mari kita jalankan aplikasi client side ini dan perhatikan apa yang terjadi pada sisi client dan pada sisi server. Berikut screenshot yang saya ambil dari eksekusi aplikasi client  tersebut:
Client Side Application:
Server Side Application:
Demikianlah percobaan kita kali ini, dalam pemanfaatanya tentu saja bisa lebih luas dari apa yang kita lakukan disini, misal kita bisa membuat aplikasi client-nya yang merupakan Java GUI dengan Swing Framework dan aplikasi server side-nya yang bisa kita integrasikan dengan hibernate framework sebagai aplikasi J2EE.
Source code aplikasi ini bisa anda download dari sini.

Semoga bermanfaat

Menteng, 20 July 2013


Josescalia

No comments: