Thursday, November 28, 2013

Selenium 

A sample java-selenuim code to upload an artifact (Helloword.aar) on your desktop to wso2 application server instance. Note that we will use firefox browser for the demonstration.

package selenium;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

import static org.testng.Assert.assertEquals;

public class AppserverArtifactUpload {

    private static final Log log = LogFactory.getLog(AppserverArtifactUpload.class);

    public static void main(String[] args) {

        // Initializing the web driver
        WebDriver driver = new FirefoxDriver();

        // Setting the url
        driver.get("https://ip:port/carbon/"); 
        // your server ip & port (eg: ip-100.100.100.100 , port- 9443)

        // Creating username & password fields
        WebElement userName = driver.findElement(By.name(("username")));
        WebElement password = driver.findElement(By.name(("password")));

        // Setting values for username & password
        userName.sendKeys("admin");
        password.sendKeys("admin");

        // Now submit the form. WebDriver
        password.submit();

        // Check the title of the page
        log.info("Page Title : " + driver.getTitle());
        assertEquals("WSO2 Management Console", driver.getTitle(), "Page Title Mismatch");

        // Traveling to AAR upload page
        driver.findElement(By.xpath("/html/body/table/tbody/tr[2]/td[2]/table/tbody/tr/td/div/ul/li[5]/ul/li[4]/ul/li[3]/ul/li/a")).click();

        /*// if u want to add additional browser buttons
        driver.findElement(By.cssSelector("input[type='button']")).click();*/

        // browsing and selecting the .aar file
        driver.findElement(By.xpath("/html/body/table/tbody/tr[2]/td[3]/table/tbody" +
                "/tr[2]/td/div/div/form/table/tbody/tr[2]/td/input"))
                .sendKeys("/home/dimuthu/Desktop/HelloWorld.aar");

        // uploading the selected aar file
        WebElement upload = driver.findElement(By.name(("upload")));
        upload.submit();

        log.info("HelloWorld.aar uploaded successfully");
    }
}

Friday, November 1, 2013

Identifying OSGI components in server startup .......

For this post I will publish a code snippet for identifying unsatisfied osgi bundles. 

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.telnet.TelnetClient;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.carbon.automation.core.MultipleServersManager;

import java.io.*;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;

import static org.testng.Assert.assertTrue;

/*
  This class can be used to identify required osgi component service components (eg: unsatisfied) in server startup
 */
public class OSGIServerBundleStatusTest {

    private static final Log log = LogFactory.getLog(OSGIServerBundleStatusTest.class);

    private static int telnetPort = 2000;
    private TelnetClient telnet = new TelnetClient();
    private ArrayList<String> arrList = new ArrayList<String>();
    private ArrayList<String> unsatisfiedList = new ArrayList<String>();
    private HashMap<String, String> serverPropertyMap = new HashMap<String, String>();
    private MultipleServersManager manager = new MultipleServersManager();

    @BeforeClass(alwaysRun = true)
    public void init() throws Exception {

        serverPropertyMap.put("-DportOffset", "1"); // to start the server from a different port offset
        serverPropertyMap.put("-DosgiConsole", Integer.toString(telnetPort)); // start with osgicomponentservice
        CarbonTestServerManager server = new CarbonTestServerManager(System.getProperty("carbon.zip"),
                serverPropertyMap);
        manager.startServers(server);
    }

    @AfterClass(alwaysRun = true)
    public void stopServers() throws Exception {
        disconnect();  // telnet disconnection
        // manager.stopAllServers();
    }

    @Test(groups = "wso2.as", description = "Identifying and storing unsatisfied OSGI components")
    public void testOSGIUnsatisfiedComponents() throws Exception {

        telnet.connect(InetAddress.getLocalHost().getHostAddress(), telnetPort);
        telnet.setSoTimeout(10000);

        ArrayList<String> arr = retrieveUnsatisfiedComponentsList("ls");

        for (int x = 0; x < arr.size(); x++) {
            unsatisfiedList.add(arrList.get(x).split("\t")[3]);
            log.info(unsatisfiedList.get(x));
        }


        assertTrue(unsatisfiedList.size() > 0);  // TODO - Will vary according to the requirement
    }

    private ArrayList<String> retrieveUnsatisfiedComponentsList(String command) throws IOException {
        writeInputCommand(command);
        try {
            readResponse();
        } catch (SocketTimeoutException e) {
            log.error("Socket timeout Exception "  e);
        }
        return arrList;
    }

    private void writeInputCommand(String value) {

        PrintStream out = new PrintStream(telnet.getOutputStream());
        out.println(value);
        out.flush();
        log.info(value);
    }

    private void readResponse() throws IOException {

        InputStream in = telnet.getInputStream();
        BufferedReader inBuff = new BufferedReader(new InputStreamReader(in));
        String inputLine = inBuff.readLine();

        while (!inputLine.equals("")) {
            if (inputLine.contains("Unsatisfied")) {  // filtering Unsatisfied components
                arrList.add(inputLine);
            }
            inputLine = inBuff.readLine();
            log.info(inputLine);
        }
    }

    private void disconnect() throws IOException {
        telnet.disconnect();
        log.info("Telnet connection is disconnected");
    }
}


