Sunday, November 3, 2013

REST service aggregator di WSO2 ESB


Sekilas tentang ESB (Enterprise Service Bus)

Enterprise Service Bus  adalah sebuah platform integrasi berbasisstandar yang mengabungkan pesan, layanan web, transformasi data dan routing cerdas untuk menghubungkdan dan mengkoordinasikan interaksi sejumlah aplikasi yang beragam di suatu perusahaan dengan integritas transaksional (Chappell, 2004). Dengan kata lain ESB merupakan infrastruktur untuk mengintegrasikan aplikasi dan layanan. ESB memperkuat SOA melalui pengurangan jumlah, ukuran dan kompleksitas interface antara aplikasi dan layanan-layanan.
(dikutip dari : wikipedia)

Tugas utama ESB adalah:
1. Memantau dan mengontrol routing pertukaran pesan antar layanan
2. Mengatasi konflik/ketidaksesuaian antar komponen layanan komunikasi
3. Mengontrol penyebaran dan versioning dari layanan
4. Penyusunan penggunaan servis redundant
5. Melayani jasa komoditas seperti penanganan event, transformasi data dan pemetaan, pesan dan event antrian serta penanganan, keamanan atau pengecualian penanganan, konversi protokol dan menguatkan kualitas layanan komunikasi yang tepat

Dalam tutorial kali ini kita akan menggunakan WSO2 ESB. ESB ini bersifat open source.  Mengenai detail dan keunggulan apa saja di software ini dapat dilihat di situsnya langsung di wso2.com

Tutorial kali ini akan khusus membahas bagaimana cara aggregasi 2 buah atau lebih Rest webservice menjadi 1 output Rest.

Pengantar Aggregator

