Configure WSO2 ESB with jms, accept message to ESB and persist to database

Required
WSO2 ESB 4.0.3
Activemq-5.6.0

Steps
Download ActiveMQ from here http://activemq.apache.org/
Download WSO2 ESB from here http://wso2.com/products/enterprise-service-bus/
Download Mysql and connector jars from http://dev.mysql.com/downloads/
Setup ActiveMQ
Extract ActiveMQ to /opt folder
/opt/apache-activemq-5.6.0
run activeMQ using type command /opt/apache-activemq-5.6.0/bin/activemq

Setup WSO2 ESB
First we need to copy following activeMQ jars available in /opt/apache-activemq-5.6.0/lib into repository/lib folder of ESB distribution home. From here onwards i will refer that place as ESB_HOME.

Copy these 2 jars
geronimo-j2ee-management_1.1_spec-1.0.1.jar
activemq-core-5.6.0.jar

Since we are using mysql database download and copy mysql jar as well
mysql-connector-java-5.1.12-bin.jar

Now we need to configure jms transport from ESB. open ESB_HOME/repository/conf/axis2.xml file and Enable jms transport receiver by uncommenting following section


<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
<parameter name="myTopicConnectionFactory" locked="false">
<parameter name="java.naming.factory.initial"
locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
<parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</
parameter>
<parameter name="transport.jms.ConnectionFactoryJNDIName"
locked="false">TopicConnectionFactory</parameter>
<parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</
parameter>
</parameter>
<parameter name="myQueueConnectionFactory" locked="false">
<parameter name="java.naming.factory.initial"
locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
<parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</
parameter>
<parameter name="transport.jms.ConnectionFactoryJNDIName"
locked="false">QueueConnectionFactory</parameter>
<parameter name="transport.jms.ConnectionFactoryType"
locked="false">queue</parameter>
</parameter>
<parameter name="default" locked="false">
<parameter name="java.naming.factory.initial"
locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
<parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</
parameter>
<parameter name="transport.jms.ConnectionFactoryJNDIName"
locked="false">QueueConnectionFactory</parameter>
<parameter name="transport.jms.ConnectionFactoryType"
locked="false">queue</parameter>
</parameter>
</transportReceiver>



Enable jms transport sender by uncomment following configuration

<transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>



So now we have enabled jms transport for WSO2 ESB.
Now we will define new proxy service to consume messages through jms transport. Create new proxy service as follows.





                    step5: edit out sequence(we don’t have to do anything here)

Now we have completed proxy service.Next we will see how to invoke this service.

First build sample
Go to ESB_HOME/samples/axis2Server/src/SimpleStockQuoteService
run ant command > ant
Next we have to start Axis2Service for that go to ESB/samples/axis2Server.
run command > sh axis2Server.sh

So now we have proxy service with following sub items
01.Log full message
02.Extract some parameter in message body using xpath expression
xmlns:m="http://services.samples"
xmlns:m0="http://schemas.xmlsoap.org/soap/envelope/" expression="//m0:Body/m:placeOrder/
m:order/m:symbol" type="VARCHAR"
03.Persist that parameter to database using db report mediator(We can write our own mediator
using class mediator to store message or part of it in any given store)
04.Send to some back end service or drop message(in this particular use case we can drop
message since we are not going to send it to actual back end anyway i have added that as well)
Here is the synapse configuration for proxy service.


<proxy name="StockQuoteProxy" transports="jms" startOnLoad="true" trace="disable">
<target>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
</endpoint>
<inSequence>
<log level="full"/>
<dbreport>
<connection>
<pool>
<password>root</password>
<user>root</user>
<url>jdbc:mysql://localhost/testdb</url>
<driver>com.mysql.jdbc.Driver</driver>
</pool>
</connection>
<statement>
<sql>call addmessage(?)</sql>
<parameter xmlns:m="http://services.samples" xmlns:m0="http://
schemas.xmlsoap.org/soap/envelope/" expression="//m0:Body/m:placeOrder/m:order/
m:symbol" type="VARCHAR"/>
</statement>
</dbreport>
<property name="OUT_ONLY" value="true"/>
</inSequence>
<outSequence><send/></outSequence>
</target>
<publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/xml</default>
</rules>
</parameter>
</proxy>