import java.io.IOException;
import java.util.HashMap;

public class CarbonTestServerManager extends TestServerManager {

    public CarbonTestServerManager() {
    }

    public CarbonTestServerManager(String carbonZip, HashMap<String, String> startupParameterMap) {
        super(carbonZip, startupParameterMap);
    }

    public CarbonTestServerManager(int portOffset) {
        super(portOffset);
    }

    public String startServer() throws IOException {
        String carbonHome = super.startServer();
        System.setProperty("carbon.home", carbonHome);
        return carbonHome;
    }

    public void stopServer() throws Exception {
        super.stopServer();
    }

    protected void copyArtifacts(String carbonHome) throws IOException {
    }
}

Wednesday, October 23, 2013

Java Tips .....

To get directory names inside a particular directory ....

private String[] getDirectoryNames(String path) {

        File fileName = new File(path);
        String[] directoryNamesArr = fileName.list(new FilenameFilter() {
            @Override
            public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
            }
        });
        log.info("Directories inside " + path + " are " + Arrays.toString(directoryNamesArr));
        return directoryNamesArr;
    }



To retrieve links on a web page ......

 private List<String> getLinks(String url) throws ParserException {
        Parser htmlParser = new Parser(url);
        List<String> links = new LinkedList<String>();

        NodeList tagNodeList = htmlParser.extractAllNodesThatMatch(new NodeClassFilter(LinkTag.class));
        for (int x = 0; x < tagNodeList.size(); x++) {
            LinkTag loopLinks = (LinkTag) tagNodeList.elementAt(m);
            String linkName = loopLinks.getLink();
            links.add(linkName);
        }
        return links;
    }


To search for all files in a directory recursively from the file/s extension/s ......

