Wednesday, November 13, 2013

Advertising with WSO2 API Manager by Publishing to External API Store

 In WSO2 API Manager 1.5.0, we don't have the support of API sharing across tenants because with the current design, there is not way to replicate API metadata that should be written to the databases and registries along with the API configurations. Therefore, there is no straightforward approach to replicate a set of tenant APIs from one tenant to others.
 













But we have the Advertising feature, where we have the capability of displaying APIs published by tenant 1, in tenant 2's API store. However, tenant 2's users will not be able to subscribe to the APIs published by tenant 1.


To do this, you need to uncomment the <ExternalAPIStores> element in $APIM_HOME/repository/conf/api-manager.xml. Tenant's external API stores can be configured as follows by giving the tenant domain, tenant admin's user name and password
     <ExternalAPIStore id="Store1" type="wso2">
            <DisplayName>Store1</DisplayName>
            <Endpoint>http://localhost:9763/store?tenant=abc.com</Endpoint>
            <Username>abc@abc.com</Username>
            <Password>abc123</Password>
        </ExternalAPIStore>


Imagine you logged into the API Publisher as the tenant xyz.com. Then in the UI, there will be a tab available saying "External API Store". There, you will be able to see all the External tenant details you have configured earlier via the api-manager.xml. Now tenant xyz.com can publish its API, so that tenant abc.com too can see it.
Now if you login to tenant abc.com's API store, you will see the API advertised or published by tenant xyz.com. (But still tenant abc.com will not be able to subscribe to it using abc.com's credentials. )

Await for the next WSO2 API Manager release, which will allow you to subscribe to the Advertised API regardless of the tenant. 

Friday, November 8, 2013

Experience What is New in Mulit Tenanted WSO2 App Factory


App Factory is a multi-tenanted Enterprise platform that enables multiple project teams to collaboratively create, run and manage enterprise applications.

This is a one stop shop, which helps you to manage your agile application development, testing and releasing process by providing all the necessary tools and options. This includes
 - Continous Build system (Jenkins build farm)
 - Source control system (Git repo)
 - User management system (LDAP)
 - Issue tracking system (WSO2 Issue Tracker)
 - Application hosting environment (WSO2 AS)
 - API management environment (WSO2 API Manager)
 - Databases and datasource management environment (MySQL)



















The inceptional design of AF (App Factory) was such that, an application was considered as a tenant. There was no organization concept attached in the old AF story.

But now the story has been matched with the real organizational behavior in an industry. In the current implementation, we have considered this organizational concept into picture. Now, an ORGANIZATION IS A TENANT.

You can register an Organization in App Factory and you will be getting a tenant space for your organization. In their you can have multiple applications belonging to your organization. (Earlier you are getting a tenant space each time you create an application. Now tenant space is given at the creation of organization)

Few architectural changes in essence



New Architecture
Old Architecture
Cartridge subscription happens at
Tenant creation
Application creation
Jenkins allocation
  • For each tenant, jenkins_home and maven_home is set.
  • Jenkins.war is copied to all tenants
  • Jenkins.war has a context.xml that contains tenant specific domain info
  • Jenkins_home and maven_home is shared among applications
  • Single Jenkins.war for all the apps
Git repo creation
No space is created at tenant creation. At application creation, a repo is created with the tenant name appended to the repo url as $git_basedir/abc.com/app1.git
At application creation. Created repo is $git_basedir/app1.git
Issue tracker
Any user in an organization can see all the issues of all apps in that organization.
App level isolation on the issues.
User Management
  • Roles (Dev, QA, DevOps, AppOwner) are for the organization level. Not for the application level
  • Multiple app owners per app
  • Developers can’t create apps
  • Roles for the users are in application level
  • Single app owner per app
  • Developers can create apps



We have put up all these latest changes into a preview hosting, so you can get a glimpse of it.
To experience all these latest changes visit
https://cloudpreview.wso2.com/ and register your tenant now and start playing around with it.

Hope you will enjoy your new AF experience.

Monday, August 19, 2013

WSO2 CARAMEL - Caramelize your AS environment


Have you ever tried writing the Front End of your application in Jaggery?
Jaggery is a framework for writing web apps and HTTP web services which you can implement front end and server side logic in pure java script.  You can get the latest taste of jaggery in here.




Do you know Caramel? Caramel is a framework built for Jaggery while enforcing a standard for developing web applications using Jaggery.



Latest WSO2 UES server is enriched with Caramel framework. Do you want to make your service hosting environment Caramelize? You can follow the steps below:

  1. Download a latest AS 5.2.0 SNAPSHOT from here.(You need the latest AS because, you need latest jaggery features)
  2. Put the caramel, handlebars and markdown modules into your AS_HOME/modules that reside inside caramel feature after building the caramel source.
  3. Test your environment by deploying the sample
Congratulations!
If you are able to view the UI of the sample with nice icons, without any errors, then you have successfully installed caramel features on your AS environment.