Create test_db and execute following commands to create table and stored procedure.
CREATE TABLE `testdb`.`messages` (
`message_id` int(10) NOT NULL AUTO_INCREMENT,
`message` text,
PRIMARY KEY (`message_id`)
) ENGINE=MyISAM AUTO_INCREMENT=44 DEFAULT CHARSET=latin1
CREATE DEFINER=`root`@`localhost` PROCEDURE `testdb`.`addmessage`(message_txt
VARCHAR(10))
INSERT INTO messages (message) values (message_txt)
Now we can invoke proxy service from the axis2 Client available inside wso2 ESB.
Goto ESB_HOME/samples/axis2Client and type following command.
>ant jmsclient -Djms_type=pox -Djms_dest=dynamicQueues/StockQuoteProxy -
Djms_payload=dddddd
So now you will see message log in ESB console and then persist extracted parameter to
database and message send to actual back end. If you want to drop message drop it from proxy
configuration.
ESB-log
=======
[2012-08-28 12:11:43,798] INFO - LogMediator To: http://localhost:9000/services/
SimpleStockQuoteService, WSAction: urn:placeOrder, SOAPAction: urn:placeOrder,
MessageID: urn:uuid:ed0de324-79eb-4101-9a0b-c201971910fd, Direction: request
To : http://localhost:9000/services/SimpleStockQuoteService
WSAction : urn:placeOrder
SOAPAction : urn:placeOrder
MessageID : urn:uuid:ed0de324-79eb-4101-9a0b-c201971910fd
Body : 70.25</
m0:price>200MSFT
</
m0:placeOrder>

[2012-08-28 12:11:43,801] INFO - PlaceStockOrderTask placed order symbol:MSFT
quantity:200 price:70.25
[2012-08-28 12:11:45,213] INFO - LogMediator To: , MessageID: ID:sanjeewa-TECRA-
M11-47367-1346181105012-1:1:1:1:1, Direction: request, Envelope: encoding='utf-8'?>

150.33783033599516
6095
MSFTddii
Actual axis2 backend log
==================
Tue Aug 28 12:11:45 PDT 2012 samples.services.SimpleStockQuoteService :: Accepted order
#76 for : 6095 stocks of MSFTddii at $ 150.33783033599516
Table entry in database
=================
If you go to database and see there will be entry for stock symbol you entered

How to move files between 2 folders using WSO2 ESB


In some deployments users may want to synch up files between folders.
With WSO2 ESB you can do this simply. Here in this example we will listen
to one folder and if you put some xml file in to that folder it will move it to some other location. Here you can see few parameters. Action should named as Move and you can define where we pick file and also output folder. Inside in sequence or out sequence you dont have to do anything. So we will keep them as it is and put drop tag there. See the complete configuration for file copy proxy below.

Also you have to enable vfs transport from axis2 xml. To do that go to repository/conf/axis2/axis2.xml file and and uncomment vfs transport tags.
There are two tags.

<proxy name="filetest" transports="vfs" startOnLoad="true" trace="disable">
        <target>
            <inSequence>
                <drop/>
            </inSequence>
            <outSequence>
                <drop/>
            </outSequence>
        </target>
<publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
<parameter name="transport.PollInterval">15</parameter>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.FileURI">file:///home/sanjeewa/test/in</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file:///home/sanjeewa/test/out</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file:///home/sanjeewa/test/original</parameter>
<parameter name="transport.vfs.FileNamePattern">.*.xml</parameter>
<parameter name="transport.vfs.ContentType">text/xml</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
</proxy>


How to disable chunking - WSO2 ESB Proxy service


Some times .Net back end services are not supporting chunked encoding. By default
when  ESB calls back end it assumes back end supports chunked encoding.
If your .Net back end service cannot access through proxy service you can try this.
Sometimes you may get empty response for the request due to this issue.
So what we have to do is add following 2 lines to in sequence



<property name="FORCE_HTTP_1.0" value="true" scope="axis2" />
 <property name="DISABLE_CHUNKING" value="true" scope="axis2" />
 
See the following complete proxy service configuration

<proxy xmlns="http://ws.apache.org/ns/synapse" name="IssueProxy" 
transports="https,http" statistics="disable" trace="disable" 
startOnLoad="true">
 <target>
  <inSequence>
   <property name="FORCE_HTTP_1.0" value="true" scope="axis2" />
   <property name="DISABLE_CHUNKING" value="true" scope="axis2" />
   <send>
     <endpoint>
       <address uri="http://192.168.1.216:3333/Service1.svc" />
      </endpoint>
   </send>
   </inSequence>
   <outSequence>
      <send />
   </outSequence>
   </target>
   <publishWSDL uri="http://192.168.1.216:3333/Service1.svc?wsdl" />
