Showing posts with label WSO2 ESB. Show all posts
Showing posts with label WSO2 ESB. Show all posts

Saturday, May 11, 2013

The simplest possible way to simulate a backend service delay

When testing service integrations, we usually want to simulate the delayed responses from backend web services. For example, if you want to test how WSO2 ESB or Apache Synapse reacts when the backend service takes large amount of time for responding, there are many approaches to introduce delay to backend web service. I have observed that, most of the people modify the backend web services to add Thread.sleep() when they need to introduce a delay in service invocation.

If you are not testing the backend web service and just want to test the integration (e.g:- outgoing calls from ESB), I cannot think of a better solution than using soapUI mock services.

Step 1

 

Add a new mock service to soapUI project. This can be done at the time of creating the project or by selecting a particular interface (binding) of a wsdl based project.

Step 2

 

Select the mock service in soapUI navigator and open the mock service editor. In the mock service editor, select OnRequest script.










Step 3

 


Add the following groovy script inside the OnRequest Script editor to introduce 1 minute delay.

sleep(60000)

Now, send a request to the mock service. You will notice that all requests will respond back to the caller after 1 minute of delay.

Read chapter 6 (Web service simulation with soapUI) and 11 (Extending soapUI with Scripting) of Web Services Testing with soapUI book for more information about soapUI scripting capabilities.




Sunday, May 5, 2013

Testing one-way operations which do not return HTTP 202 responses

When you invoke a one-way (in-Only) operation of a web service over HTTP, it responds with HTTP 202 accepted message. Many web service clients such as soapUI or Jmeter waits till they receive a response from the web service.
Waiting for HTTP 202 response is always not desirable since there are situations where you do not even get a 202 response. For example, if you invoke one-way JMS operation, it does not send a reply back to the client.
Look at a scenario similar to the following.

A client sends a message over HTTP to a proxy service in WSO2 ESB. The proxy service places the message in a JMS queue and does not expect a response back. In this case, client does not even get a HTTP 202 response hence it waits and eventually timed out. This prevents you using the tools like soapUI, Apache Jmeter in these scenarios. How can we fix this so that the client always get a HTTP 202 response back?

Let's go through the procedure in detail.

Step 1:

Configure Apache ActiveMQ JMS broker with WSO2 ESB as explained here.

Step 2: 

Create a queue in ActiveMQ. You could access ActiveMQ console application through http://localhost:8161/admin and create a new queue. Name it as "onewaytest".

Step 3: 

Create a simple proxy service in WSO2 ESB as shown below. This proxy service just forwards the incoming SOAP messages into the "onewaytest" JMS queue which we have created in the previous step.

<proxy xmlns="http://ws.apache.org/ns/synapse" name="onewayProxy" transports="http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true"/>
<send>
<endpoint>
<address uri="jms:/onewaytest?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<description></description>
</proxy>


Step 4:


Use soapUI (or SOAP/XML-RPC sampler in Apache Jmeter) and send a SOAP request to the above proxy service. You will get "java.net.SocketTimeoutException: Read timed out" in soapUI log. This explains the behavior of HTTP client waiting for HTTP 202 response.

Step 5:


There is an useful property, FORCE_SC_ACCEPTED which can be used inside the inSequence of the proxy service to send HTTP 202 Accepted response back to the client in case of one-way JMS operations.

Add this property to the inSequence of the above proxy service.

<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2" />

Step 6:


Re-send a SOAP message to the proxy service using soapUI. You will get a HTTP 202 response.


HTTP/1.1 202 Accepted
Content-Type: text/xml; charset=UTF-8
Date: Sun, 05 May 2013 07:42:27 GMT
Server: WSO2-PassThrough-HTTP
Transfer-Encoding: chunked



Saturday, February 16, 2013

How to connect WSO2 ESB to Apache ActiveMQ using simple authentication

There are different types of pluggable authentication mechanisms provided by Apache ActiveMQ message broker. One of the quickest and easiest mechanisms is to use simple authentication. As the name implies, it is as simple as adding authentication details to ACTIVEMQ_HOME/conf/activemq-security.xml


 <plugins>
<!-- Configure authentication; Username, passwords and groups -->
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="system" password="${activemq.password}"
groups="users,admins"/>
<authenticationUser username="user" password="${guest.password}"
groups="users"/>
<authenticationUser username="guest" password="${guest.password}" groups="guests"/>
</users>
</simpleAuthenticationPlugin>