private List<String> getFilesWithSpecificExtensions(String filePath) throws ParserException {

// extension list - Do not specify "." 
 List<File> files = (List<File>) FileUtils.listFiles(new File(filePath),
                new String[]{"txt"}, true);

        File[] extensionFiles = new File[files.size()];

        Iterator<File> itFileList = files.iterator();
        int count = 0;

        while (itFileList.hasNext()) {
            File filePath = itFileList.next();
           
extensionFiles[count] = filePath;
            count++;
        }
        return
extensionFiles;



Reading files in a zip

     public static void main(String[] args) throws IOException {
        final ZipFile file = new ZipFile("Your zip file path goes here");
        try
        {
            final Enumeration<? extends ZipEntry> entries = file.entries();
            while (entries.hasMoreElements())
            {
                final ZipEntry entry = entries.nextElement();
                System.out.println( "Entry "+ entry.getName() );
                readInputStream( file.getInputStream( entry ) );
            }
        }
        finally
        {
            file.close();
        }
    }
        private static int readInputStream( final InputStream is ) throws IOException {
            final byte[] buf = new byte[8192];
            int read = 0;
            int cntRead;
            while ((cntRead = is.read(buf, 0, buf.length) ) >=0)
            {
                read += cntRead;
            }
            return read;
        } 



Converting Object A to Long[]

 long [] myLongArray = (long[])oo;
        Long myLongArray [] = new Long[myLongArray.length];
        int i=0;

        for(long temp:myLongArray){
            myLongArray[i++] = temp;
        } 


Getting cookie details on HTTP clients

import org.apache.http.impl.client.DefaultHttpClient;

HttpClient httpClient = new DefaultHttpClient();

((DefaultHttpClient) httpClient).getCookieStore().getCookies(); 

 HttpPost post = new HttpPost(URL);
        post.setHeader("User-Agent", USER_AGENT);
        post.addHeader("Referer",URL );
        List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
        urlParameters.add(new BasicNameValuePair("username", "admin"));
        urlParameters.add(new BasicNameValuePair("password", "admin"));
        urlParameters.add(new BasicNameValuePair("sessionDataKey", sessionKey));
        post.setEntity(new UrlEncodedFormEntity(urlParameters));
        return httpClient.execute(post);



Ubuntu Commands

1. Getting the process listening to a given port (eg: port 9000) 

sudo netstat -tapen | grep ":9000 "


Running  a bash script from python script

shell.py
-----------

import os

def main():

    os.system("sh hello.sh")

if __name__=="__main__":
 os.system("sh hello.sh")


hello.sh
-----------
#Linux shell Script


echo "Hello Python from Shell";

public void scriptExecutor() throws IOException {

    log.info("Start executing the script to trigger the docker build ... ");

    Process p = Runtime.getRuntime().exec(
            "python  /home/dimuthu/Desktop/Python/shell.py ");
    BufferedReader in = new BufferedReader(new InputStreamReader(
            p.getInputStream()));
    log.info(in.readLine());

    log.info("Finished executing the script to trigger the docker build ... ");

}

Monday, September 16, 2013

WSO2 Deployment Synchronizer (Dep-sync) ...


What is a cluster?

A cluster is a bunch of similar computers / products that is integrated/ connected  to achieve a goal. Members of the cluster can work in many respects and more importantly they can be viewed as a single system.

Sharing artifacts across a cluster

Deployment Synchronizer enables us to synchronize the deployment of artifacts across the nodes of a cluster.

The Deployment Synchronizer makes use of two different approaches for its deployment artifact synchronization.

 1. SVN based synchronizer
 2. Registry based synchronizer

In this usecase I will describe how to setup a SVN based deployment synchronizer. Now lets move into the deeper end of this category.

SVN based synchronizer

In simple terms this means your manager-node will use a remote svn location to commit all artifacts and the slave node/s will perform a svn checkout to obtain mentioned, committed artifacts to its respective artifact directories.

Following graphical elaboration will help you to get a quick understanding of the setup we are going to develope in a while.

fig 1.0
I will use two wso2 esb servers in this example out of which one server will perform as the master-node and the other will serve as the slave-node. 

You can download the latest wso2 esb distribution from here. 


You can configure this setup either to run both ESB servers in the same machine or run one server on remote location/ computer.

Since setting up the configuration to run both servers in the same local machine is simple for this demonstration we are going to look into setting up the correct configuration to run one server in the local machine and the other in a remote machine. 

After downloading the distribution extract it onto your computer desktop or any preferred place. 

For easy reference purposes rename the distribution as wso2esb-4.7.0_master. Now move the distribution to the other remote computer and extract, rename it as wso2esb-4.7.0_slave. (For this example we will host our remote machine instance at openstack cloud (http://www.openstack.org/) . You may create a private openstak cloud , thereafter create an instance to host your slave-node on it.

In-order to setup the clustering we need to have a svn location. You need to create a suitable svn location and keep the credentials to access the svn with you as we need to include them in our configuration files of both ESBs.

Now lets look at the master-node. You need the go to the ....../wso2esb-4.7.0_master/repository/conf/ folder of your esb pack and open the carbon.xml file. 

Add the following entries to your carbon.xml configuration file.These are the basic properties we need to set in-order to configure svn based synchronizing. Draw your attention to each tag. Detail explanation for each are provided with.

Master-node : carbon.xml configuration file (..../wso2esb-4.7.0_master/repository/conf/carbon.xml)  

<DeploymentSynchronizer>
   <Enabled>true</Enabled> <!-- enables the dep sync feature-->
   <AutoCommit>true</AutoCommit> <!-- master node has the right to commit artifacts to the svn     location-->
   <AutoCheckout>true</AutoCheckout><!-- master node has the right to extract artifacts from svn-->
   <RepositoryType>svn</RepositoryType> <!-- repo type : svn -->
    <SvnUrl>https://svn.xxx.com/yyy/zzz/</SvnUrl> <!-- url of the svn location-->
    <SvnUser>aaa@bbb.com</SvnUser> <!-- credentials - user name -->
    <SvnPassword>vvvvv</SvnPassword> <!-- credentials password -->
    <SvnUrlAppendTenantId>false</SvnUrlAppendTenantId><!--Enable tenant-specific
    configurations-->                
</DeploymentSynchronizer> 

Points to ponder :
We need to set value as true to <AutoCommit>,  <AutoCheckout> entries.

Now we need to change the axis.xml in-order to reflect the dep-sync features.

Master-node : axis2.xml configuration file (..../wso2esb-4.7.0_master/repository/conf/axis2/axis2.xml)  

<clustering class="org.apache.axis2.clustering.tribes.TribesClusteringAgent" enable="true">

    <!--The membership scheme used in this setup. The only values supported at the moment are "multicast" and "wka"
           1. multicast - membership is automatically discovered using multicasting
           2. wka - Well-Known Address based multicasting. Membership is discovered with the help of one or more nodes running at a Well-Known Address. New members joining a cluster will first connect to a well-known node, register with the well-known node and get the membership list from it. When new members join, one of the well-known nodes will notify the others in the group. When a member leaves the cluster or is deemed to have left the cluster, it will be detected by the Group Membership Service (GMS) using a TCP ping mechanism.-->

        <parameter name="membershipScheme">wka</parameter>

       <!-- The host name or IP address of this member -->
        <parameter name="localMemberHost">xx.xx.xx.xx</parameter>

      <!-- The TCP port used by this member. This is the port through which other        nodes will contact this member-->
        <parameter name="localMemberPort">4000</parameter>

        <!--The clustering domain/group. Nodes in the same group will belong to the same multicast domain. There will not be interference between nodes in different groups. -->
        <parameter name="domain">wso2.carbon.domain</parameter>

Points to ponder :
clustering should be enabled. (enable="true")

That is all we consider for the moment on the manager-node. Now we need to seek into worker-node clustering configurations.

For worker-node there are a few additional modifications need to be configured. Here is how worker-node carbon.xml differs from the manager-node.

Slave-node : carbon.xml configuration file  (..../wso2esb-4.7.0_slave/repository/conf/carbon.xml)  

<!-- Ports offset. This entry will set the value of the ports defined below to the define value + Offset. e.g. Offset=2 and HTTPS port=9443 will set the effective HTTPS port to 9445 -->

 <Offset>1</Offset>

 <DeploymentSynchronizer>
        <Enabled>true</Enabled>
        <AutoCommit>false</AutoCommit>
        <AutoCheckout>true</AutoCheckout>
        <RepositoryType>svn</RepositoryType>
        <SvnUrl>https://svn.xxx.com/yyy/zzz/</SvnUrl>
        <SvnUser>aaa@bbb.com</SvnUser>
        <SvnPassword>vvvvv</SvnPassword>
        <SvnUrlAppendTenantId>false</SvnUrlAppendTenantId>
  </DeploymentSynchronizer>

Points to ponder :
Note the <AutoCommit>false</AutoCommit> entry. This is because the  slave-node should only be able to check-out from the svn, what master-node had commited to svn.

Slave-node : axis2.xml configuration file  (..../wso2esb-4.7.0_slave/repository/conf/axis2/axis2.xml)  

<clustering class="org.apache.axis2.clustering.tribes.TribesClusteringAgent" enable="true">

  <parameter name="membershipScheme">wka</parameter>

  <parameter name="domain">wso2.carbon.domain</parameter>

   <!-- The host name or IP address of this member -->
        <parameter name="localMemberHost">yy.yy.yy.yy</parameter>
        <parameter name="localMemberBindAddress">zz.zz.zz.zz</parameter>

        <!-- The TCP port used by this member. This is the port through which other nodes will contact this member -->
        <parameter name="localMemberPort">4000</parameter>
        <parameter name="localMemberBindPort">4000</parameter>

  <members>
            <member>
                <hostName>xx.xx.xx.xx</hostName>
                <port>4000</port>
            </member>
   </members>

Points to ponder :
clustering should be enabled. (enable="true")
Since from openstack cloud instance we can define both public and private interfaces for a given space instance we need to add an additional entry -  "localMemberBindAddress" - which declares the public IP of the space instance to the outside world. "localMemberHost" defines the private IP of the cloud space instance.
<hostName>xx.xx.xx.xx</hostName> , here refers the manager-node IP address which is the known member of the cluster to all slave-nodes. 
<port>4000</port> refers the manager-node port , slave should establish the connection with. 


Ultimately we are now ready with the clustering set-up. Now we need to start two severs separately. To do so,

--> navigate to wso2esb-4.7.0_master/bin folder from the console and type,
                     sh wso2server.sh.
--> navigate to wso2esb-4.7.0_slave/bin folder from the console and type,
                     sh wso2server.sh -DworkerNode = true

You now can deploy artifacts to manager-node and observe they are automatically getting deployed at the worker-node. For example if you want to deploy artifacts using a cApp (myCarbonApp.car) with deployment synchronizing feature all you need to do is to place your myCarbonApp.car inside the folder ..../wso2esb-4.7.0_master/repository/carbonapps/0/. After deploying artifacts inside myCarbonApp.car file to its relevant artifact folders the manager-node will auto commit the artifacts to the relevant folder structure in the svn location and the slave-node will perform svn chekout and deploy artifacts to its relevant artifact folders.

Hence deployment synchronizer is a hassle-free way to deploy numerous number of artifacts across several computers in a cluster at the same time.

Saturday, September 7, 2013

Lets move into another step ahead ....

Hope you will enjoy my online written articles to be published very soon in my official blog. 
These articles will explore deep variety of topics spanning from ground level to galaxy. Please cross your fingers folks.

Tuesday, June 25, 2013

Working with Jetty server


Please visit http://www.eclipse.org/jetty/ for more information about Jetty. Jetty server is famous among many IT professionals because it can run as a standalone application server or just as easily embed it in an application. You can use Jetty to host your web applications.


Download link : http://mirrors.xmission.com/eclipse/jetty/

Installing Jetty :

a) Save any distribution onto your desktop. (Eg : jetty-distribution-8.1.10.v20130312.tar.gz)
b) To unpack it type,  sudo tar xfz jetty-distribution-8.1.10.v20130312.tar.gz in your command console.
c) Type , sudo java -jar start.jar jetty.port=8080.
d) Now you should be able to access your Jetty server home page. Just type http://localhost:8080 in your browser url.