Now you are ready to taste the jaggery with caramel.


Friday, July 12, 2013

Create Artifacts for WSO2 App Factory using WSO2 Developer Studio


After a couple of iterations, now the  WSO2 App Factory is released. You can experience the live version of WSO2 App Factory from here.
The Developer Studio too is compatible with creating artifacts and deploying them into App Factory.

The blog below shows how to work on App Factory seamlessly with Developer Studio.



  1. Download and install Eclipse Juno distribution - eclipse-jee-juno-SR2-linux-gtk-x86_64.tar.gz
  2. Download latest Dev Studio distribution from http://wso2.com/more-downloads/developer-studio/
  3. Start Eclipse and install the above Dev Studio distribution. This contains the latest App Factory tooling support as well.
  4. Go to Windows --> Open Perspective --> App Factory


  1. Once click on App Factory, this will prompt a window to enter the Host, Username and Password to connect to App Factory.

  1. Once provided the above, it opens up the App Factory views as below.
  1. In the Application List view, go to an app, Select an app --> version --> checkout --> Add to workspace
The particular App version will be appeared in the Project Explorer.

  1. Right click on app in project explorer --> Team --> Share Project --> in the wizard, select Git
Select the project and click Finish.

  1. Change a file in the application. The changes will be shown as below. (with a “>”)

  1. Right click changed file --> Team -->Commit.
Add a commit message --> Commit 
Right click the file --> Team --> Push to Upstream

Tuesday, May 7, 2013

I/O exception (org.apache.http.NoHttpResponseException) caught when processing request: The target server failed to respond

I was continuously getting this error when trying to try out this code.


May 6, 2013 5:53:51 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request: The target server failed to respond
May 6, 2013 5:53:51 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: Retrying request
May 6, 2013 5:54:53 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request: The target server failed to respond
May 6, 2013 5:54:53 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: Retrying request
May 6, 2013 5:55:54 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request: The target server failed to respond
May 6, 2013 5:55:54 PM org.apache.http.impl.client.DefaultRequestDirector execute
INFO: Retrying request
Exception in thread "main" org.apache.http.NoHttpResponseException: The target server failed to respond
at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:101)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:252)
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:281)
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:227)
at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:229)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:298)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:447)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at QuickStart.main(QuickStart.java:107)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)