In this simple configuration, passwords of each user is defined in ACTIVEMQ_HOME/apache-activemq-5.7.0/conf/credential.properties file.


You can find more details about ActiveMQ simple authentication plugin in this blog.

Suppose, you have started Apache ActiveMQ with simple authentication. Then, any consumer of the destinations defined in your ActiveMQ broker should connect using the credentials defined under simple authentication plugin.

If WSO2 ESB needs to connect to ActiveMQ configured with simple authentication, we can simply update the broker configuration details in ESB_HOME/repository/conf/axis2/axis2.xml as shown below.

 <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.UserName">system</parameter>
<parameter name="transport.jms.Password">manager</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.UserName">system</parameter>
<parameter name="transport.jms.Password">manager</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.UserName">system</parameter>
<parameter name="transport.jms.Password">manager</parameter>

<parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
<parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
</parameter>
</transportReceiver>

Note that highlighted parameters (transport.jms.UserName and transport.jms.Password) which are used to connect to the broker using simple authentication.

The above configuration can be used to connect any Apache Axis2 based server (Apache Axis2, WSO2 Application Server etc..) to ActiveMQ using simple authentication.

Friday, February 8, 2013

How to preserve User-Agent HTTP header when messages passing through WSO2 ESB

When WSO2 ESB forwards a request to the back-end web service, ESB alters the User-Agent of the incoming request and sets it to Synapse-HttpComponent-NIO.

Suppose, you want to avoid this and preserve User-Agent header sent by client. You can simply do it using the following method.

Step 1

Open ESB_HOME/repository/conf/nhttp.properties file

Step 2

Add the following property and save nhttp.properties file.

http.user.agent.preserve=true


Step 3

Restart ESB and send a HTTP request to ESB. Monitor the HTTP traffic between ESB and the back-end web service. You will see the User-Agent value is not altered by ESB.

HTTP headers of the inbound request (client to ESB)

POST http://localhost:8280/services/Axis2Proxy HTTP/1.1

Accept-Encoding: gzip,deflate

Content-Type: text/xml;charset=UTF-8

SOAPAction: "urn:echoString"

User-Agent: Jakarta Commons-HttpClient/3.1

Host: localhost:8280

Content-Length: 299


HTTP headers of the outbound request (ESB to back-end service)

POST /services/Axis2Service HTTP/1.1

Content-Type: text/xml; charset=UTF-8

Accept-Encoding: gzip,deflate

User-Agent: Jakarta Commons-HttpClient/3.1

SOAPAction: "urn:echoString"

Transfer-Encoding: chunked

Host: 127.0.0.1:9765

Connection: Keep-Alive






Friday, January 25, 2013

How to disable HTTP Keep-Alive connections for all out-going requests in WSO2 ESB

By default, WSO2 ESB establishes HTTP Keep-Alive connection with the back-end web service. However, in some cases, we want to close connections just after using them specially when back-end server does not properly support Keep-Alive connections .
At individual proxy service or sequence level, you can add NO_KEEPALIVE property to disable Keep-Alive connection between ESB and backend web services.

<property name="NO_KEEPALIVE" value="true"
scope="axis2"/>

However, if you want to disable Keep-Alive connections globally for all message mediations, the above property will not be the solution.

In such cases, you can add the following parameter to ESB_HOME/repository/conf/nhttp.properties file.

http.connection.disable.keepalive=1

Saturday, January 12, 2013

JSON pass-through in WSO2 ESB

JSON is a lightweight data exchange format used in many web applications. WSO2 ESB supports sending and receiving JSON messages out-of-the-box. Exposing a SOAP web service over JSON is explained under sample 440 in WSO2 ESB official documentation. This post is to summarize steps of invoking a pass-through proxy service which accepts JSON request, forwards it to a RESTful service and reply back with JSON response (JSON-in, JSON-out).

Pre-requisite:

  • Download and extract the binary distribution of WSO2 ESB-4.5.1
  • I will use WSO2 Application Server-5.0.1 to deploy RESTful backend web service. You can use any server as the backend. However, in order to follow the steps mentioned in this post, you should use WSO2 Application server.

Step 1:

First, we need to setup the backend web service.  We will deploy a JAX-RS based restful service which consumes and produces JSON messages. You can download this RESTful web service(jaxrs_basic.war) from here.

Step 2:

Start WSO2 Application Server, log in to management console and navigate to Manage --> Applications --> List.
You will notice the web applications which are deployed by default in WSO2 Application Server. Since we already have a JAX-RS web app with the name jaxrs_basic, delete the default jaxrs_basic web application.

