Tuesday, October 16, 2012

How to Create Web Service Proxy in ESB

We will be using WSO2 ESB as our enterprise service bus. We're using WSO2 ESB because of its simplicity and even eBay uses it to process their transactions which is over 1 billion transaction a day. And most of all, its open source.

You can read all about their features from the website. http://wso2.com/products/enterprise-service-bus/ 

Installation & Running
==================================
1. Extract the wso2esb-4.0.2.zip and go to the extracted directory
2. Run the wso2server.sh or wso2server.bat as appropriate

Wait until you got to this sentence :

INFO - StartupFinalizerServiceComponent WSO2 Carbon started in 

3. Point your favourite browser to



4. Use the following username and password to login

    username : admin
    password : admin


5. Click on the left menu : Manage  Web Services  Add  Proxy Service.


6. Select WSDL Based Proxy.



Copy our WSDL URI that we have created before. 
If your confuse about the WSDL Service and Port, Don’t be !
Just open the browser and open our WSDL URI once again, and scroll down to the bottom and you will have your answers.




Next just make sure you select the Publish Same Service Contract option, and we're done. Click Create.



Congratulations, you just create a Web Service Proxy on ESB.



We were given TWO services address by the ESB, 

Now lets get back to our Deployed Service page, and click our service the HrmsService .






And Click on Security.




Lets choose the Advance Scenario Number 8. You can always choose other Security Scenario, and see how that works for you.


Number 8 requires a Username and a certificate to be available. Lets just use what is already available in WSO2 ESB.


Click Finish.



Congratulations. We now have a secured Web Service handled completely by the ESB.





Monday, October 15, 2012

Prolog to Enterprise Service Bus [In Bahasa]


Kompleksitas IT telah meningkat secara siginifikan dalam kurun waktu 20 tahun ini, dengan makin banyaknya aplikasi baru yang hadir dan di-implementasikan dalam organisasi untuk menciptakan efisiensi dalam departemen, core business, dan back office. Trend ini akan terus berlanjut untuk tahun-tahun berikutnya karena makin banyaknya aplikasi dan metodologi baru yang hadir, ditambah lagi dengan  mulai maraknya Enterprise Aplication yang telah banyak diadopsi oleh banyak Perusahaan.

Banyak perusahaan sekarang menghadapi tantangan besar untuk me-manage data secara efektif  untuk memastikan orang yang tepat memiliki akses terhadap informasi yang dibutuhkan kapanpun mereka membutuhkannya. 

Hal ini mengakibatkan tingginya permintaan terhadap integrasi data real-time intra-departemen, antar system dan antara lokasi kantor yang berbeda.

Seringkali permintaan "SEDERHANA" dari Business Owners terhadap Informasi tepat guna dalam kenyataannya lebih kompleks karena back-end system yang saling terkait satu sama lain dan aplikasi existing yang sulit untuk di-trace juntrungannya.


Application to Application (A2A) dan Business to Business (B2B) integration

Enterprise Application Integration (EAI) dan Message Oriented Middleware (MOM / middleware) adalah tools yang umumnya digunakan untuk memfasilitasi A2A dan B2B integration. Tools ini umumnya berupa adapters, transformation logic dan reliable messaging modules di core framework-nya.

  • Adapters : Adapters umumnya digunakan sebagai sarana untuk pertukaran informasi dengan aplikasi bisnis seperti SAP atau PeopleSoft, tapi bisa juga digunakan untuk berkomunikasi melalui protokol seperti TCPIP atau dengan bisnis aplikasi lain dengan perantara XML
  • Transformation logic : Digunakan untuk mengubah tipe informasi yang bisa dibaca oleh satu system menjadi tipe format berbeda yang bisa dimengerti system lain.
  • Messaging : Kunci untuk solusi integrasi adalah messaging yang cepat dan dapat diandalkan. Contoh messaging : JMS, TIBCO, etc.

Notes: Messaging hanya mensupport SOAP-based web service, dan tidak mensupport format HTTP GET/POST, REST, dll. Itulah sebab kenapa kita pertama-tama harus dapat menguasai SOAP web service.

Service Oriented Architecture (SOA) dan Enterprise Service Bus (ESB) integration

Service Oriented Architecture (SOA) adalah sebuah himpunan dari design principles (ada beberapa design principle, bukan cuma satu) yang digunakan dalan systems development dan integration. SOA muncul karena banyaknya inefficiencies dari implementasi yang menggunakan arsitektur point-to-point atau arsitektur hub-and-spoke.

P2P / Hub and Spoke