* you can use any other port number (eg : 80)

To deploy your web application in jetty :

a) Simply create a folder (myapp) inside  /jetty-distribution-8.1.10.v20130312/webapps folder.
b) Now place your web application inside /jetty-distribution-8.1.10.v20130312/webapps/myapp folder.
c) Type http://localhost:8080/myapp in your browser url.
d) You should be able to access your deployed web application through your browser now.








Tuesday, June 18, 2013


Writing Platform Integration Tests 

Platform integration tests can be useful when you want to run your tests in an environment which comprises of multiple products. Integration of these products which develop a business use case can be  considered as a platform.

Here I am going to illustrate the integration of wso2as-5.1.0 and wso2esb-4.6.0 product servers in the platform and how to write a platform test case to test a given scenario.

You can find binary distributions of wso2as-5.1.0 and wso2esb-4.6.0 from the respective links below.

http://wso2.com/products/application-server/

http://wso2.com/products/enterprise-service-bus/


Resources need,

http://wso2.com/files/ESB-Sample-02.zip

Sample scenario,

http://wso2.com/library/articles/2011/01/wso2-esb-by-example-service-chaining

Before you write your test you need to do some configuration changes in-order to reflect the product integration inside the platform.

Following are the changes you need to do.

automation.properties  file should be amended as follows.

product.list=AS,ESB

as.host.name=localhost
as.http.port=9765
as.https.port=9445