The Aggregator menggabungkan hasil individu, pesan terkait sehingga mereka dapat diproses secara keseluruhan. Dia bekerja sebagai filter stateful, mengumpulkan dan menyimpan beberapa message individu menjadi satu set message yg utuh dan kemudian mengirimkannya. (http://www.eaipatterns.com/Aggregator.html)



Dari gambar diatas terlihat ada 3 service message yg terpisah (Inventory item 1, item 2, item 3). Oleh si Aggregator 3 message tersebut akan diAggregasi menjadi 1 service yakni Inventory Order

Kita langsung saja pada contohnya.

1. Download terlebih dahulu software WSO2 ESB (http://wso2.com/products/enterprise-service-bus/). Berbentuk file zip.
Ekstrak file zip tersebut, kemudian masuk ke direktori /bin.
Jalankan wso2server.bat (windows) atau wso2server.sh (Unix)

2.  Jalankan https://localhost:9443
Tampilannya seperti ini


Untuk login awal masukkan username : admin password : admin



3. Kita siapkan dulu Rest webservice nya.
Untuk cara paling mudah bisa menggunakan framework Spring MVC.
Untuk cara membuatnya akan saya bahas ditutorial berikutnya. ☺

Asumsinya sudah tersedia 2 buat Rest webservice :
http://localhost:8087/sample/students/get

saat dipanggil dibrowser outputnya seperti ini :

http://localhost:8088/sample/schools/getStudent


Kedua Rest diatas mempunyai element yg sama yakni ‘students’, tetapi isi datanya berbeda. Element inilah nanti yang akan diAggregasi
Syarat melakukan aggregasi, Rest nya harus memiliki element yg sama

4.  Kita buka kembali halaman console WSO2.
Kita kita pilih di menu utama -> Source View



Kemudian kita buat script service proxy sebagai berikut (misal namanya : StudentAggregateProxy) :

 <?xml version="1.0" encoding="UTF-8"?>  
 <proxy xmlns="http://ws.apache.org/ns/synapse"  
     name="StudentAggregateProxy"  
     transports="https,http"  
     statistics="disable"  
     trace="disable"  
     startOnLoad="true">  
   <target>  
    <inSequence>  
      <log level="full"/>  
      <clone>  
       <target>  
         <endpoint name="ReceiverA">  
          <address uri="http://localhost:8087/sample/students/get/" format="rest"/>  
         </endpoint>  
       </target>  
       <target>  
         <endpoint name="ReceiverB">  
          <address uri="http://localhost:8088/sample/schools/getStudent/" format="rest"/>  
         </endpoint>  
       </target>  
      </clone>  
    </inSequence>  
    <outSequence>  
      <aggregate>  
       <completeCondition>  
         <messageCount/>  
       </completeCondition>  
       <onComplete expression="//students">  
         <send/>  
       </onComplete>  
      </aggregate>  
    </outSequence>  
   </target>  
   <description/>  
 </proxy>  

Tambahkan script diatas ke source view. Kemudian update.

Pada inSequence kita melakukan clone masing masing target Rest endpoint.  
Pada outSequence (outputnya) kita melakukan aggregasi menggunakan tag <aggreagte>. Kemudian pada onComplete ditambahkan expression “//students”. Ini artinya element “students” dari masing masing output endpoint akan diAggregate (digabungkan)                      

5.  Maka service proxy akan otomatis ditambahkan.
Pilih menu Service -> list.
Maka service proxy “StudentAggregateProxy” akan muncul di listnya



Untuk mengedit service proxy yg kita sudah buat. Klik “Source View”



6.  Selanjutnya akan kita coba servicenya.
Kita panggil url : http://localhost:8280/services/StudentAggregateProxy/


di ouputnya terlihat data ‘students’ dari enpoint pertama dan kedua sudah digabungkan.

Sebenarnya masih banyak hal yang perlu diexplore tentang aggregasi ini, sebab masih ada kelemahannya. Misalnya salah satu endpoint sedang mati, maka service proxy nya tdk jalan atau error.
Jadi mari sama-sama kita pelajari :)

Terima kasih.
Selamat mencoba ☺

Create SOAP webservice di Spring MVC

Pada tutorial kali akan saya contohkan cara membuat webservice SOAP di Spring MVC.

Spring MVC defaultnya tidak menyediakan fungsi untuk SOAP webservice. Tetapi menyediakan fungsi untuk Rest webservice.
Untuk membuat Rest webservice SOAP kita cukup mendefinisikan Controller
Dan membuat method yang diberi annotasi @RequestMapping dan @ResponseBody.
Maka Rest webservice sudah jadi. Contoh codenya :


 @Controller  
 @RequestMapping("/students")  
 public class StudentController {  
   @Autowired  
   private StudentDao studentDao;       
   @RequestMapping(value="/getAll",method=RequestMethod.GET, produces = "application/json")  
   public @ResponseBody List<Student> getAll(){  
     return studentDao.getAll();  
   }  
 ...  

Nah bagaimana caranya membuat SOAP di spring mvc.
Langkah untuk membuat sample SAOP di spring mvc adalah sebagai berikut :

1.  Kita buat project berbasis framework spring mvc.
Kali ini saya pakai IDE intelIj, karena sudah ada plugin untuk spring mvc.
Tetapi bisa juga pakai Eclipse atau Netbeans, tergantung prefer kita saja.

Kita buat New Project -> pilih modul Spring MVC



Maka akan tercreate otomatis project spring mvc lengkap dengan dependency pom xml nya.




2.  Kita siapkan dulu class untuk domain, DAO, dan DTO (data transfer object)

Class Domain :


 package com.nostratech.sample.springmvc.soap.domain;  
 import java.io.Serializable;  
 public class Student implements Serializable {  
   private Integer id;  
   private String firstName;  
   private String lastName;  
   private String address;  
   public Student(){  
   }  
   public Student(Integer id, String firstName, String lastName, String address) {  
     this.id = id;  
     this.firstName = firstName;  
     this.lastName = lastName;  
     this.address = address;  
   }  
   public Integer getId() {  
     return id;  
   }  
   public void setId(Integer id) {  
     this.id = id;  
   }  
   public String getFirstName() {  
     return firstName;  
   }  
   public void setFirstName(String firstName) {  
     this.firstName = firstName;  
   }  
   public String getLastName() {  
     return lastName;  
   }  
   public void setLastName(String lastName) {  
     this.lastName = lastName;  
   }  
   public String getAddress() {  
     return address;  
   }  
   public void setAddress(String address) {  
     this.address = address;  
   }  
 }  

Class DAO :


 package com.nostratech.sample.springmvc.soap.dao;  
 import com.nostratech.sample.springmvc.soap.domain.Student;  
 import org.springframework.stereotype.Service;  
 import java.util.ArrayList;  
 import java.util.List;  
 @Service  
 public class StudentDao {  
   private List<Student> students = new ArrayList<Student>();  
   public List<Student> getListDataStudents(){  
     Student student1 = new Student(1,"andri","sasuke","jakarta");  
     Student student2 = new Student(1,"budi","santoso","jakarta");  
     students.add(student1);  
     students.add(student2);  
     return students;  
   }  
   public Student addStudent(Student student){  
     students.add(student);  
     return student;  
   }  
 }  

Class DTO :


 package com.nostratech.sample.springmvc.soap.vo;  
 import com.nostratech.sample.springmvc.soap.domain.Student;  
 import java.util.List;  
 public class ListStudentVO {  
   private List<Student> students;  
   public List<Student> getStudents() {  
     return students;  
   }  
   public void setStudents(List<Student> students) {  
     this.students = students;  
   }  
 }  


3.  Kita tambahkan dependency library webservice-rt dari java.metro.net di pom.xml
Library yg dipakai ini berbasis JAX-WS dan sudah support juga untuk transactional
    <dependency>  
       <groupId>com.sun.xml.ws</groupId>  
       <artifactId>webservices-rt</artifactId>  
       <version>2.1-b13</version>  
     </dependency>  


4.  Kemudian di web.xml nya kita tambahkan servlet-mapping untuk jax-ws


 <web-app version="2.4"  
      xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
      <display-name>Spring MVC Application</display-name>  
   <listener>  
     <listener-class>org.springframework.web.context.ContextLoaderListener  
     </listener-class>  
   </listener>  
   <servlet>  
     <servlet-name>appServlet</servlet-name>  
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
     <init-param>  
       <param-name>contextConfigLocation</param-name>  
       <param-value>/WEB-INF/applicationContext.xml</param-value>  
     </init-param>  
     <load-on-startup>1</load-on-startup>  
   </servlet>  
   <servlet-mapping>  
     <servlet-name>appServlet</servlet-name>  
     <url-pattern>/</url-pattern>  
   </servlet-mapping>  
   <!-- Jaxws - servlet -->  
   <servlet>  
     <servlet-name>jaxws-servlet</servlet-name>  
     <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>  
     <load-on-startup>2</load-on-startup>  
   </servlet>  
   <servlet-mapping>  
     <servlet-name>jaxws-servlet</servlet-name>  
     <url-pattern>/webservice/*</url-pattern>  
   </servlet-mapping>  
   <listener>  
     <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>  
   </listener>  
 </web-app>  



5.  Kita buat class untuk SOAP service nya.
kita tambahkan annotasi @WebService dan @SOAPBinding, agar class tersebut dikenali sebagai service.

 package com.nostratech.sample.springmvc.soap.service;  
 import com.nostratech.sample.springmvc.soap.dao.StudentDao;  
 import com.nostratech.sample.springmvc.soap.domain.Student;  
 import com.nostratech.sample.springmvc.soap.util.ApplicationContextUtils;  
 import com.nostratech.sample.springmvc.soap.vo.ListStudentVO;  
 import org.springframework.context.ApplicationContext;  
 import javax.jws.WebMethod;  
 import javax.jws.WebParam;  
 import javax.jws.WebService;  
 import javax.jws.soap.SOAPBinding;  
 import java.util.List;  
 @WebService(serviceName = "StudentService" , targetNamespace = "http://nostratech.com/")  
 @SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL)  
 public class StudentOperation {  
   private StudentDao studentDao;  
   @WebMethod(operationName="getListStudent")  
   public ListStudentVO getListStudent(){  
     ListStudentVO vo = new ListStudentVO();  
     vo.setStudents(getStudentDao().getListDataStudents());  
     return vo;  
   }  
   @WebMethod(operationName="addStudent")  
   public Student addStudent( @WebParam(name="student") Student student){  
     return getStudentDao().addStudent(student);  
   }  
   /*  
   * get student dao from appliaction context  
   */  
   private StudentDao getStudentDao(){  
     if(studentDao==null){  
       ApplicationContext appCtx = ApplicationContextUtils  
           .getApplicationContext();  
       studentDao = (StudentDao) appCtx.getBean("studentDao");  
     }  
     return studentDao;  
   }  
 }  


Kita perlu membuat juga class Util untuk mengambil class DAO yg diinject lewat applicatioContext. Karena di class service ini kita tidak bisa melakukan @Autowired seperti pada Controller spring mvc, jadi kita membutukan bantuan class util yg didaftarkan di ApplicationContext.

Class Util :


 package com.nostratech.sample.springmvc.soap.util;  
 import org.springframework.beans.BeansException;  
 import org.springframework.context.ApplicationContext;  
 import org.springframework.context.ApplicationContextAware;  
 public class ApplicationContextUtils implements ApplicationContextAware {  
  private static ApplicationContext ctx;  
  @Override  
  public void setApplicationContext(ApplicationContext appContext)  
    throws BeansException {  
   ctx = appContext;  
  }  
  public static ApplicationContext getApplicationContext() {  
   return ctx;  
  }  
 }  

ApplicationContext.xml :
 <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans"  
  xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"  
  xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd  
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">  
  <!-- Enable @Controller annotation support -->  
  <mvc:annotation-driven />  
  <!-- Map simple view name such as "test" into /WEB-INF/views/test.jsp -->  
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
   <property name="prefix" value="/WEB-INF/" />  
   <property name="suffix" value=".jsp" />  
  </bean>  
  <!-- Scan classpath for annotations (eg: @Service, @Repository etc) -->  
  <context:component-scan base-package="com.nostratech.sample.springmvc.soap"/>  
  <!-- application context util -->  
  <bean id="applicationContextUtils" class="com.nostratech.sample.springmvc.soap.util.ApplicationContextUtils" />  
 </beans>  



6.  Di folder WEB-INF kita buat file sun-jaxws.xml.
File ini berisi definisi class SOAP yg sudah kita buat dan mapping url nya.
Xml ini nantinya akan otomatis diload oleh web xml saat aplikasi start.

sun-jaxws.xml
 <?xml version="1.0" encoding="UTF-8"?>  
 <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://java.sun.com/xml/ns/jax-ws/ri/runtime http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/jaxws/sun-jaxws.xsd"  
      version="2.0">  
      <endpoint name="StudentOperation"  
           implementation="com.nostratech.sample.springmvc.soap.service.StudentOperation"  
           url-pattern="/webservice/student-service" />  
 </endpoints>  


7. Untuk start aplikasinya kita bisa gunakan mvn tomcat:run atau mvn jetty:run dari console. Bisa juga langsung dideploy ke application server.
Dari browser kita buka wsdl nya :  http://localhost:8088/sample/webservice/student-service?wsdl
“/webservice/student-service” adalah url-pattern yang didefinisikan di sun-jaxws.xml tadi.

Output wsdl :

 <definitions targetNamespace="http://nostratech.com/" name="StudentService">  
 <types>  
 <xsd:schema>  
 <xsd:import namespace="http://nostratech.com/" schemaLocation="http://localhost:8088/sample/webservice/student-service?xsd=1"/>  
 </xsd:schema>  
 </types>  
 <message name="addStudent">  
 <part name="student" type="tns:student"/>  
 </message>  
 <message name="addStudentResponse">  
 <part name="return" type="tns:student"/>  
 </message><message name="getListStudent"/>  
 <message name="getListStudentResponse">  
 <part name="return" type="tns:listStudentVO"/>  
 </message><portType name="StudentOperation">  
 <operation name="addStudent">  
 <input wsam:Action="http://nostratech.com/StudentOperation/addStudentRequest" message="tns:addStudent"/>  
 <output wsam:Action="http://nostratech.com/StudentOperation/addStudentResponse" message="tns:addStudentResponse"/>  
 </operation><operation name="getListStudent">  
 <input wsam:Action="http://nostratech.com/StudentOperation/getListStudentRequest" message="tns:getListStudent"/>  
 <output wsam:Action="http://nostratech.com/StudentOperation/getListStudentResponse" message="tns:getListStudentResponse"/>  
 </operation></portType><binding name="StudentOperationPortBinding" type="tns:StudentOperation">  
 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>  
 <operation name="addStudent"><soap:operation soapAction=""/>  
 <input>  
 <soap:body use="literal" namespace="http://nostratech.com/"/>  
 </input>  
 <output>  
 <soap:body use="literal" namespace="http://nostratech.com/"/>  
 </output>  
 </operation>  
 <operation name="getListStudent">  
 <soap:operation soapAction=""/>  
 <input>  
 <soap:body use="literal" namespace="http://nostratech.com/"/>  
 </input>  
 <output>  
 <soap:body use="literal" namespace="http://nostratech.com/"/>  
 </output>  
 </operation></binding><service name="StudentService">  
 <port name="StudentOperationPort" binding="tns:StudentOperationPortBinding">  
 <soap:address location="http://localhost:8088/sample/webservice/student-service"/>  
 </port>  
 </service>  
 </definitions>  


8.  Untuk mencoba SOAP webservice nya kita bisa gunakan SOAP-UI
Create project dari wsdl : http://localhost:8088/sample/webservice/student-service?wsdl


Kita coba jalankan service getListStudent()


9.  Sekian tutorial dari saya, mungkin next time bisa ditambahkan juga untuk akses ke database juga. Karena tutorial di atas masih menggunkan data yg hardcode.


Terima kasih.
Selamat mencoba. ☺