</proxy>

How to set revision number to svn external

Sometimes when we branched out from trunk we have to remove svn externals. Other possible solution is set branched revision number to external. so it will always referring that particular revision even externals got updated.

Command to get svn externals
svn propget svn:externals -R

Then you will see out put like this
modules/application - store-web  https://svn.test.org/repos/test/store-web



so first you have to go to that folder
cd modules/application

then you have to set the revision number as follows. Let say we branched from revision 11111. then we have to set to that version

svn propset svn:externals 'store-web -r11111 https://svn.test.org/repos/test/store-web' . property 'svn:externals' set on '.'

Then commit to svn branch.

How To install HAProxy Load Balancer on redhat


In my previous post i have described how to configure HAProxy load balancer on ubuntu. Here in this post i will describe how to do it on red-hat. Please make sure you are doing all this with necessary permissions for the your account.
01. Install HAProxy using following commands
wget http://haproxy.1wt.eu/download/1.2/src/haproxy-1.2.17.tar.gz
tar -zxf haproxy-1.2.17.tar.gz
cd haproxy-1.2.17
make
cp haproxy /usr/sbin/haproxy

02.Copy and edit config files
wget http://layer1.rack911.com/haproxy/haproxy-standard.cfg -O /etc/haproxy.cfg
wget http://layer1.rack911.com/haproxy/haproxy.init -O /etc/init.d/haproxy
chmod +x /etc/init.d/haproxy

03.Starting server
 sudo  /etc/init.d/haproxy start

04.restarting server after any changes
 sudo  /etc/init.d/haproxy restart

Use the same config file mentioned in earlier post of mine. After installation everything is 
same as ubuntu.

Setup HAProxy Load Balancer on Ubuntu

01. installing haproxy on ubuntu machine
sudo apt-get install haproxy

02. Edit configurations file
sudo vi /etc/haproxy/haproxy.cfg

Add following text to file and save it

global
maxconn 4096
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
contimeout
5000
clitimeout
50000
srvtimeout
50000
listen webcluster *:80
mode http
stats enable
stats auth us3r:passw0rd
balance roundrobin
option httpchk HEAD / HTTP/1.0
option forwardfor
cookie LSW_WEB insert
option httpclose
server web01 10.100.2.85:8280 cookie LSW_WEB01 check
server web02 10.100.2.85:8281 cookie LSW_WEB02 check
03. Setting startup parameter for HAProxy set enabled as 1 to start HAproxy
sudo vi /etc/default/haproxy

# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1

04. Start HAProxy form command line
sudo /etc/init.d/haproxy start

05. Restart HAProxy after any configuration change form command line
sudo /etc/init.d/haproxy restart

06. Start 2 ESB servers (Set HTTP port as 8280 and 8281) and with default configurations

07. Access Web user interface from browser
Type following url in browser and provide stat credentials you provided in configurations file(haproxy.cfg)

http://10.100.2.85:80/haproxy?stats

You will see following User interface.




08. Access ESB from browser or send requests to following url
http://10.100.2.85:80/services/echo?wsdl


Following Diagram shows you how this laod balancer works.


Tenant Aware Load balancer

Tenant Aware Load Balancer is the upcoming Load Balancer from WSO2. Here in this article i will briefly describe it's architecture and how it works. 

Introduction
 
LoadBalancer
Load balancing is a key concern in a Platform-as-a-Service (PaaS) or a middleware platform deployed on the Cloud.
The primary functionality of a load balancer is to distribute the load of the incoming traffic amongst a set of back end worker nodes. This set of worker nodes can be either statically configured or can be dynamically discovered. In WSO2 carbon based products we use cluster messages which based on axis2 clustering to identify the node join to cluster or leave cluster.

Multi-tenancy - Tenant-aware Load Balancing
If a Cloud deployment has to be able to scale to thousands, hundreds of thousands or millions of tenants, we need tenant-partitioning. This means, for a single Cloud service, there will be multiple clusters, and each of these Service clusters will handle a subset of the tenants in the system. Creating dynamic tenant clusters & tenant partitioning strategies are some of the ongoing research areas. In such a tenant-partitioned deployment, the load balancers themselves need to be tenant-aware, in order to be able to route the requests to the proper tenant clusters. This means the load balancer has to be tenant-aware as well as Service-aware, since it is the Service clusters that are partitioned according to the tenants. WSO2 Load Balancer is now capable of routing messages in both tenant aware and service aware way.

