API(Application programming interface) is not new, it has been a commonly used term in computing for decades. But what is management of APIs?
When a set of entities become larger and grow in exponential manner, there is alway a need of management. You can have your own shop and you are able to look after each and every aspect of its operations till it grows to some level. Once, you have a chain of shops, you, by your own cannot do the same which you did with one shop. You should have some kind of management to govern and control your business operations.
Similarly, management is a common requirement for most of the entities around us. DBMS systems were built to manage pools of data.
If you expose the computing assets of your organization to external parties so that they can build applications to integrate with your systems, it can be considered as an API offering. With the widespread adoption of mobile devices and service oriented computing, business organizations began to open application and services to external developers. These third party developers built applications to integrate with the systems of API provider allowing the provider to extend the capabilities of their business as well as helping the third party developers to earn by their own.
Today, there is a enormous set of applications build by third party developers based on the APIs exposed by large vendors. For example, how many new android, iPad, iPhone apps out there for download? how many facebook, twitter apps?
With this demand of APIs, there is a necessity of adopting a proper API management if you are a Internet application vendor who expose the business APIs for third party developers. Similar to database management software, API management software is used primarily to help API publishers to expose the APIs and third party developers to build applications in simple and efficient manner. Mashery is considered as the first known API management solution. An API management software should be capable of governing and controlling access to the APIs, securing APIs, metering and monitoring usage of APIs etc..
With large amount of APIs offered by many vendors as well as the adoption of API management solutions, should we expect a radical change in software testing space? Should there be a totally different approach for API testing?
Since there is a close relationship with services in service oriented architecture (SOA) and web APIs, I believe the approach which I suggested for SOA testing will still be applicable for APIs.
Similar to web services, the APIs which are exposed to outside, for various application development and integration efforts, must be tested end-to-end to verify both functional and non-functional needs. In API development, everyone (both QA and Development) should equally be responsible for quality. You should not even think of exposing your APIs for public use if you do not have automated tests to verify regressions. Think about the performance impacts, think about security concerns, think about usage patterns of your APIs and derive a comprehensive test plan.
Open source tools such as soapUI which we use for web services testing can also be used for API testing out of the box. Specially, soapUI can easily be used for REST API testing.
I do not think there will be a completely different set of tools for API testing since API testing has been there for years and most of the tools as well as the constructs provided by programming languages such as Junit, Nunit etc.. have been used in API testing in all these years.
However, I believe, the API management vendors should think more about the testing and quality assurance aspects. Quality is as important as the govern, control, monitoring aspects of web APIs. Therefore, it will be important for API management solutions, at least to include a set of tools for testing the APIs managed by them.
Thursday, January 26, 2012
Saturday, January 21, 2012
Truly RESTful Services using Apache Wink and WSO2 Application Server