esb.host.name=localhost
esb.http.port=9763
esb.https.port=9443
esb.nhttp.port=8280
esb.nhttps.port=8243

Note:

 Please refer http://wso2.com/library/articles/2011/01/wso2-esb-by-example-service-chaining again to understand the need for these changes. Below is a short description about these changes.

* Since we are using two product servers we need to assign product.list =AS,ESB.
* As we can not run both the servers on the same port we need to change a port of a one server (wso2as-5.1.0 ) to a different port number. In-order to do so go to wso2as-5.1.0/repository/conf/carbon.xml in your wso2as-5.1.0 distribution and search for     <Offset>0</Offset> . Now in-order to run wso2as-5.1.0 server on a different port (9445) change the value of <Offset> to 2. (<Offset>2</Offset>). Since the default port for wso2as-5.1.0 is 9443 as we just changed the Offset value, once you start the server it will run on port number 9445. Hence the http port will become 9765.
*As you changed the "as" configurations you can let the esb server to run on its default ports (9443,9763).

Your class should look something similar to this.

package org.wso2.carbon.automation.platform.scenarios.esb;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.carbon.automation.api.clients.jarservices.JARServiceUploaderClient;
import org.wso2.carbon.automation.api.clients.registry.ResourceAdminServiceClient;
import org.wso2.carbon.automation.core.ProductConstant;
import org.wso2.carbon.automation.core.utils.endpointutils.EsbEndpointSetter;
import org.wso2.carbon.automation.core.utils.environmentutils.EnvironmentBuilder;
import org.wso2.carbon.automation.core.utils.environmentutils.EnvironmentVariables;
import org.wso2.carbon.automation.utils.as.ASIntegrationTest;
import org.wso2.carbon.automation.utils.axis2client.AxisServiceClient;
import org.wso2.carbon.automation.utils.esb.ESBBaseTest;

import javax.activation.DataHandler;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import static org.testng.Assert.assertTrue;

/**
 * Implement the scenario described at
 * http://wso2.com/library/articles/2011/01/wso2-esb-by-example-service-chaining
 * Pre-requests : as server should run on port 9445 , esb should run on port 9443
 */
public class CreditPolicyTestCase extends ASIntegrationTest {

    private static final Log log = LogFactory.getLog(CreditPolicyTestCase.class);
    private ESBBaseTest esbBaseTest;

    @BeforeClass(alwaysRun = true)
    public void init() throws Exception {
        super.init();
        esbBaseTest = new ESBBaseTest();
        uploadResourcesToGovernanceRegistry();
    }

    @AfterClass(alwaysRun = true)
    public void jarServiceDelete() throws Exception {

        deleteService("CreditService");
        deleteService("PersonInfoService");

        log.info("esb-samples-1.0-SNAPSHOT services deleted successfully");
    }

    @Test(groups = "wso2.as", description = "Upload jar service and verify deployment")
    public void asServerJarServiceUpload() throws Exception {

        JARServiceUploaderClient jarServiceUploaderClient =
                new JARServiceUploaderClient(asServer.getBackEndUrl(),
                        asServer.getSessionCookie());
        List<DataHandler> jarList = new ArrayList<DataHandler>();
        URL url = new URL("file://" + ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION +
                "artifacts" + File.separator + "AS" + File.separator + "jar" + File.separator +
                "artifact5" + File.separator + "esb-samples-1.0-SNAPSHOT.jar");
        DataHandler dh = new DataHandler(url);
        jarList.add(dh);

        jarServiceUploaderClient.uploadJARServiceFile("", jarList, dh);

        isServiceDeployed("CreditService");
        isServiceDeployed("PersonInfoService");
        log.info("esb-samples-1.0-SNAPSHOT.jar uploaded successfully");
    }

    @Test(groups = "wso2.esb", description = "update synapse config", dependsOnMethods = "asServerJarServiceUpload")
    public void testUpdateSynapseConfig() throws Exception {

        String synapseConfigPath = ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION + File.separator +
                "artifacts" + File.separator + "ESB" + File.separator + "synapseconfig" +
                File.separator + "service_chaining" + File.separator + "synapse.xml";

        EsbEndpointSetter esbEndpointSetter = new EsbEndpointSetter();
        OMElement synapseConfigOM =
                esbEndpointSetter.setEndpointURL(new DataHandler(new URL("file://" + synapseConfigPath)));
        esbBaseTest.updateESBConfiguration(synapseConfigOM);
    }

    @Test(groups = "wso2.as", description = "invoke credit proxy service", dependsOnMethods = "testUpdateSynapseConfig")
    public void invokeService() throws Exception {

        AxisServiceClient axisServiceClient = new AxisServiceClient();

        String endpoint = esbBaseTest.getBackEndServiceUrl("CreditProxy");
        OMElement response = axisServiceClient.sendReceive(createPayLoad(), endpoint, "credit");
        log.info("Response : " + response);
        assertTrue(response.toString().contains("<ns:return>true</ns:return>"));
    }