Arsitektur P2P dan hub and spoke akan melumpuhkan bisnis karena setiap perubahan memerlukan effort yang luar biasa dan resiko yang tidak kalah besarnya.


Dengan makin banyaknya pendatang baru dalam enterprise integration dengan membawa tools SOA masing-masing. SOA kini digadang-gadang sebagai "future architecture for enterprise integration" dan "significant business value" dapat direalisasikan dari implementasi SOA asalkan di-deliver secara benar.

SOA dapat secara tepat mengexpose functionality dari aplikasi kita sebagai services, memungkinkan kita untuk mengorkestrasikan workflow processes lintas system yang berbeda. Enterprise Service Bus (ESB) adalah platform yang umum digunakan dalam merealisasikan SOA. ESB mem-provides functionality untuk messaging, complex event processing, management, routing dan mediation.

SOA / ESB

Enterprise service bus mengurangi redundansi dan tight coupling diantara system yang berbeda, sehingga secara drastis mengurangi resiko dan memungkinkan reuseability secara signifikan.


Skenario ESB bagi programmer

Implementasi yang umumnya digunakan sekarang adalah P2P. Setiap aplikasi (misalnya portals.) akan mendefine system apa saja yang harus digunakan, data apa yang harus diterima dan dikirim, validasi user diambil dari database mana, transaksi log-nya akan disimpan di system mana, dan lain sebagainya. Dan itu hanya dari satu aplikasi, coba lakukan untuk aplikasi yang lain. Proses yang sama pastinya akan berulang.

Sehingga kalo kita melihat secara global, untuk semua aplikasi, hasilnya adalah keruwetan luar biasa seperti yang kita lihat pada gambar diatas (sebelum Enterprise service bus).

Jika kita menggunakan SOA, dengan ESB sebagai platformnya, maka caranya akan sedikit berbeda. Coba lihat gambar diatas. Panah diatas mewakili Web Service. Setiap aplikasi akan melakukan pemanggilan ke web service dan sebaliknya akan dipanggil oleh aplikasi lain melalui web service.

Semua functionality akan terpusat di ESB, sehingga kita hanya harus memanage semua functionality kita (Web service) dari Web Admin ESB. Dalam ESB, kita bisa mengassign user siapa saja yang bisa mengakses web service, memberikan security berupa data encryption dalam SOAP XML datanya, dll. Lebih lanjut bisa dibaca standarisasi SOA di https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=soa-blueprints

Karena semua functionality kita terpusat di ESB, semua pemanggilan akan melalui ESB, sehingga kita harus meningkatkan performance dari Web traffic-nya. Disini, kita memerlukan Load Balancing dan Failover strategy seperti yang kita sudah bahas sebelumnya.

Mudah-mudahan bisa memberikan pencerahan.



Sunday, October 14, 2012

How to Load Balancing and Failover with Apache/Tomcat


Front-ending Apache Tomcat with Apache Web Server is sometimes thought to improve performance. However, performance of Tomcat standalone has already been known to be very good. So why add  Apache web server in front of it? – the answer is scalability and maintenance. Front-ending Tomcat with such web servers allows you to add more instances in case of increased load and also bring down instances for maintenance/upgrades.

These solutions provides high scalability, high availability, and good load balancing capabilities that are comparable with any other software solution. 
In order to get this done, you’ll need Apache 2.2, Tomcat 6 or 7, and the MOD_JK connector library.