Apache Wink is a complete implementation of JAX-RS v-1.1 specification. JAX-RS is a java API which supports creating web services in RESTful manner.
WSO2 Application Server is the enterprise-ready, scalable web services and web app hosting platform powered by Apache Axis2 and Apache Tomcat.
In this post, we are going to create a RESTful web service using Apache wink libraries and deploy it in WSO2 Application Server. If we summarize the steps that we are going to do in this example;
1. Create a JDBC data source (mySQL)
2. Create the web service with JAX-RS annotations which makes use of the above database
3. Create a web application (war) with apache wink libraries
4. Deploy the web app in WSO2 Application Server
WSO2 provides application developers with a complete middleware platform in cloud. Therefore, we makes use of WSO2 StratosLive PaaS (Platform as a Service) as our development platform. In other words, we are NOT even going to install mySQL or WSO2 Application server in our machines to try this sample out. We will create the database in cloud and host web application in the cloud.
Without discussing further. lets start our journey.
Step 1
We are going to create a primitive customer registration application which consists of a mySQL database with one table called customer. We need to create the DB schema.
WSO2 Stratos middleware platform in cloud allows us to have our own data storage in cloud within seconds. As I explained in this post, all we have to do is;
- Register a new tenant
- Log into https://stratoslive.wso2.com
- Access DataServices Server
- Create a database and a table
CREATE TABLE CUSTOMER_T(customerID int, customerName varchar(100), customerAge int, customerAddress varchar(200));
Once the database and table is created, note the DB connection URL. In my case, it is,
jdbc:mysql://rss1.stratoslive.wso2.com/wink_superqa_com
Step 2
Now, our application data source is ready for use. As I have explained before, we are going to create a customer registration web service which includes all CRUD operations associated with above DB schema. In other words, we can add, delete, read and update customers using the web service. We will implement our webservice in completely RESTful manner so that we makes use of HTTP verbs to invoke service.
Therefore, lets create the Customer bean first. Open your favorite Java IDE and add Customer class with the following properties and associated getters and setters. The complete class can be found at https://wso2.org/repos/wso2/trunk/commons/qa/qa-artifacts/app-server/rest/jaxrs-sample/src/com/beans/Customer.java
public class Customer {
private int customerID;
private String customerName;
private String customerAddress;
private int customerAge;
Step 3
We will use a separate class to handle all communication with the database which we created above. Lets name the class as Storage.java and implement all CRUD operations.
public class Storage {
Connection connection = null;
Statement statement = null;
ResultSet rs = null;
private Connection getConnection() {
String driverName = "com.mysql.jdbc.Driver";
String conectionURI = "jdbc:mysql://rss1.stratoslive.wso2.com/wink_superqa_com";
String userName = "ck_l96225fe";
String password = "ck";
try {
Class.forName(driverName);
try {
connection = DriverManager.getConnection(conectionURI, userName, password);
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return connection;
}
//CREATE operation
public void addCustomer(Customer customer) {
try {
connection = getConnection();
statement = connection.createStatement();
String sqlStatement = "INSERT INTO CUSTOMER_T VALUES (" + customer.getCustomerID()
+ ",'" + customer.getCustomerName() + "', " + customer.getCustomerAge() + ",'" + customer.getCustomerAddress() + "')";
statement.execute(sqlStatement);
} catch (SQLException e) {
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Similarly, add the other methods to UPDATE, DELETE and READ operations. The complete Storage.java class can be found here.
Step 4
Now, we can implement our web service. We are going to use JAX-RS annotations to make our web service completely RESTful. Download Apache wink distribution from here and add WINK_HOME/dist and WINK_HOME/lib to class path of your IDE.
We will have four methods to demonstrate the basic HTTP methods.
- addCustomer() method is used to add a new customer to the system. We use a HTTP POST request to send the customer details to the web service method.
- getCustomerName() is just a HTTP GET operation which reads the CUSTOMER_T table and send back the name of the customer associated with given customer ID.
- updateCustomer() method updates the customer address of the given customer
- deleteCustomer() method removes a customer record from the table
@Path("/qa")
public class CustomerService {}
Now, we need to implement the methods associated with CRUD operations. First lets look at addCustomer method. As we defined the root resource at the class declaration level, we can define subresource methods to handle the common HTTP methods. Here, addCustomer is a subresource method and we annotate it with @POST to direct POST requests which are targeted to '/qa' root resource. @Path annotation at the sub resource level resolves the URL path which is targeted to the method. In otherwords, if the request URL is, /qa/customer and the HTTP method is POST, the request is dispatched to addCustomer() method.
@POST
@Consumes("application/x-www-form-urlencoded")
@Path("/customer")
public void addCustomer(@FormParam("customerid") int customerID, @FormParam("customername") String customerName, @FormParam("customerage") int customerAge, @FormParam("customeraddress") String customerAddress){
Storage storage = new Storage();
Customer customer = new Customer();
customer.setCustomerID(customerID);
customer.setCustomerName(customerName);
customer.setCustomerAge(customerAge);
customer.setCustomerAddress(customerAddress);
storage.addCustomer(customer);
}
Also, make a note of the @Consumes annotation, here we define the Content-Type which must be included in the HTTP POST request. In our example, if a POST request to '/qa/customer' is issued with "application/x-www-form-urlencoded" Content-Type, the addCustomer() method will be invoked. If we send any other content in the POST request, this method will not get invoked.
We also use annotated parameters to pass some additional information with a request. For example we can use query parameters, path parameters etc and process them accordingly. In our example, we use @FormParm parameter to extract parameter values from the form posts.
Similarly, we can implement the other methods in our service implementation class.
@GET
@Path("/customer/{customerid}")
@Produces("text/plain")
public String getCustomerName(@PathParam("customerid") int customerID) {
Storage storage = new Storage();
Customer customer = null;
try {
customer = storage.getCustomerDetails(customerID);
} catch (SQLException e) {
e.printStackTrace();
}
return customer.getCustomerName();
}
@PUT
@Consumes("application/x-www-form-urlencoded")
@Path("/customer")
public void updateCustomer(@FormParam("customername") String customerName, @FormParam("customeraddress") String customerAddress){
Storage storage = new Storage();
storage.updateCustomer(customerName, customerAddress);
}
@DELETE
@Path("/customer/{customerid}")
public void deleteUser(@PathParam("customerid") int customerID) {
Storage storage = new Storage();
storage.deleteCustomer(customerID);
}
Step 5
We have completed the implementation of our web service class with JAX-RS annotations. Apache wink needs us to create a sub-class of javax.ws.rs.core.Application if we deploy deploy our application on non-JAX-RS aware containers. At the time of writing, WSO2 Application Server is not JAX-RS aware hence we need to create this particular subclass. This class basically returns the root resource(s).
public class CustomerResourceApplication extends Application {
@Override
public Set> getClasses() {
Set> classes = new HashSet>();
classes.add(CustomerService.class);
return classes;
}
}
Step 6
Next, we need to create the web.xml file for our web application. In addition to the standard constructs in web.xml, we should define that the Apache wink JAX-RS servlet should be initialized with an instance of the above CustomerResourceApplication.
We also define that the requests begin with '/rest/' will be handled by Apache Wink JAX-RS servlet.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Restful service Test Web Application</display-name>
<servlet>
<servlet-name>CustomerServlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.sample.CustomerResourceApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Step 7
We are done with our web application now. Create a war with the above classes as well as apache wink libraries. Make sure to place all jars included in WINK_HOME/dist and WINK_HOME/lib in WEB-INF/lib of the web application. You can use the ant build script given here to do all these stuff.
Step 8
Once the web application (CustomerService.war) is ready, log in to https://appserver.stratoslive.wso2.com with your tenant credentials and upload the web application. (Please read my blog post on Apache Tomcat As a Service if you want to know how WSO2 application Server can be used in web app deployment)
Step 9
Finally, we can invoke each of the operations of our web service in truly RESTful manner using a client application such as curl.
HTTP POST:
curl --data "customerid=1&customername=charitha&customerage=33&customeraddress=piliyandala" -X POST -H "Content-Type: application/x-www-form-urlencoded"http://appserver.stratoslive.wso2.com/t/superqa.com/webapps/CustomerService/rest/qa/customer
HTTP GET:
curl -X GET http://appserver.stratoslive.wso2.com/t/superqa.com/webapps/CustomerService/rest/qa/customer/1
HTTP PUT:
curl --data "customername=charitha&customeraddress=colombo" -X PUT -H "Content-Type: application/x-www-form-urlencoded" http://appserver.stratoslive.wso2.com/t/superqa.com/webapps/CustomerService/rest/qa/customer
HTTP DELETE:
curl -X DELETE http://appserver.stratoslive.wso2.com/t/superqa.com/webapps/CustomerService/rest/qa/customer/1
SOAP with HTTP basic auth using Apache JMeter
SOAP/XML-RPC request sampler of Apache Jmeter can be used to send SOAP requests to a web service. We looked into the details of SOAP/XML-RPC sampler in a previous blog post.
If the web service is secured, we cannot directly send messages using the above sampler. This post will help you to use Jmeter in web service testing if the service is secured using HTTP basic authorization.
If a web service is secured using HTTP basic authorization, the authorization credentials are carried over HTTP headers of the message. The security information is not coupled with the SOAP envelope. Therefore, the same procedure which we are going to discuss below can be applied to any other sampler in Jmeter.
Step 1:
Have a web service secured with HTTP basic authentication. I use Apache Axis2 as the web service container and deploy it on Apache Tomcat. Then use the tomcat authorization to secure any service hosted in Axis2 As explained by Prabath in here.
If the service is secured with HTTP basic auth, the service can only be invoked if you send the request with Authorization header as follows.
Authorization: Basic Y2hhcml0aGE6Y2hhcml0aGE=
Step 2:
We need to insert this header into SOAP messages which transmits over HTTP channel. In other words, we need Jmeter to add this header for all requests which are sent to the above web service. Lets see how we can do this.
Start to create a new Jmeter test plan. Add a thread group and add SOAP/XML-RPC request sampler. Add SOAP envelope and specify the endpoint URL.

Step 3
We need to insert authorization HTTP header to each SOAP request. Therefore, we need to use one of the Config Elements included in Jmeter. HTTP Authorization Manager config element comes in handy in this situation. Authorization manager can be used to specify login information when you access websites, web services or any other HTTP accessible resource which secured with basic authorization.
Select the thread group and select Config Element --> Authorization Manager
HTTP authorization manager config element will be added to your thread group as shown below.

Step 4
Specify the following properties in HTTP Authorization manager.
Base URL = http://localhost:8080/axis2
username = charitha
password = charitha
Here, Base URL is a part or complete URL of the web service you are going to access.
User name and password are the credentials which we specified in tomcat-users.xml file
Step 5
Add a listener and run the test. You will see the SOAP request with the following HTTP headers.
Content-Type: text/xml
SOAPAction: "urn:echoString"
Connection: close
Authorization: Basic Y2hhcml0aGE6Y2hhcml0aGE=
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:8080
Content-Length: 268
If the web service is secured, we cannot directly send messages using the above sampler. This post will help you to use Jmeter in web service testing if the service is secured using HTTP basic authorization.
If a web service is secured using HTTP basic authorization, the authorization credentials are carried over HTTP headers of the message. The security information is not coupled with the SOAP envelope. Therefore, the same procedure which we are going to discuss below can be applied to any other sampler in Jmeter.
Step 1:
Have a web service secured with HTTP basic authentication. I use Apache Axis2 as the web service container and deploy it on Apache Tomcat. Then use the tomcat authorization to secure any service hosted in Axis2 As explained by Prabath in here.
If the service is secured with HTTP basic auth, the service can only be invoked if you send the request with Authorization header as follows.
Authorization: Basic Y2hhcml0aGE6Y2hhcml0aGE=
Step 2:
We need to insert this header into SOAP messages which transmits over HTTP channel. In other words, we need Jmeter to add this header for all requests which are sent to the above web service. Lets see how we can do this.
Start to create a new Jmeter test plan. Add a thread group and add SOAP/XML-RPC request sampler. Add SOAP envelope and specify the endpoint URL.

Step 3
We need to insert authorization HTTP header to each SOAP request. Therefore, we need to use one of the Config Elements included in Jmeter. HTTP Authorization Manager config element comes in handy in this situation. Authorization manager can be used to specify login information when you access websites, web services or any other HTTP accessible resource which secured with basic authorization.
Select the thread group and select Config Element --> Authorization Manager
HTTP authorization manager config element will be added to your thread group as shown below.

Step 4
Specify the following properties in HTTP Authorization manager.
Base URL = http://localhost:8080/axis2
username = charitha
password = charitha
Here, Base URL is a part or complete URL of the web service you are going to access.
User name and password are the credentials which we specified in tomcat-users.xml file
Step 5
Add a listener and run the test. You will see the SOAP request with the following HTTP headers.
Content-Type: text/xml
SOAPAction: "urn:echoString"
Connection: close
Authorization: Basic Y2hhcml0aGE6Y2hhcml0aGE=
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:8080
Content-Length: 268
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.
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.
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.
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.
Add the following registry mounts through CARBON_HOME/repository/conf/registry.xml of ESB READ-ONLY node.
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.

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.
<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>
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.
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.
- 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.
Tuesday, November 15, 2011
How to pass system properties when WSO2 Carbon server is running in daemon mode
When you start wso2 carbon server using a startup script such as wso2server.sh, you can simply pass system properties such as -DosgiConsole, just by passing system property in command line.
e.g:- sh wso2server.sh -DosgiConsole
However, if you start the server as a System process (daemon), how should you send those parameters?
Lets look at how we can start OsgiConsole, if we start server in daemon mode.
1. Open CARBON_HOME/repository/conf/wrapper.conf
2. Add the following parameter under Java additional properties section
wrapper.java.additional.11=-DosgiConsole=1234
wrapper.java.additional.11=-DosgiConsole=1234
3. Start the server as "sh wso2server.sh -start"
4. Open a new shell and "telnet localhost 1234"
Sunday, November 6, 2011
ApacheCon NA 2011 - a week full of Apache community gathering

ApacheCon is the official event of Apache Software Foundation which brings together the global Apache community in a week full of trainings, live demos, hands-on sessions and various other meet ups.
The event will be commenced tomorrow, 7th of November 2011 in the Westin Bayshore Vancouver Canada.
I'm witnessing a lot of technology enthusiasts from diverse parts of the world are checking-in at Westin Bayshore hotel at the moment predicting a successful function.
With the tightly-coupled relationship of WSO2 and various Apache projects, WSO2 is playing a key role in ApacheCon 2011 as well. WSO2 is presenting 3 talks and is an exhibitor Sponsor too.
Afkham Azeez speaks about building scalable multi-tenant application server on cloud using Tomcat, Axis2 and Synapse on Wednesday, November 9th.
He is also talking about an architecture for enabling multi-tenancy for Apache Axis2 on Thursday, November 10th.
Prabath Siriwardhana will also do a half-day training on web services security on Monday, November 7th.
Come and meet us at WSO2 booth at ApacheCon. You will find how WSO2 built world's first free and open source PaaS and renowned SOA platform using various Apache project components and how we adhered to the Apache process in project releases.
Friday, October 28, 2011
Why is testing taking so long?
When you are involved in software testing, you may have heard the following 3 common questions at the end, beginning or middle of any testing cycle.
1. Why did not you find that bug during testing cycle?
2. Why is testing taking so long?
3. Why did not you automate the damn thing?
I have answers for all three questions but Michael Boloton, the testing genius in our era, explained the answer for question 2 with some great examples. I would recommend this to be a must read for anyone work in software engineering.
Study the facts given by Michael. You will realize the truth of test estimation and traditional way of managing test processes.
Subscribe to:
Posts (Atom)
