Saturday, October 26, 2013

Flot Multi Bar Chart with Text based X-axis Ticks

Flot is a javascript plotting library for jquery which has some nice, interactive and easy to use features. Also unlike some other plotting libraries, almost all browsers supports flot graphs.

In this blog post I'm going to explain how to create a multi-bar chart using flot which has text based tick values in X axis. If you have ever played with Flot, you may know why I emphasize the phrase "text based tick values". Because flot normally supports only number based tick values in X-axis. As you read ahead the post, I'll show up the way how to get your texty ticks in X-axis.

As you can see in the above graph, I'm going to explain a multi bar chart drawn in order to display the number of successful and failed builds per each application. I will explain the code step by step in drawing the chart.


    
    
    
    

The first script tag contains the excanvas which is needed for support Internet Explorer versions below 9.

Flot placeholder is a jquery object and therefore you need to add the jquery.js. And then comes the file that is responsible for drawing all these flot charts which is jquery.flot.js. All the flot related library files can be checked out from the flot github location. (Note: To draw this graph we do not need all those files, but you might need them when trying with other types of graphs or other flot features.)

By default Flot doesn't come with the support for axis labels. The file jquery.flot.axislabels.js is included to make it possible to mark the axis names of the graph. In the above graph X-axis is named as App and Y-axis is named as No of builds. You can download that flot plugin from here.

In order to get the multi bar chart to work, we will have to include a plugin called jquery.flot.orderBars.js underneath the above files.  You can download the jquery.flot.orderBars.js from here.

Below given is the initial data set which I need to get a flot multi bar chart.



Now let's look at the format of the data that needs to be passed in to the flot graph.

The format of our initial data will be different from the data that is passed to the flot graph. As I have mentioned above, one reason for that is X-axis of the graph contains text based tick values such as "app4", "app5" and etc. But flot accepts only integer type ticks for the X-axis. So what we do is we come up with some integer mapping to represent each X-axis tick which is text based.

[1, "app4"],
[2, "app5"],
[3, "app6"],
[4, "app7"],
[5, "app8"]

So we map "app4", "app5" and etc with the integer we selected according to the above mapping.(instead of "app4" we put 1, for "app5" we put 2 and so on ) Hence the data that we will be passing to flot will take the following format.

var build_pass_data = [
                [1, 4],
                [2, 1],
                [3, 1],
                [4, 4],
                [5, 3]
            ];
var build_fail_data = [
                [1, 2],
                [2, 3],
                [3, 3],
                [4, 3],
                [5, 6]
            ];

var data = [
            {label: "PASS", data: build_pass_data, bars: {fillColor: "#336600"}, color: "#336600"},
            {label: "FAIL", data: build_fail_data, bars: {fillColor: "#E41B17"}, color: "#E41B17"}
           ]

Along with the data we will pass the fill color and the border color of the bars as well.

Then we have to tell the flot about the above mapping we used. That information is passed to the flot options. So our options section is as follows.

var options = {
                xaxis: {
                    min: 0,
                    max: 7,
                    mode: null,
                    ticks: [
                        [1, "app4"],
                        [2, "app5"],
                        [3, "app6"],
                        [4, "app7"],
                        [5, "app8"]
                    ],
                    tickLength: 0,
                    axisLabel: "App",
                    axisLabelUseCanvas: true,
                    axisLabelFontSizePixels: 12,
                    axisLabelFontFamily: "Verdana, Arial, Helvetica, Tahoma, sans-serif",
                    axisLabelPadding: 5
                }, yaxis: {
                    axisLabel: "No of builds",
                    tickDecimals: 0,
                    axisLabelUseCanvas: true,
                    axisLabelFontSizePixels: 12,
                    axisLabelFontFamily: "Verdana, Arial, Helvetica, Tahoma, sans-serif",
                    axisLabelPadding: 5
                }, grid: {
                    hoverable: true,
                    clickable: false,
                    borderWidth: 1
                }, legend: {
                    labelBoxBorderColor: "none", 
                    position: "right"
                }, series: {
                    shadowSize: 1, 
                    bars: {
                        show: true, 
                        barWidth: 0.13, 
                        order: 1
                    }
                }
            };


You might notice that under the "ticks" of xaxis we have placed our mapping. Also note how we have mentioned the X-axis name and the Y-axis name and their formatting.

Finally we need to pass the data and the options to the flot placeholder.

$.plot($("#placeholder"), data, options);

Additionally we have to specify the css of the placeholder,legend and etc for the better look and feels of the graph.

Now we are done with the Flot Multi-bar chart !!!