How WSO2 Tenant Aware Load Balancer Works
Load Balancer's task is to distribute the load of the incoming traffic amongst a set of back end worker nodes.
We will see how this works now.
when the request comes in to Load Balancer we have to identify host header and determine cluster domain
Eg: Host header = https://appserver.cloud-test.wso2.com/t/ttt.ttt/carbon/admin/login.jsp
Service domain is appserver domain
Then determine tenant Id from the url. Here tenant domain is ttt.ttt so we can determine tenant domain.
These parameters can extract from host header.
Now we have both service domain and tenant domain. so with both of them we can direct this request to correct cluster as we defined in loadbalancer.conf. There we can configure services with their cluster domains and tenant ranges. When load balancer loads it picks those ranges and cluster domains.

See the following sample configuration . You can find those configuration under the “repository/conf” folder. There you will find loadbalancer.conf file.
appserver {
# multiple hosts should be separated by a comma.
hosts appserver.cloud-test.wso2.com;
domains {
wso2.as1.domain {
tenant_range 1-100;
}
wso2.as.domain {
tenant_range *;
}
}
}

Let’s examine this configuration.
Above configuration is for Application service with two service clusters. Let’s examine it line by line.
First line says appserver is the main node of this configurations.
In next line you will find hosts entries. There we have to add host address that maps to application server service. If you need to add multiple service domains add it with separated by commas.
Next you will find domains there you will find two domains with pre defined tenant ranges.
wso2.as1.domain named cluster is responsible for load tenants with tenant id 1 to 100
wso2.as.domain named cluster is responsible for load tenants with all tenants except the tenants belong to above range.
Then it can forward request to correct cluster based on service domain and tenant domain.

 
How Load Balance End Point works
For load balancing we are using synapse end point as a end point to determine how message should forward. So here we have defined external end point which is named as Tenant Aware Load Balance End point. It has logic to forward messages to correct back end node. We can define loadbalance end point in synapse main sequence.

In order to do this you have to change main sequence with correct load balance end point. If you need to implement your own custom load balancing implementation you can write your own end point and configure load balancer to use it.
 As an example we can load balance based on any other parameter which is available in request header (something similar to tenant domain). It's simple and straightforward.

See the following diagram to get general idea on how it works.


Advantages and other features of WSO2 Tenant Aware Load Balancer
  • Tenants are loaded in demand to the pre defined cluster based on the configurations in loadbalancer.conf.
  • Unload unused tenants after paticular predefined time.
  • Tenant Partitioning
  • Tenant may have multiple service clusters
  • Tenants will define the partitions.
  • When a new instance added, notify the LB instances.
  • Auto scaling - starting and terminating of instances based on the load. This supports any type of infrastructure as a service. What we have to do is write simple adapter to auto-scaler service based on the service vendor's API. It’s straight forward and simple. External components Autoscaler service can add, assign nodes into LB. So load Balancer is independent from the infrastructure that we are using.
  • Group communication between clusters using cluster messages.
  • Notifying all the load balancers when a new node is added to cluster.
  • Data partitioning(tenants data) - we can use this design to data partitioning based on the Geography or any other factors. As an example if we decide tenant 1 to 100 should loaded and store their data on United state we can deploy new application cluster at united states and inform it to loadbalancer. So we have to add configuration to loadbalancer.conf file saying tenant 1 to 100 are loaded at particular cluster(named as wso2.as.usa.domain). Then all requests come to the tenant 1 to 100 will forward to that cluster. so all data related to those tenants (Application files, databases) will stored at united state servers.
  • Private jet mode - Also we can assign some particular application cluster to specific tenant. Its like private jet. If you are willing to pay for entire cluster we can assign entire cluster for your tenant. This is again we can do using configurations at loadbalancer.conf file. So all request comes to that tenant will forward to that particular cluster.
  • Always running an additional cluster(Default cluster) to quickly load new tenant. This cluster is responsible for all newly created tenants in the system and super admin tenant. We can define this cluster in load balancer configuration file with * mark as upper tenant ID.  

After next release of WSO2 Load Balancer you will be able to use all above mentioned functionalities. Please visit  http://wso2.org/projects/load-balancer










Empowering the Future of API Management: Unveiling the Journey of WSO2 API Platform for Kubernetes (APK) Project and the Anticipated Alpha Release

  Introduction In the ever-evolving realm of API management, our journey embarked on the APK project eight months ago, and now, with great a...