Also, you’ll need to have a Java JDK installed, and your JAVA_HOME pointing to it. Make sure your PATH contains %JAVA_HOME%/bin.

  1. Install Apache 2.2. With this configuration.


  2. Copy the mod_jk-1.2.28-httpd-2.2.3.so file to your Apache/modules directory.
  3. Add the following to your apache/conf/httpd.conf

    LoadModule jk_module modules/mod_jk-1.2.28-httpd-2.2.3.so

    JkWorkersFile conf/workers.properties
    JkLogFile logs/jk.log
    JkLogLevel debug

    JkMount /* router
    JkMount /jk_status status

  4. Create a file, name it workers.properties in your Apache/conf directory. The file should contain the following:

    worker.list=router,status

    worker.worker1.port=8109
    worker.worker1.host=localhost
    worker.worker1.type=ajp13
    worker.worker1.lbfactor=1
    worker.worker1.local_worker=1
    worker.worker1.sticky_session=0

    worker.worker2.port=8209
    worker.worker2.host=localhost
    worker.worker2.type=ajp13
    worker.worker2.lbfactor=1
    worker.worker2.local_worker=0
    worker.worker2.sticky_session=0

    worker.worker3.port=8309
    worker.worker3.host=localhost
    worker.worker3.type=ajp13
    worker.worker3.lbfactor=1
    worker.worker3.local_worker=0
    worker.worker3.sticky_session=0

    worker.router.type=lb
    worker.router.balanced_workers=worker1,worker2,worker3
    worker.router.local_worker_only=1
    worker.status.type=status


  5. Extract the Tomcat 6 or 7 installation ZIP archive to three different directories, as we’re going to load balance three instances of Tomcat.


  6. Replace the server.xml file in each of the Tomcat conf/ directories with the following:

    <Server port="8100" shutdown="SHUTDOWN">

    <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
    type="org.apache.catalina.UserDatabase"
    description="User database that can be updated and saved"
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>

    <Service name="Catalina">
    <Connector port="8180" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

    <!-- Define an AJP 1.3 Connector -->
    <Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>

    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
    channelSendOptions="8">

    <Manager className="org.apache.catalina.ha.session.DeltaManager"
    expireSessionsOnShutdown="false"
    notifyListenersOnReplication="true"/>

    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
    <Membership className="org.apache.catalina.tribes.membership.McastService"
    address="228.0.0.4"
    port="45564"
    frequency="500"
    dropTime="3000"/>

    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
    address="auto"
    port="4000"
    autoBind="100"
    selectorTimeout="5000"
    maxThreads="6"/>

    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
    <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
    </Sender>

    <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
    </Channel>

    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
    tempDir="/tmp/war-temp/"
    deployDir="/tmp/war-deploy/"
    watchDir="/tmp/war-listen/"
    watchEnabled="false"/>

    <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
    </Cluster>
    </Host>
    </Engine>
    </Service>
    </Server>

    Looking into the XML above, there are three ports we’re concerned with: 8100, 8180, and 8109. These are the server, HTTP, and AJP13 ports, respectively. We’ll need each instance of Tomcat to run on it’s own ports. So, you can use this file as is in your first folder containing Tomcat, however, you’ll need to change the port numbers to: 8200, 8280, and 8209 for you 2nd installation. The third installation will use the ports, 8300, 8380, and 8309.



  7. Start (or Restart) Apache 2.2
  8. Start each instance of Tomcat (use the startup.bat script in the Tomcat /bin directory) – you should see no errors.
  9. Verify each Tomcat is working by opening a browser window to each Tomcat instance – if you’ve followed my instructions, the links are: 
  10. If Tomcat started correctly, start Apache 2.2. You should be able to access the Tomcat example pages via the following URL: 
  11. You’re done. Using my configuration, you can access a page to control the JK connector here:

    I’d recommending hiding and protecting this should you want to put this configuration into production. 

  12. Try experimenting with the configuration by stopping instance of Tomcat… as long as one instance of Tomcat is running, you should be able to see the examples.
  13. Now lets deploy, our web service that we just made before. Hrms.war
  14. Just put the war into TOMCAT_HOME\webapps.
  15. Start (or Restart) Apache 2.2
  16. Start each instance of Tomcat (use the startup.bat script in the Tomcat /bin directory) – you should see no errors.
  17. Verify each tomcat instance is working : 

  18. Now open the apache instance via the following URL : 




Conclusions

We have succeeded in creating a solution that provides high scalability, high availability, and good load balancing capabilities for our web services. For every request to our Apache Server, the load will be divided between the node server available (Tomcat instance). Even if one or more node server is down, as long as there is one node still running, the request will be responded by Apache. That is the true meaning of High Scalability and High Availability.

Monday, October 8, 2012

How to create a SOAP Web Services with Apache CXF


Create new Dynamic Web Project


Choose Dynamic web module version to 2.5, and Configuration template to CFX Web Services Project v2.5. And click Modify (If you haven't already)






Make sure you already download Apache CXF and extract it in your favorite folder. Manage your Apache CXF Configuration, and locate it to your Apache CXF location.


Click Configure installed runtime.. And click Add. Browse to your copy of Apache CXF runtime.



Click OK and Finish.



  
Project structure generated by Eclipse.



Now, Lets start by modifying the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
          <display-name>HrmsWS</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/company/hr/service/cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
 Then we create our employee object, Employee.java, in package com.company.hr.bean
package com.company.hr.bean;

import java.io.Serializable;
import java.util.Set;

public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String gid;
private String lastName;
private String firstName;
private Set<String> privileges;
public Employee() {}
public Set<String> getPrivileges() {
return privileges;
}
public void setPrivileges(Set<String> privileges) {
this.privileges = privileges;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getGid() {
return gid;
}
public void setGid(String gid) {
this.gid = gid;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public boolean isUserInRole(String role) {
if(privileges == null) { return false; }
else { return privileges.contains(role); }
}
}
Lets assume we have a Data Access Object, EmployeeDAO.java, we can always replace this with an actual access to database. Put this in package com.company.hr.dao.
package com.company.hr.dao;

import com.company.hr.bean.Employee;

public class EmployeeDAO
{
public EmployeeDAO() {
// TODO Auto-generated constructor stub
}
public Employee getEmployee(String gid)
{
Employee bleh = new Employee(); // from database or SAP
bleh.setFirstName("Panji");
bleh.setLastName("Pratomo");
return bleh;
}
}

Next we create an interface that will be accessed by the SOAP Web services, HrmsService.java. Lets put it in com.company.hr.service. The @WebService is a declaration to be used by SOAP WSDL, the @WebParam will maintain the parameter name in WSDL the same as the parameter name in java interface.

package com.company.hr.service;

import java.util.List;
import javax.jws.WebService;
import javax.jws.WebParam;
import com.company.hr.bean.Employee;

@WebService
public interface HrmsService {
Employee getEmployee(@WebParam(name="gid") String gid);
List<Employee> getAllEmployee(@WebParam(name="status") String status);
}

Then we need a class for implementing the interface above, HrmsServiceImpl.java, lets put it in the same package as HrmsService,  com.company.hr.service.
The @WebService require the definition of an EndPointInterface and ServiceName. This will define the WSDL contract for our purposes.

package com.company.hr.service;

import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.company.hr.bean.Employee;
import com.company.hr.dao.EmployeeDAO;

@WebService(endpointInterface = "com.company.hr.service.HrmsService", serviceName = "hrmsService")
public class HrmsServiceImpl implements HrmsService {
public Employee getEmployee(String gid) {
EmployeeDAO dao = new EmployeeDAO();
return dao.getEmployee(gid);
}

public List<Employee> getAllEmployee(String status) {
List<Employee> employees = new ArrayList<Employee>();
Employee emp1 = new Employee();
emp1.setFirstName("Panji");
emp1.setLastName("Pratomo");
Employee emp2 = new Employee();
emp2.setFirstName("Fahmi");
emp2.setLastName("Satrio");
Employee emp3 = new Employee();
emp3.setFirstName("Said");
emp3.setLastName("Hafiz");
employees.add(emp1);
employees.add(emp2);
employees.add(emp3);
return employees;
}
}

Next, we will need to manage our CXF configuration, cxf.xml, lets put this configuration file in the same package as HrmsService, com.company.hr.service.
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns:jaxws="http://cxf.apache.org/jaxws" 
xmlns:clustering="http://cxf.apache.org/clustering"  
xmlns:cxf="http://cxf.apache.org/core"  
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/clustering http://cxf.apache.org/schemas/clustering.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd 
-->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="authEnd"
implementor="com.company.hr.service.HrmsServiceImpl" 
address="/hrmsService" >
</jaxws:endpoint>
<!-- ONLY USE THIS IN DEVELOPMENT -->
<bean id="abstractLoggingInterceptor" abstract="true">
   <property name="prettyLogging" value="true"/>
</bean>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" parent="abstractLoggingInterceptor"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" parent="abstractLoggingInterceptor"/>
 
<cxf:bus>
   <cxf:inInterceptors>
       <ref bean="loggingInInterceptor"/>
   </cxf:inInterceptors>
   <cxf:outInterceptors>
       <ref bean="loggingOutInterceptor"/>
   </cxf:outInterceptors>
   <cxf:outFaultInterceptors>
       <ref bean="loggingOutInterceptor"/>
   </cxf:outFaultInterceptors>
   <cxf:inFaultInterceptors>
       <ref bean="loggingInInterceptor"/>
   </cxf:inFaultInterceptors>
</cxf:bus>
<!-- ONLY USE THIS IN DEVELOPMENT -->
</beans>

The structure of the project would look like this,



Thats it, now we are ready to try our web service. Type the URL :
http://localhost:8080/Hrms/services/hrmsService?WSDL

The Hrms is the name of your project (If you have different project name, change accordingly), the /services/ comes from servlet settings in your web.xml, the hrmsService is your WSDL contract that you define previously in interface HrmsService.


Congratulations, you have created a SOAP Web service using Apache Cxf.

Next time, once I got the time, I will try to cover all about Enterprise Service Bus from one of Open Source products.

Why open source?

Because I dont have time to install WebSphere or Oracle SOA Suite.