Finally after wasting about 5-6 hours of my time, :( found that this was due to an old HTTPClient jar. I had earlier used the version 4.0 org.apache.httpcomponents.httpclient. 
When upgraded this to 4.1, the issue got fixed. (source from a mail archive)

Friday, February 22, 2013

Extract a value of an XML type attribute using WSO2 ESB

Let's say you have an XML input with some elements as below.

<SOAP-ENV:Body>
        <Publish>
            <Notification
                message="&lt;RegistraionNotificationEvent NotificationType=&quot;Place&quot;>&lt;DeviceLocPlace
                timestamp=&quot;1361210060855&quot; accuracy=&quot;344.0&quot;
                macAddress=&quot;7b:29:a8:8b:e4:f8&quot; lastSeen=&quot;7&quot;
                sourceTimestamp=&quot;1361209904211&quot; x=&quot;171.34&quot; y=&quot;104.513&quot;/>&lt;/RegistraionNotificationEvent>" />
        </Publish>
    </SOAP-ENV:Body>

 You need to extract out the macAddress which is inside the message attribute. How can we do that?


If you closely look at this input, you would see, the macAddress stays inside the value of the attribute "message". But this message attribute carries another XML element which comes as a String. 

Now what? 

This is where WSO2 ESB Script mediator comes into rescue.
With just the following piece of configuration, you can extract out the  Mac Address.

<script language="js">
      <![CDATA[mc.setPayloadXML(new XML(mc.getPayloadXML()..*::Notification.@message.toXMLString()));]]></script>

The above segment converts the value of the attribute message into XML.

<property xmlns:ns="http://org.apache.synapse/xsd" name="mac" expression="//@macAddress" scope="default" type="STRING"/>

Using this segment, from the XML obtained above, you can extract out the macAddress part easily.

As handy as that...

Tuesday, February 5, 2013

Write Data to Cassandra with UTF-8 (String) validators

Cluster cassandraCluster = HFactory.createCluster("TestCluster",
                new CassandraHostConfigurator("localhost:9161"), credentials);
        Keyspace keyspace = HFactory.createKeyspace(keyspaceName, cassandraCluster);
       
        BasicColumnFamilyDefinition columnFamilyDefinition = new BasicColumnFamilyDefinition();
        columnFamilyDefinition.setKeyspaceName(keyspaceName);
        columnFamilyDefinition.setName(columnFamily);   
      columnFamilyDefinition.setComparatorType(ComparatorType.UTF8TYPE); 
 columnFamilyDefinition.setDefaultValidationClass(ComparatorType.UTF8TYPE.getClassName());
columnFamilyDefinition.setKeyValidationClass(ComparatorType.UTF8TYPE.getClassName());
       
        ColumnFamilyDefinition cfDef = new ThriftCfDef(columnFamilyDefinition);
       
        KeyspaceDefinition keyspaceDefinition =
            HFactory.createKeyspaceDefinition(keyspaceName, "org.apache.cassandra.locator.SimpleStrategy", 1, Arrays.asList(cfDef));
        cassandraCluster.addKeyspace(keyspaceDefinition);
       
       
        KeyspaceDefinition fromCluster = cassandraCluster.describeKeyspace(keyspaceName);
        cfDef = fromCluster.getCfDefs().get(0);
       
        columnFamilyDefinition = new BasicColumnFamilyDefinition(cfDef);
       
        BasicColumnDefinition columnDefinition = new BasicColumnDefinition();
       
        columnDefinition.setName(StringSerializer.get().toByteBuffer("lat"));
        columnDefinition.setIndexType(ColumnIndexType.KEYS);
        columnDefinition.setIndexName("lat");

columnDefinition.setValidationClass(ComparatorType.UTF8TYPE.getClassName());
        columnFamilyDefinition.addColumnDefinition(columnDefinition);
       
        columnDefinition = new BasicColumnDefinition();
        columnDefinition.setName(StringSerializer.get().toByteBuffer("lon"));   
        columnDefinition.setIndexType(ColumnIndexType.KEYS);
        columnDefinition.setIndexName("lon");

 columnDefinition.setValidationClass(ComparatorType.UTF8TYPE.getClassName());
        columnFamilyDefinition.addColumnDefinition(columnDefinition);
       
        columnDefinition = new BasicColumnDefinition();
        columnDefinition.setName(StringSerializer.get().toByteBuffer("timestamp"));   
  columnDefinition.setIndexType(ColumnIndexType.KEYS);
        columnDefinition.setIndexName("timestamp");
       columnDefinition.setValidationClass(ComparatorType.UTF8TYPE.getClassName());

        columnFamilyDefinition.addColumnDefinition(columnDefinition);
       
        cassandraCluster.updateColumnFamily(new ThriftCfDef(columnFamilyDefinition));
       
        for (int i = 90; i < 100; i++) {
            Mutator<String> mutator = HFactory.createMutator(keyspace, sser);
            String dID = Integer.toString(i);
            mutator.insert(dID, columnFamily, HFactory.createStringColumn("lat", lat));
            mutator.insert(dID, columnFamily, HFactory.createStringColumn("lon", lon));
            mutator.insert(dID, columnFamily,
                    HFactory.createStringColumn("timestamp", timestamp));
            mutator.execute();
        }



 You can check whether the created CFs are in proper and according to the required validation methods, by using a Cassandra-CLI tool. How to use this tool?
Refer my previous blog post       

A Smart and Quick Cassandra Client

Recently I wanted to get the internal details of a created Column Family. Here how I did that. 
  • Download the latest Cassandra server from here.
  • Extract to a preferred location. This will be known as CASS_HOME
  • Start up the Cassandra Server. For my task, I was using the built-in cassandra support that comes with WSO2 CEP. (The Cassandra server was running in localhost:9161)
  • Navigate to CASS_HOME/bin. From there execute the command below.
 sh cassandra-cli -h localhost -p 9161 -u admin -pw admin
  • The above command will take you to the Cassandra CLI console. Type the command below to get the key spaces:
show keyspaces;
  • That would show up fine details like validation class and comparator type etc. as follows:
Keyspace: LocationKeySpaceTestDemo_25:
  Replication Strategy: org.apache.cassandra.locator.SimpleStrategy
  Durable Writes: true
    Options: [replication_factor:1]
  Column Families:
    ColumnFamily: LocationDataTestDemo_25
      Key Validation Class: org.apache.cassandra.db.marshal.UTF8Type
      Default column value validator: org.apache.cassandra.db.marshal.UTF8Type
      Columns sorted by: org.apache.cassandra.db.marshal.UTF8Type
      GC grace seconds: 0
      Compaction min/max thresholds: 4/32
      Read repair chance: 0.0
      DC Local Read repair chance: 0.0
      Replicate on write: false
      Caching: KEYS_ONLY
      Bloom Filter FP chance: default
      Column Metadata:
        Column Name: lon
          Validation Class: org.apache.cassandra.db.marshal.UTF8Type
        Column Name: lat
          Validation Class: org.apache.cassandra.db.marshal.UTF8Type
        Column Name: timestamp
          Validation Class: org.apache.cassandra.db.marshal.UTF8Type
      Compaction Strategy: org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy
      Compression Options:
        sstable_compression: org.apache.cassandra.io.compress.SnappyCompressor
WARNING: Could not connect to the JMX on localhost:7199, information won't be shown.