Now, we can deploy our jaxrs_basic web application (Note that, jaxrs_basic is a modified version of default sample jax-rs web application which has been customized to consume and produce JSON messages).

Go to  Manage --> Applications -->Add --> JAX-WS/JAX-RS.
Upload JAX-WS/JAX-RS Applications page will be shown. Browse the downloaded jaxrs_basic.war and click on upload. New JAX-RS web service will be deployed in WSO2 Application Server.

Step 3:

The auto-generated WADL of the RESTful web service can be obtained by accessing http://<wso2_application_server_hostname>:<wso2_application_server_port>/jaxrs_basic/services/customers?_wadl
From there, you will identify the POST URL of 'customer' resource;

http://<wso2_application_server_hostname>:<wso2_application_server_port>/jaxrs_basic/services/customers/customerservice/customers

We will forward a message to the above URL from WSO2 ESB.

Step 4:

Now we have the backend web service, ready to process messages. Let's create a pass-through proxy service in ESB. Obviously, the endpoint URL will be the one mentioned above.


<proxy xmlns="http://ws.apache.org/ns/synapse" name="jsonproxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<outSequence>
<send/>
</outSequence>
<endpoint>
<address uri="http://localhost:9764/jaxrs_basic/services/customers/customerservice/customers"/>
</endpoint>
</target>
<description></description>
</proxy>

Either using Pass Through Proxy template in WSO2 ESB management console or using file system, deploy the above proxy service.

Step 5:

Let's send a JSON request to our proxy service. I will use soapUI as usual since it is the best tool out there to invoke web services.