I have given the complete code below in-case you need any reference. (enclosed the following code within two html tags.)

Enjoy plotting with flot :)



    
    Flot Multi Bar Chart

    

    
    
    
    
    

    




Sunday, October 20, 2013

Tricky way to modify the userName SCIM claim in WSO2 Identity Server ( IS )

SCIM is an open standard for Identity Provisioning. In simple words SCIM is designed to create, maintain (read,update) and deactivate (delete) user accounts and related identities which reside in one or more systems/applications.

In this blog post, I'm going to explain a tricky way to modify the userName claim. Why I said a tricky way is because you will not be able to simply update it via a curl command as userName claim in carbon user stores is immutable. If you have ever tried updating the userName claim, you might have ended up with an error like this.

{"Errors":[{"description":"User name is immutable in carbon user store.","code":"500"}]}

In order to test this, start a WSO2 IS (tested with IS 4.5.0) connected to Active Directory as back-end data store. (You can do it by modifying the user-mgt.xml to connect to a AD instance.)

And then go to Configure --> Claim Management and select urn:scim:schemas:core:1.0

Now we have to map the SCIM claims to the existing attributes of the Active Directory. Because when we add a user via SCIM, apart from the userName SCIM claim there are four other SCIM attributes that is being added behind the scene.
( Make sure that you map String type attributes from the AD with the SCIM claims. You can find the AD attributes here. )

CLAIM URIAD Attribute
urn:scim:schemas:core:1.0:userName mail
urn:scim:schemas:core:1.0:meta.location streetAddress
urn:scim:schemas:core:1.0:meta.created homePhone
urn:scim:schemas:core:1.0:meta.lastModified pager
urn:scim:schemas:core:1.0:id homePostalAddress

Apart from the above mapping add the following mappings as well. (This is for better explanation of this post.)

CLAIM URIAD Attribute
urn:scim:schemas:core:1.0:name.givenName givenName
urn:scim:schemas:core:1.0:name.familyName company

First of all let's Create a user via SCIM. 

curl -v -k --user username:password --data "{"schemas":[],"name":{"familyName":"Madurapperuma", "givenName":"Tani"},"userName":"tanya@wso2.com","password":"testing123@"}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users

You will get a response payload as follows.

{"id":"5c05a64c-4f9b-44c7-9092-27cd4dc15640","schemas":["urn:scim:schemas:core:1.0"],"name":{"familyName":"Madurapperuma","givenName":"Tani"},"userName":"tanya@wso2.com","meta":{"lastModified":"2013-10-20T09:47:35","location":"https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640","created":"2013-10-20T09:47:35"}}

As I have mentioned above, you will not be able to update the userName SCIM claim after the creation of the user since the userName claim is immutable in carbon user store.

So with this tricky method you will be able to modify it.
Map the AD attribute that you have mapped to the userName claim to another SCIM claim and try modifying the newly mapped claim

In our case we have mapped AD attribute "mail" to SCIM claim "userName". So we will map it to SCIM claim "Emails" as well.

Now we have the following additional mapping as well.

CLAIM URI
AD Attribute
urn:scim:schemas:core:1.0:emails
mail

Now let's try updating SCIM claim "emails".

curl -v -k --user username:password -X PUT -d "{"schemas":[],"userName":"tanya@wso2.com", "emails":"tani@wso2.com"}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640

At this point, you might be worrying that it did not work seeing the response payload. Wait !!! The response payload that I got is as follows. 

{"id":"5c05a64c-4f9b-44c7-9092-27cd4dc15640","schemas":["urn:scim:schemas:core:1.0"],"userName":"tanya@wso2.com","emails":"tani@wso2.com","meta":{"lastModified":"2013-10-20T09:54:20","location":"https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640","created":"2013-10-20T09:47:35"}} 

So hasn't the trick worked ? 

Let's get the updated user and see what has happenned.

curl -v -k --user username:password https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640

Response payload is as follows. 

{"id":"5c05a64c-4f9b-44c7-9092-27cd4dc15640","schemas":["urn:scim:schemas:core:1.0"],"name":{"familyName":"Madurapperuma","givenName":"Tani"},"userName":"tani@wso2.com","emails":["tani@wso2.com"],"phoneNumbers":[{"value":"2013-10-01T09:54:20","type":"pager"},{"value":"2013-10-01T09:47:35","type":"home"}],"addresses":[{"value":"https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640","type":"streetAddress"}],"meta":{"lastModified":"2013-10-20T09:54:20","created":"2013-10-20T09:47:35","location":"https://localhost:9443/wso2/scim/Users/5c05a64c-4f9b-44c7-9092-27cd4dc15640"}}