    private void uploadResourcesToGovernanceRegistry() throws Exception {  // uploads personToCredit.xslt to esb governance
        EnvironmentBuilder builder = new EnvironmentBuilder().esb(Integer.parseInt(userInfo.getUserId()));
        EnvironmentVariables esbServer = builder.build().getEsb();
        ResourceAdminServiceClient resourceAdminServiceStub =
                new ResourceAdminServiceClient(esbServer.getBackEndUrl(), esbServer.getSessionCookie());

        resourceAdminServiceStub.deleteResource("/_system/governance/xslt");
        resourceAdminServiceStub.addCollection("/_system/governance/", "xslt", "",
                "Needed xslt files for credit policy");

        URL url = new URL("file://" + ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION +
                "artifacts" + File.separator + "ESB" + File.separator + "synapseconfig" + File.separator + "service_chaining"
                + File.separator + "personToCredit.xslt");
        DataHandler dh = new DataHandler(url);   // creation of data handler .

        assertTrue(resourceAdminServiceStub.addResource(
                "/_system/governance/xslt/personToCredit.xslt", "application/xml", "Needed xslt files for credit policy", dh),
                "PersonToCredit.xslt file upload to /_system/governance/xslt/ failed");
    }

    private static OMElement createPayLoad() {    // creation of payload
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://samples.esb.wso2.org", "ns");
        OMElement getOme = fac.createOMElement("credit", omNs);

        OMElement getID = fac.createOMElement("id", omNs);
        OMElement getAmount = fac.createOMElement("amount", omNs);
        getID.setText("100");
        getAmount.setText("200");

        getOme.addChild(getID);
        getOme.addChild(getAmount);

        return getOme;
    }
}


Important points :