Open soapUI project and add a HTTP request test step to any existing test suite. Change the default method as POST. Enter the proxy service endpoint URL (http://<esb_host_name>:8280/services/jsonproxy) as the Request URL.
Set the media type as application/json and add the following JSON request to POST body text area.

{
"Customer": { "name": "charitha" }
}

Finally, your soapUI request editor will look like the following.

















Submit the request. You will get a JSON response back as shown below. WSO2 ESB will seamlessly forward JSON request to RESTful web service and forward the JSON response to soapUI.

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Server: WSO2 Carbon Server
Date: Sat, 12 Jan 2013 13:34:31 GMT
Transfer-Encoding: chunked

{"Customer":{"id":"125","name":"charitha"}}


NOTE:
In the previous versions of ESB (4.0.3 etc), you should add JSON message builders and formatters to ESB_HOME/repository/conf/axis2.xml in order to enable JSON message processing capabilities in ESB. (See http://docs.wso2.org/wiki/display/ESB403/ESB+and+JSON)
However, these builder and formatters are enabled by default in WSO2 ESB version 4.5.1 and later.  In addition to that, you may need to set the following property in IN and OUT paths of proxy services and sequences in previous ESB versions.

<property name="messageType" value="application/json" scope="axis2" />


Friday, January 4, 2013

TIP: How to view log statements generated by WSO2 ESB log mediator in System Logs UI?

When you use log mediator inside sequences and proxy services in WSO2 ESB , the logs are shown by default in wso2carbon.file which can be found in CARBON_HOME/repository/logs directory. The same logs are viewable from "System Logs" page in ESB management console.
However, from ESB-4.5.X releases, you should do the following simple change in order to see these logs in "System Logs" UI in management console.

Step 1
Open CARBON_HOME/repository/conf/axis2/axis2.xml

Step 2
Uncomment the following element.

             <handler class="org.wso2.carbon.utils.logging.handler.TenantDomainSetter" name="TenantDomainSetter">

Now, restart the server. Send a request to ESB and see the logs in "System Logs" UI in management console.

Friday, May 18, 2012

Managing SOA artifacts in different environments using WSO2 Governance Registry

NOTE:

Please note that the instructions given in this blog post are applicable ONLY for ESB-4.0.X and G-reg-4.1.X, G-reg-4.5.0 versions. The deployment approach of the latest ESB versions has been changed and the recommended deployment synchronization approach has been switched to SVN based synchronizer. Because of that the following set of instructions cannot be applied to the latest WSO2 ESB and G-reg product versions.



Managing artifacts of a service oriented solution is one of the most important features expected from any SOA middleware platform. In a typical service oriented project, SOA artifacts are subjected to move through multiple phases. Usually, separate environments are maintained for the activities associated with those phases.
e.g:-
  • Development environment
Service development and system integration tasks are carried out in a separate physical environment. Depending on the requirements, there can be multiple SOA middleware solutions used in development environment to facilitate service development, integration and deployment processes.Once the development tasks are completed,  SOA artifacts are transferred into QA environment for QA verification.
  • QA environment
Solution testing is done in an independent environment which is usually identical to the production settings. Various functional and non-functional tests are performed in QA environment. Upon successful QA verification, the artifacts are moved to production or staging environment

When the service oriented solution becomes complex and there are large number of SOA artifacts, automated artifact governance mechanism is required to ensure smooth transition between various environments. In this post, I will take you through a simplified SOA artifact governance process using WSO2 SOA middleware stack. We will explore a use case similar to the following.

Separate development and QA environments are used to maintain the SOA artifacts. For example, solution developers implement various configuration artifacts in ESB development node. After completing those development tasks, solution developers move those artifacts in to QA environment which allows the testers to carryout QA activities in an independent environment.  The moving of artifacts will be done automatically using the features provided by central SOA governance solution.
In this example, we will use WSO2 ESB as the enterprise service bus middleware, WSO2 Governance Registry as the SOA governance solution.


Lets go through each of the steps in detail. We need to have 2 WSO2 ESB instances and 1 WSO2 G-reg instance which runs on mySQL. All these instances will be deployed in single host.

Setting up G-reg and ESB products
Step 1
Download the latest versions of WSO2 ESB and WSO2 G-reg from here. First we will configure WSO2 G-reg instance. Extract wso2greg-4.x.x.zip into your file system. We will refer to the extracted location as GREG_HOME.
By default, WSO2 products run on the file based embedded H2 database. Since we need two ESB instances connect to the database used by G-reg instance, we will configure G-reg to run on a mySQL database. Enter the following commands to create a database and grant permission to a user.

mysql> create database greg_db;
Query OK, 1 row affected (0.00 sec)

mysql> use greg_db;
Database changed
mysql> grant all on greg_db.* to regadmin@localhost identified by "regadmin";
Query OK, 0 rows affected (0.05 sec)

Step 2
Now, we need to change the default database configuration in G-reg instance through registry.xml configuration file. Open GREG_HOME/repository/conf/registry.xml and update dbConfig element as shown below.
<dbConfig name="wso2registry">
<url>jdbc:mysql://localhost:3306/greg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
</dbConfig>
Copy mysql jdbc driver to GREG_HOME/repository/components/lib and start G-reg server by running wso2server.sh

Step 3
We have completed the configurations of WSO2 Governance Registry instance. Lets move forward with setting up ESB instance in development environment.

Extract the downloaded wso2esb-4.x.x.zip into a directory in your file system. We will refer to this directory as ESBDEV_HOME. Since we are running all product instances in a single machine, we need to start them up in different ports. Therefore, change port offset parameter in ESBDEV_HOME/repository/conf/carbon.xml as follows.

<Offset>1</Offset>
Step 4
As shown in the above diagram, we will mount /_system/config collection, where the ESB artifacts are stored in to /_system/dev collection of G-reg instance. ESBDEV_HOME/repository/conf/registry.xml is used to configure that.
<dbConfig name="configgovregistry">
<url>jdbc:mysql://localhost:3306/greg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
</dbConfig>
<remoteInstance url="https://localhost:9443/registry">
<id>configgov</id>
<dbConfig>configgovregistry</dbConfig>
<readOnly>false</readOnly>
<enableCache>true</enableCache>
<registryRoot>/</registryRoot>
</remoteInstance>

<mount path="/_system/config" overwrite="true">
<instanceId>configgov</instanceId>
<targetPath>/_system/dev</targetPath>
</mount>
<mount path="/_system/governance" overwrite="true">
<instanceId>configgov</instanceId>
<targetPath>/_system/governance</targetPath>
</mount>
Start ESB dev instance. If you log in to management console of the ESB instance (https://localhost:9444/carbon) and access registry browser, you will notice the config and governance collections are mounted (See the arrow icons) to the remote G-reg database.













Step 5

Repeat step 3 and 4 with another copy of wso2esb-4.x.x.zip. Lets call it ESBQA instance. (The root directory of ESBQA instance will be referred to as ESBQA_HOME). Make sure to specify a different offset value in carbon.xml. In this instance, we will mount /_system/config collection to /_system/qa collection of G-reg instance. Update registry.xml of ESBQA node as follows.
<dbConfig name="configgovregistry">
<url>jdbc:mysql://localhost:3306/greg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
</dbConfig>
<remoteInstance url="https://localhost:9443/registry">
<id>configgov</id>
<dbConfig>configgovregistry</dbConfig>
<readOnly>false</readOnly>
<enableCache>true</enableCache>
<registryRoot>/</registryRoot>
</remoteInstance>

<mount path="/_system/config" overwrite="true">
<instanceId>configgov</instanceId>
<targetPath>/_system/qa</targetPath>
</mount>
<mount path="/_system/governance" overwrite="true">
<instanceId>configgov</instanceId>
<targetPath>/_system/governance</targetPath>
</mount>

Start the server. We are done with the product configurations. However, we have not done any artifact governance configuration yet. In the next steps, we will look into moving artifacts between the two ESB instances.

Using WSO2 Governance Registry to move artifacts between environments
As I explained at the beginning, we use central governance registry instance to manage the artifacts produced by each of DEV and QA environments. The ESB artifacts produced by development environment are stored under /_system/dev collection of governance registry where as the artifacts used in QA environment are stored in /_system/qa collection. When the development tasks are compelte and ready for QA, we can manually copy the artifacts into the relevant locations and configure the QA environment. Obviously it will be a painful task to copy large number of artifacts into various locations of ESB QA environment by hand. Therefore, we need some kind of automated artifact copying mechanism.
WSO2 Governance Registry provides us with registry extension features to extend the core functionality of G-reg to use in these types of situations. The lifecycle management feature is such a useful extension provided by WSO2 Governance Registry which can be used to manage life cycle of a resource stored in registry.
The standard WSO2 G-reg distribution is shipped with a default ServiceLifeCycle which can be used to move service artifacts among different environments. We will modify the default ServiceLifeCycle to copy artifacts stored under /_system/dev collection to /_system/qa when promoting from development stage to testing.

Log in to G-reg management console and navigate to Extensions --> Configure --> Lifecycles. Click on Add New LifeCycle and add the following life cycle.
<aspect name="ESBLifeCycle" class="org.wso2.carbon.governance.registry.extensions.aspects.DefaultLifeCycle">
<configuration type="literal">
<lifecycle>
<scxml xmlns="http://www.w3.org/2005/07/scxml"
version="1.0"
initialstate="Development">
<state id="Development">
<datamodel>
<data name="checkItems">
<item name="Configurations Completed" forEvent="">
</item>
<item name="Transform Rules Done" forEvent="">
</item>
<item name="Routing Rules Completed" forEvent="">
</item>
</data>
<data name="transitionExecution">
<execution forEvent="Promote" class="org.wso2.carbon.governance.registry.extensions.executors.CopyExecutor">
<parameter name="currentEnvironment" value="/_system/dev"/>
<parameter name="targetEnvironment" value="/_system/qa"/>
</execution>
</data>
<data name="transitionUI">
<ui forEvent="Promote" href="../lifecycles/pre_invoke_aspect_ajaxprocessor.jsp?currentEnvironment=/_system/dev/"/>
</data>
</datamodel>
<transition event="Promote" target="Testing"/>
</state>
<state id="Testing">

<transition event="Demote" target="Development"/>
</state>
</scxml>
</lifecycle>
</configuration>
</aspect>
You can see that we have used org.wso2.carbon.governance.registry.extensions.executors.CopyExecutor class to copy one or more resources from one environment to another. Executors are custom extensions to G-reg which used to trigger a custom execution logic at the time of state transition (e.g:- Dev to QA, QA to Production). When artifacts are promoted to Testing state from Development, the CopyExecutor is triggered and the events defined under transitionExecution element are carried out. In this lifecycle, CopyExecutor copies any resource which is at currentEnvironment to targetEnvironment

Note that, CopyExecutor has not been shipped by default in WSO2 G-reg-4.1.X versions. Hence, you need to implement org.wso2.carbon.governance.registry.extensions.interfaces.Execution interface. However, in current trunk based versions (which will be released within few months), this executor is included by default and you can use it out-of-the-box.

Once the life cycle is created and saved, we can apply it to the relevant collection in registry. In this example, we need to move the artifacts stored at /_system/dev to /_system/qa. Hence, we must apply  ESBLifecycle to /_system/dev collection.

Navigate to /_system/dev collection in registry browser. Click on Lifecycle in the left pane. Select Add Lifecycle and choose ESBLifeCycle from the dropdown list. Click on Add to add ESBLifeCycle to /_system/dev collection.

We do not have any artifacts in /_system/dev collection yet. Therefore, lets add some ESB artifacts through ESB management console. Log in to the management console of ESB DEV instance and add a sequence. (say it is "devsequence). This will create a new sequence in ESB and it will be stored under /_system/dev in G-reg
Now, go back to G-reg management console and navigate to /_system/dev collection. Select the check-list items such as Configurations Completed, Transform Rules Defined etc.. and click on Promote.
After promotion, click on Search --> metadata in left menu in G-reg management console and search for the resource which has just been added ("devsequence"). The resource will be copied to /_system/qa collection.

We have just completed automatic promotion of resources which have been created from ESB DEV environment to ESB QA environment. However, you will notice that the ESB sequence artifact which has just been added, is not "deployed" in ESB QA instance. Because of that, you will not see "devsequence" in sequence list of ESB QA instance. The artifact is added to the relevant registry location but in order for deployment of the resource, ESB needs to check-out the resource from /_system/qa/repository/deployment/server/synapse-configs/default/sequences location in registry to the corresponding deployment directory of file system of ESB QA server. 
DeploymentSynchronizer comes into action in this situation. As I have explained in a previous blog post, DeploymentSynchronizer can be used to synchronize deployment artifacts among cluster nodes.
Lets enable registry based deployment synchronizer for ESB DEV and ESB QA instances.

- Shutdown both ESB DEV and ESB QA servers
- From WSO2 Carbon-4.0.0 release onwards, we need to enable Tribes based clustering in order for deployment synchronizer to communicate with cluster nodes. Open ESBDEV_HOME/repository/conf/axis2/axis2.xml and enable clustering and specify a unique domain name.
<clustering class="org.apache.axis2.clustering.tribes.TribesClusteringAgent" enable="true">
<parameter name="domain">wso2.charitha.domain</parameter>

Repeat the same with ESBQA_HOME/repository/conf/axis2/axis2.xml as well.

- Enable deployment synchronizer configuration in ESBDEV_HOME/repository/conf/carbon.xml
<DeploymentSynchronizer>
<Enabled>true</Enabled>
<AutoCommit>true</AutoCommit>
<AutoCheckout>true</AutoCheckout>
</DeploymentSynchronizer>
- Similarly, Enable deployment synchronizer configuration in ESBQA_HOME/repository/conf/carbon.xml. ESB QA instance automatically checks out the resources from /_system/qa collection of G-reg. Therefore, we just enable AutoCheckout in that node.

<DeploymentSynchronizer>
<Enabled>true</Enabled>
<AutoCommit>false</AutoCommit>
<AutoCheckout>true</AutoCheckout>
</DeploymentSynchronizer>
We have completed enabling deployment synchronizer for both ESB development and QA servers. Now, try out adding another sequence from ESB DEV instance (say it is "devsequence2"). Once the sequence is added, access G-reg management console and browse /_system/dev collection. Promote the lifecycle again. This time, you will notice that devsequence2 is deployed in ESB QA instance upon successful promotion
In this post, I took you through the steps of moving artifacts between different environments using WSO2 ESB and WSO2 G-reg. We created artifacts in ESB using management console. However, the recommended best practice is to build SOA artifacts using a tool like WSO2 Carbon Studio and upload the CAR artifacts to ESB. We will look into CAR based SOA governance mechanism in a future post.

Monday, November 21, 2011

WSO2 Deployment Synchronizer - Sharing deployment artifacts across a product cluster

This post is about a new feature in WSO2 Carbon product platform. I will use the latest versions of WSO2 Governance Registry(WSO2-G-reg-4.1.0) and WSO2 Enterprise Service Bus (ESB-4.0.2) for the demonstration.
Before going through the configuration steps, lets look at the problem which is going to be addressed using Deployment Synchronizer.
Suppose we have a WSO2 ESB product cluster with a single READ-WRITE node and a several READ-ONLY nodes which shares a common configuration registry. When we deploy a proxy service from READ-WRITE node, in order for other nodes to be synced with that new service deployment, all READ-ONLY nodes have to be restarted. This is a painful concern in a large product cluster.
WSO2 Deployment Synchronizer feature has been implemented to resolve that concern. With that, once you deploy a service (or any deployable artifact such as ESB sequence, scheduled task etc..) from one node in a product cluster, the other nodes automatically get the changes and sync up with the master (or READ-WRITE) node.
The Deployment Synchronizer makes use of two different approaches for deployment artifact synchronization.

1. SVN based synchronizer
2. Registry based synchronizer

Lets look at each of these in detail.

Pre-Requisites:
Download WSO2 ESB-4.0.2 and WSO2 Governance Registry-4.1.0 binary distributions from wso2 oxygen tank

Product Clustering Setup


Lets proceed through setting up a two node WSO2 Carbon product cluster as shown above.

Step 1:

Extract the downloaded WSO2ESB-4.0.2.zip and make two copies of it as wso2esb-rw and wso2esb-ro
wso2esb-rw directory is used as the master node of the cluster and wso2esb-ro node will be used as the slave node.

Step 2:

Extract the downloaded WSO2greg-4.1.0.zip into a new directory. This will be used as the central governance and configuration registry in our ESB cluster.

Step 3:
The above WSO2 G-reg instance will run on a mysql DB instead of the default H2 database. Therefore, lets create a mysql DB first.
Open a mysql prompt in your server. Type the following commands to create a database and assign user privileges.

mysql>create database reg_db;
mysql>use reg_db;
mysql>grant all on reg_db.* TO regadmin@localhost identified by "regadmin";

Edit the CARBON_HOME/repository/conf/registry.xml of the WSO2 G-reg server as follows.
<currentDBConfig>mysql-reg</currentDBConfig>
<readOnly>false</readOnly>
<enableCache>true</enableCache>
<registryRoot>/</registryRoot>

<dbConfig name="mysql-reg">
<url>jdbc:mysql://localhost:3306/reg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>5</maxActive>
<maxWait>60000</maxWait>
<minIdle>50</minIdle>
<validationQuery>SELECT 1</validationQuery></dbConfig>



Now, copy mysql jdbc driver (mysql-connector-java-5.1.7-bin.jar or later) to CARBON_HOME/repository/component/lib directory of WSO2Greg server and start the server with -Dsetup switch.

sh wso2server.sh -Dsetup

This will start WSO2-Greg server on mysql.

Step 4

Now, we have started central governance and configuration registry instance of our WSO2 ESB product cluster. Now, lets proceed with configuring WSO2 ESB nodes.
Lets configure read-write node first.

We are going to run 3 carbon servers in the same machine. Therefore, we need to change the port index in CARBON_HOME/repository/conf/carbon.xml so that each of the WSO2 ESB nodes will run on their own ports without conflicting with each other.
In carbon.xml, change the following element in order to run the ESB read-write node in HTTP port 9764 and HTTPS port 9444.


<Offset>1</Offset>

We are going to store the configuration data of ESB nodes in the cluster in /_system/esbnodes space of the above registry. Also, the governance data will be stored in /_system/governance directory. Therefore, lets add the following registry mounts through CARBON_HOME/repository/conf/registry.xml.
<dbConfig name="mysql-reg">
<url>jdbc:mysql://localhost:3306/reg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>5</maxActive>
<maxWait>60000</maxWait>
<minIdle>50</minIdle>
<validationQuery>SELECT 1</validationQuery></dbConfig>

<remoteInstance url="https://localhost:9443/registry">
<id>conf-gov-registry</id>
<dbConfig>mysql-reg</dbConfig>
<readOnly>false</readOnly>
<enableCache>true</enableCache>
<registryRoot>/</registryRoot>
</remoteInstance>

<!-- Governance data will be stored in /_system/governance collection of central registry instance -->
<mount overwrite="true" path="/_system/governance">
<instanceId>conf-gov-registry</instanceId>
<targetPath>/_system/governance</targetPath>
</mount>

<!-- Configuration data will be stored in /_system/esbnodes collection of central registry instance -->
<mount overwrite="true" path="/_system/config">
<instanceId>conf-gov-registry</instanceId>
<targetPath>/_system/esbnodes</targetPath>
</mount>


Copy mysql jdbc driver (mysql-connector-java-5.1.7-bin.jar or later) to CARBON_HOME/repository/component/lib directory of WSO2 ESB read-write node and start the server.

sh wso2server.sh

Step 5

We have configured and started the READ-WRITE node of ESB cluster. Now, we can configure the READ-ONLY node. The configuration is almost same as READ-WRITE node except the highlighted elements given below.

First, change the port offset to 2 so that the ports will not be conflicted with the other server ports.

<Offset>2</Offset>

Change the default NIO HTTP and HTTPS ports in CARBON_HOME/repository/conf/axis2.xml as follows.

<transportReceiver class="org.apache.synapse.transport.nhttp.HttpCoreNIOListener" name="http">
<parameter locked="false" name="port">8281</parameter>

<transportReceiver class="org.apache.synapse.transport.nhttp.HttpCoreNIOSSLListener" name="https">
<parameter locked="false" name="port">8244</parameter>


Add the following registry mounts through CARBON_HOME/repository/conf/registry.xml of ESB READ-ONLY node.
<dbConfig name="mysql-reg">
<url>jdbc:mysql://localhost:3306/reg_db</url>
<userName>regadmin</userName>
<password>regadmin</password>
<driverName>com.mysql.jdbc.Driver</driverName>
<maxActive>5</maxActive>
<maxWait>60000</maxWait>
<minIdle>50</minIdle>
<validationQuery>SELECT 1</validationQuery></dbConfig>

<remoteInstance url="https://localhost:9443/registry">
<id>conf-gov-registry</id>
<dbConfig>mysql-reg</dbConfig>
<readOnly>true</readOnly>
<enableCache>true</enableCache>
<registryRoot>/</registryRoot>
</remoteInstance>

<!-- Governance data will be stored in /_system/governance collection of central registry instance -->
<mount overwrite="true" path="/_system/governance">
<instanceId>conf-gov-registry</instanceId>
<targetPath>/_system/governance</targetPath>
</mount>

<!-- Configuration data will be stored in /_system/esbnodes collection of central registry instance -->
<mount overwrite="true" path="/_system/config">
<instanceId>conf-gov-registry</instanceId>
<targetPath>/_system/esbnodes</targetPath>
</mount>


Copy mysql jdbc driver (mysql-connector-java-5.1.7-bin.jar or later) to CARBON_HOME/repository/component/lib directory of WSO2 ESB read-only node and start the server.

sh wso2server.sh

Now we are done with the clustering setup but we have not done any configurations related to the deployment synchronizer yet.
We will look in to the registry based deployment synchronization first.

Step 6 - Registry based deployment synchronizer

In this mode, once you deploy an artifact from the READ-WRITE node, the artifacts will be stored in the relevant collection in the configuration registry. The other nodes of the cluster will use the registry checkin-checkout client and checkout the deployment artifacts to their file system. Then with the hot deployment functionality, the artifacts will get deployed in the cluster nodes.

Lets look at how we can use the registry based deployment synchronizer.

  • Log in to management console of ESB READ-WRITE node (https://localhost:9444/carbon)
  • Navigate to Configure --> Deployment Synchronizer UI

  • Select Auto Commit option and click on Enable
  • Log in to management console of ESB READ-ONLY node (https://localhost:5/carbon)
  • Access Configure --> Deployment Synchronizer UI
  • Select Auto Checkout option and click on Enable
  • Create a proxy service (eg:-proxy1) in READ-WRITE node
  • After 60 seconds (the default synchronization period), log in to the management console of the READ-ONLY node of the cluster.
  • You will notice that the proxy1 is listed in the services list of READ-ONLY node

Step 7 - SVN based deployment synchronizer

Deployment synchronization can be achieved using a SVN repository as well. Lets look at SVN based deployment synchronizer.

In this mode, instead of a registry, we use a subversion repository as the deployment artifact store. As we check-in files to SVN, the synchronizer use a SVN client API and commit and update deployment artifacts periodically by using a SVN location.

  • First, revert the registry based deployment synchronizer settings which we did above. (Disable deployment synchronizer in Configure --> Deployment Synchronizer UI)

  • Have a proper SVN location. You can use an existing SVN location or create a new one.
  • Add the following configuration in CARBON_HOME/repository/conf/carbon.xml of both ESB nodes. Make sure to specify correct SVN credentials and location URL according to your environment.
<DeploymentSynchronizer>
<Enabled>true</Enabled>
<AutoCommit>true</AutoCommit>
<AutoCheckout>true</AutoCheckout>
<RepositoryType>svn</RepositoryType>
<SvnUrl>https://svn.wso2.com/wso2/custom/projects/projects/qa/deployment-synchronizer/esb</SvnUrl>
<SvnUser>qasvn</SvnUser>
<SvnPassword>test</SvnPassword>
<SvnUrlAppendTenantId>false</SvnUrlAppendTenantId>
</DeploymentSynchronizer>


  • Restart both ESB nodes.
  • Deploy a proxy service from either one of the nodes
  • Changes will get reflected into other nodes after 60 seconds (default synchronization period)

We looked at two different ways of sharing deployment artifacts among cluster nodes. If you come across any issues when configuring either one of the above approaches, please drop me a mail.