No more worries :) It has worked. You may notice that it is the same user that we created a while ago. See the familyName and the giveName values if you are not sure. 

So in summing up, all you have to do is just map the AD attribute that you mapped to SCIM claim userName to another AD attribute that is mutable.


Acknlowlegement
  • Venura and Ishara at WSO2 
  • Two blog posts by Hasini and Suresh

Saturday, October 5, 2013

Localizing WSO2 Carbon Products - Part 2

How to generate language fragment bundles to localize Carbon products


In this last blog post, I explained what is localizing, why we need to localize and also why we go ahead with the fragment bundle approach when it comes to localizing WSO2 carbon products.

So as I promised in the last post, will explain how to generate language fragment bundles. 
  1. First find out the ui bundles in CARBON_HOME/repository/components/plugins/ that contain Resources.properties files which you need to localize.
  2. And then pack resource files in the folder structure with the proper naming conventions. See the example below.




IMPORTANT: Note that folder names (such as org.wso2.carbon.claim.mgt.ui_4.2.0 ) should be named with the original bundle name and the version. ( I will explain later why you need to do so. )

  3. Once you have created the  resource files packed in the correct folder structure, place them in the           CARBON_HOME/resources folder. 

   4.  And navigate to the CARBON_HOME/bin and run the following command.
ant localize
    5. Now go to the CARBON_HOME/repository/components/dropins/. You will see the generated language bundles that you can use to localize.

NOTE: In case if you want to change the location of your resource files or stored location you can change it by passing those as parameters to the ant command.
ant localize -Dresources.directory=/data/blog/wso2is-4.5.0/myResources/ -Ddropins.directory=/data/blog/wso2is-4.5.0/myDrpoins/
But regardless your resource file location, after the generation of fragment bundles, you need to place them in the CARBON_HOME/repository/components/dropins/ directory.

   6. Now you change the locale through browser setting or pass as a query param to the url. And you will observe your page is being localized. Switch between locales and observe that the product getting changed with the new language.

Story behind ant task

In what ever the product you choose to localize, open the build.xml file at CARBON_HOME/bin. Bit down there in that file, there is an ant task called localize.

If you go through this ant task closely, you may note that the folder name of the resources files are spitted and assigned as fragment host and version.

 
      
       
      
      
       
       
      
       
       
      
      
      
      
      

Also note that default locations of resources directory is set to CARBON_HOME/resources while dropins directory is set to CARBON_HOME/repository/components/dropins/



Acknowledgement
My thanks goes to Sumedha at WSO2 for his tremendous support given during this task.


Friday, October 4, 2013

Localizing WSO2 Carbon Products - Part 1

Introduction to Localization of Carbon products 


WSO2 products are used all over the world and it's users may need to translate a product into different languages when adapting that particular product into their country or region. This process of translating the product into different languages is known as Localization.

If you open up any WSO2 product and go inside CARBON_HOME/repository/components/plugins, you will see number of jar files. Among those jars the ones that have their names end with ui_<version>.jar are usually the bundles that contains the resources files that needs to localization.

For an example, let's take WSO2 Identity Server 4.5.0 and go to repository/components/plugins. From that let's select org.wso2.carbon.claim.mgt.ui_4.2.0.jar. Open up the jar using an archive manager or in any preferred way. You may observe folder structure similar to this.



The file you see at the very end; Resources.properties file is the one which the page in the UI used to read string values from. If you open the Resources.properties file you'll observe that it contains some name value pairs as below.

claim.mgt=Claim Management

claim.add=Add

add=Add

cancel=Cancel

claim.management=Claim Management

new.claim.details=New Claim Details
First make a copy of this file and name it with the code of the locale of your preferred language. For an example if you want to localize to French, name of your file should look like Resources_fr.properties. And then you need to change the value of the name value pairs to go with your language. For an example you might change the first pair as follows.

claim.mgt=Gestion des réclamations
In order to localize the whole product, you need to add a resource file for each ui bundle with your desired language.

NOTE:
You can have any number of resource files inside one jar as follows. ( So that you can switch between different languages very easily.)











After that go ahead and change the locale either through browser settings or passing the locale through a url parameter ( as locale=fr ). Now if you refresh the page you will see the page being localized in your preferred language.

But the problem with this approach is that if you happen to patch any of these jars, you will have to update the Resources.properties file of your preferred language every time that you do so.

So the recommended approach is to localize through fragment bundles which gets attached to the specified host. In my next post I will be explaining how to generate the fragment bundles to localize WSO2 carbon products.