1. uploadResourcesToGovernanceRegistry() method is to upload the "personToCredit.xslt" to esb. (This is an alternative for manually putting this to resources directory of WSO2 ESB.

2. createPayLoad() implements the soapui request mentioned in the "Sample scenario" link.

3. your synapse.xml file should also reflect the changes made inside uploadResourcesToGovernanceRegistry(). Ultimate synape.xml file should look like this. (Note the change.  <xslt key="gov:/xslt/personToCredit.xslt">)


<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
    <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
        <parameter name="cachableDuration">15000</parameter>
    </registry>
    <proxy name="CreditProxy"
           transports="https http"
           startOnLoad="true"
           trace="disable">
        <target>
            <inSequence>
                <log level="full">
                    <property name="sequence" value="inSequence - request for CreditProxy"/>
                </log>
                <property xmlns:sam="http://samples.esb.wso2.org"
                          name="ORG_ID"
                          expression="//sam:credit/sam:id"/>
                <property xmlns:sam="http://samples.esb.wso2.org"
                          name="ORG_AMOUNT"
                          expression="//sam:credit/sam:amount"/>
                <enrich>
                    <source type="inline" clone="true">
                        <sam:get xmlns:sam="http://samples.esb.wso2.org">
                            <sam:id>?</sam:id>
                        </sam:get>
                    </source>
                    <target type="body"/>
                </enrich>
                <enrich>
                    <source type="property" clone="true" property="ORG_ID"/>
                    <target xmlns:sam="http://samples.esb.wso2.org" xpath="//sam:get/sam:id"/>
                </enrich>
                <log level="full">
                    <property name="sequence" value="inSequence - request for PersonInfoService"/>
                </log>
                <property name="STATE" value="PERSON_INFO_REQUEST"/>
                <send>
                    <endpoint key="PersonInfoEpr"/>
                </send>
            </inSequence>
            <outSequence>
                <switch source="get-property('STATE')">
                    <case regex="PERSON_INFO_REQUEST">
                        <log level="full">
                            <property name="sequence"
                                      value="outSequence - STATE 01 - response from PersonInfoService"/>
                        </log>
                        <xslt key="gov:/xslt/personToCredit.xslt">
                            <property name="amount" expression="get-property('ORG_AMOUNT')"/>
                        </xslt>
                        <log level="full">
                            <property name="sequence"
                                      value="outSequence - STATE 01 - request for CreditService"/>
                        </log>
                        <property name="STATE" value="CREDIT_REQUEST"/>
                        <send>
                            <endpoint key="CreditEpr"/>
                        </send>
                    </case>
                    <case regex="CREDIT_REQUEST">
                        <log level="full">
                            <property name="sequence"
                                      value="outSequence - STATE 02 - response from CreditService"/>
                        </log>
                        <send/>
                    </case>
                </switch>
            </outSequence>
        </target>
        <!--<publishWSDL uri="file:resources/CreditProxy.wsdl"/>-->
    </proxy>
    <!--<localEntry key="xslt" src="gov:/xslt/personToCredit.xslt"/>-->
    <endpoint name="CreditEpr">
        <address uri="http://localhost:9765/services/CreditService/"/>
    </endpoint>
    <endpoint name="PersonInfoEpr">
        <address uri="http://localhost:9765/services/PersonInfoService/"/>
    </endpoint>
    <sequence name="fault">
        <log level="full">
            <property name="MESSAGE" value="Executing default 'fault' sequence"/>
            <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
            <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
        </log>
        <drop/>
    </sequence>
    <sequence name="main">
        <in>
            <log level="full"/>
            <filter source="get-property('To')" regex="http://localhost:9000.*">
                <send/>
            </filter>
        </in>
        <out>
            <send/>
        </out>
    </sequence>
</definitions>

Tuesday, March 12, 2013

Jaggery Tests

How do I deal with jaggery .... ?????

Jaggery ???? 


Jaggery is a framework to write webapps and HTTP-focused web services for all aspects of the application: front-end, communication, Server-side logic and persistence in pure Javascript. One of the intents of this framework is to reduce the gap between writing web apps and web services. Importantly, Jaggery is open-source and released under Apache 2.0                                                                                                  
                                                                                                                                (Definition http://jaggeryjs.org/)
   
In this example I am going to show you how to upload a jaggery application to the web , read whats inside the a jaggery page (jaggery files contains the extension ".jag") and also how to delete / remove the uploaded jaggery application.

1. In the first place we need to create a package (jaggery/integration/testsapplicationobject) inside our project structure. (svn/carbon/platform/branches/4.1.0/products/as/5.1.0/modules/integration/tests-new/src/test/java)

2. Now create a java class called ApplicationObjectTestCase.java and extend ASIntegrationTest.java *.

3. Create a method call jaggeryFileUpload() inside your ApplicationObjectTestCase.java class. Now call the init() method of the ASIntegrationTest.java* class. This will enable us to use its environmental
properties inside our test class.
eg:    super.init();

4. Invoke the JaggeryApplicationUploaderClient from the Test Automation Framework. Remember we need to pass the server backendurl and a session cookie. How can we do it ?? since we extended ASIntegrationTest.java  its so simple now. its just a matter of calling its asServer environmental variable and get the job done. Here is the sample code,

JaggeryApplicationUploaderClient jaggeryAppUploaderClient  =
                new JaggeryApplicationUploaderClient(asServer.getBackEndUrl(),
                        asServer.getSessionCookie()); 

5. By using this 'jaggeryApplicationUploaderClient' object we can now invoke one of its methods called uploadJaggeryFile(java.lang.String fileName, java.lang.String filePath) which can be used to upload our jaggery application (testapp.zip) to the server. Do it as follows,

jaggeryAppUploaderClient.uploadJaggeryFile("testapp.zip",
                ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION + "artifacts" +
                        File.separator + "AS" + File.separator + "jaggery" + File.separator +
                        "testapp.zip");

Please note that ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION refers to resources directory.
(svn/carbon/platform/branches/4.1.0/products/as/5.1.0/modules/integration/tests-new/src/test/resources). We can use this resources directory to place our artifacts in this case 'testapp.zip is the artifact which comprises application.jag file which we will be using very shortly for testing purposes.

6. Fine. whats next ??? ok we uploaded a jaggery appliction to the web server. Shouldn't we check whether its services were deployed successfully ?? . hmmmm....... how to do it??? . The answer to the last question is simple. Wso2 Test automation framework contains a class called WebAppUtil.java which contains a method waitForWebAppDeployment(java.lang.String serviceUrl, java.lang.String content). As the method signature indicate we need to pass our service url and contents of the jaggery page we are testing.

Inside testapp.zip we have a jaggery file called application.jag. Since we are going to read whats inside this jaggery file our serviceUrl will be htpps://yourip/.........


WebAppUtil.waitForWebAppDeployment(asServer.getWebAppURL() + "/testapp/application.jag",
                                                                                                                                       "test jaggery application value"); 

7. Now in order to read whats inside application.jag file firstly we need to establish a http connection to the serviceUrl. Therefore we shall begin our coding like below.

URLConnection jaggeryServerConnection;
                                     URL jaggeryURL = new URL(asServer.getWebAppURL() + "/testapp/application.jag");


  long timeoutExpiredMs = 500;
        URLConnection jaggeryServerConnection = null;
        try {
            jaggeryServerConnection = url.openConnection();

        } catch (IOException e) {
        }

        while ((jaggeryServerConnection == null) && (System.currentTimeMillis() <= timeoutExpiredMs)) {
            try {
                jaggeryServerConnection = url.openConnection();
            } catch (IOException e) {
            }

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }

       assertNotNull(jaggeryServerConnection, "Connection establishment failure"); 
       // checking the connection using       testNG

8. Connection established. Now we can use a buffered reader to read the contents inside application.jag file. Hence,

   long timeoutExpiredMs = 500;
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    jaggeryServerConnection.getInputStream()));

        } catch (IOException e) {
        }

        while ((in == null) && (System.currentTimeMillis() <= timeoutExpiredMs)) {
            try {
                in = new BufferedReader(
                        new InputStreamReader(jaggeryServerConnection.getInputStream()));
            } catch (IOException e) {
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }

assertNotNull(in, "Input stream failure");

9.  Now we can get the response and validate it.

        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            response = inputLine;
        }

        in.close();
        log.info("Response: " + response);
        assertNotNull(response, "Response cannot be null");
        assertEquals(response, "test jaggery application value");

10. In order to delete /remove the uploaded jaggery app from our server we can call WebAppAdminClient.java  class from 'Test Automation Framework' and use its deleteWebAppFile(java.lang.String fileName) method. To do so,

  WebAppAdminClient webAppAdminClient = new WebAppAdminClient(asServer.getBackEndUrl(),   
                                                                                                                                             asServer.getSessionCookie());
  webAppAdminClient.deleteWebAppFile("testapp");

Thats all folks. We are done with our jaggery app testing.




Notes:

* ASIntegrationTest.java contains some useful utility methods which we can use regularly inside our test classes. It contains set of environmental variables which refers to the appserver properties (serviceUrl , backendUrl , session cookies etc. ) and also authenticates the server login (using its init() method) allowing us to use its environmental properties inside our test classes as mentioned earlier. Following are some interpretations / sample values for these environmental variables which are useful for this illustration. 

Friday, March 8, 2013

Your first integration test experience

       
Illustration here is a testing scenario in which we can upload JAXWS web app to the server , deploy and invoke its services for testing purposes. These are the steps you need to follow.
( Note : you can start writing your tests in the following location according to your as server version :
location/platform/branches/x.x.x/products/as/x.x.x/modules/integration/tests-new
eg: /home/xxxx/svn/carbon/platform/branches/x.x.x/products/as/x.x.x/modules/integration/tests-new)

1. Create a package and add a new test class. (eg: jaxwssampleservice /  JAXWSSampleTestCase.java)

2. Extend ASIntegrationTest.java class. (ASIntegrationTest.java contains some useful utility methods which we can use regularly inside our test classes.)

3. Create a method called init() in JAXWSSampleTestCase.java class under the annotation @BeforeClass . Now invoke init() method of ASIntegrationTest.java inside the init() method we just created.
eg:
@BeforeClass(alwaysRun = true)
public void init() throws Exception {
super.init();
}

(This enables us to get the backendurl of the server and a session cookie as described in step 5.)

4. We can use @Test annotation to add test cases to our test class. Create a method
(eg : webApplicationUpload ) inside our JAXWSSampleTestCase.java test class.

5 .In-order to upload our artifact to the app server we can invoke the relevant service client from the test automation framework. Since we are testing JAXWS service we can invoke JAXWSWebappAdminClient to upload the artifact "java_first_jaxws.war" to the server. (Note that we need to pass the backendurl and the session cookie when creating an instance from JAXWSWebappAdminClient. We can derive values for these arguments by invoking asServer environment variable of ASIntegrationTest.java inside JAXWSWebappAdminClient constructor.)
eg :
JAXWSWebappAdminClient   jaxwsWebappAdminClient =
                            new JAXWSWebappAdminClient(asServer.getBackEndUrl(), asServer.getSessionCookie());


We can use uploadWebapp method of JAXWSWebappAdminClient.java class to upload the artifact. (Note that we need to provide the location where "java_first_jaxws.war" resides in our application)
eg:
We can add a package (artifacts/AS/jaxws) under resources directory and place our java_first_jaxws.war inside it. Therefore our artifact location would now become :

String location = ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION +"artifacts" + File.separator + "AS" + File.separator + "jaxws" + File.separator +"java_first_jaxws.war";

Now we need to pass this location and the name of the artifact to the uploadwebapp method. We can do this using the instance we created from JAXWSWebappAdminClient.java.
eg:
jaxwsWebappAdminClient.uploadWebapp(location, "java_first_jaxws.war");

6. To check whether the deployment of the service was successful we can call waitForServiceDeployment method of AxisServiceClientUtils.java class.
(Note that we need to provide the service url of the service we deployed. If java_first_jaxws.war contains a service “hello_world” we can verify the deployment as follows)
AxisServiceClientUtils.waitForServiceDeployment(asServer.getWebAppURL() +
"/java_first_jaxws/services/hello_world");    

7. For this illustration we will call “SayHiToUser” operation inside “hello_world“ service. To invoke the service create a method (serviceRequest) under the annotation @Test and create the request as follows.

String request = "<ns2:sayHiToUser xmlns:ns2=\"http://server.hw.demo/\">" +
"<arg0><name>Galaxy</name></arg0></ns2:sayHiToUser>";

Create a new method createPayload .To create the payload pass the request made to it.

private OMElement createPayload(String request) throws XMLStreamException {
return new StAXOMBuilder(new ByteArrayInputStream(request.getBytes())).getDocumentElement();
}

8. Create an instance of AxisServiceClient.java class. In order to send the request we can call sendReceive method of this class. This will return the response from the server.
eg:
String endpoint = asServer.getWebAppURL() + "/java_first_jaxws/services/hello_world";
OMElement response = axisServiceClient.sendReceive(createPayload(request), endpoint,
"sayHiToUser");

9. We can assert the response using TestNG.
assertEquals(("<ns2:sayHiToUserResponse xmlns:ns2=\"http://server.hw.demo/\">" +
"<return>Hello Galaxy</return></ns2:sayHiToUserResponse>"),
response.toString().trim());

10. After completion of the response validation we can delete / remove the artifact uploaded to the app server by invoking deleteWebAppFile method of WebAppAdminClient.java class. We can do this under @AfterClass annotation.
eg:
@AfterClass(alwaysRun = true)
public void webApplicationDelete() throws Exception {
WebAppAdminClient webAppAdminClient = new WebAppAdminClient(asServer.getBackEndUrl(),
asServer.getSessionCookie());
webAppAdminClient.deleteWebAppFile("java_first_jaxws.war");
log.info("java_first_jaxws.war deleted successfully");
}