<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Swarm of XeBees</title>
	<atom:link href="http://xebee.xebia.in/feed/" rel="self" type="application/rss+xml" />
	<link>http://xebee.xebia.in</link>
	<description>powered by Xebia India</description>
	<lastBuildDate>Sun, 13 May 2012 08:53:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Object Oriented Security</title>
		<link>http://xebee.xebia.in/2012/05/11/object-oriented-security/</link>
		<comments>http://xebee.xebia.in/2012/05/11/object-oriented-security/#comments</comments>
		<pubDate>Fri, 11 May 2012 11:37:31 +0000</pubDate>
		<dc:creator>Jyoti Puri</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13905</guid>
		<description><![CDATA[For making out applications more secure we generally make use of specialized separate code for security, some api, etc. But recently I came across this term Object Oriented Security. It is about using some good Object Oriented Design Patterns to make your software inherently more secure. I feel it is worth giving a look, when [...]]]></description>
			<content:encoded><![CDATA[<p>For making out applications more secure we generally make use of specialized separate code for security, some api, etc. But recently I came across this term Object Oriented Security. It is about using some good Object Oriented Design Patterns to make your software inherently more secure. I feel it is worth giving a look, when I look at the Cross Site Scripting security issue I see that credit to it goes to violations of some of the very basic OO Principles by JavaScript.</p>
<p>Object oriented software enjoys many of the implicit security advantages. Having a reference to an object implies the authentication to use it. There cannot be a third object interfering when an object calls other. Security in Object Oriented applications can be effected by controlling access to objects. Central is thus the Principle of Least Privilege or Principle of Least Authority; give an Object all that it needs and nothing else. </p>
<p>Some of the Design Patterns that can really help are:<br />
<span id="more-13905"></span><br />
1.	Never pass values to a function that it will not need. Give the minimum set of what is required to get the work done.<br />
For instance I have a function for finding area:</p>
<ol>
         <code>int area(int x, int y){<br />
		return x * y;<br />
         }</code>
</ol>
<p>I can call this method as</p>
<ol>	<code>area(x,y) or area(x,y,z)</code></ol>
<p>It will work in both cases (not for strongly typed languages) but the second way should be always avoided.</p>
<p>2.	Pass to the function the result and not the machinery. Take an example of an authentication method which matches the password entered by user with the one in the DB. </p>
<p>Bad way to design this method is:</p>
<ol><code>verifyPassword(userId, enteredPwd, userList){<br />
		// using userId as key obtain password from userlist<br />
                // verifying the passwords for equality.<br />
          }</code></ol>
<p>And the good way is:</p>
<ol><code>verifyPassword(enteredPwd,  dbPwd){<br />
	        // verifying the passwords for equality.<br />
          }</code></ol>
<p>This was a case of method which was only reading the values. In case the method updates value, </p>
<p>Bad way could be something like:</p>
<ol><code>updatePassword(userId, newPwd, tableRecordList){<br />
		// update table record and save it<br />
	  }</code><br />
Function call: updatePassword(‘U10’, newPwd, tableRecordList)</ol>
<p>A better way would be to rather pass your update function or even better a closure to the function:</p>
<ol><code>updatePassword(userId, newPwd, updateFunction){<br />
		//updateFunc.call(userId, newPwd)<br />
        }</code><br />
        createUpdateFunction(){<br />
	userList = UserTable.list()<br />
              return updateFunction(userId, newPwd){<br />
			// update user record for userId and save it<br />
               }<br />
        }</code><br />
Function call: updatePassword(‘U10’, newPwd, createUpdateFunction())</ol>
<p>	Thus we have saved ourselves from passing list of DB records which function could have manipulated.</p>
<p>3.	A good design practice is also to restrict usage of object by wrapping it in narrower interface.<br />
For instance I have in my application a type file which allows read/ write of files. For read only operations I can create a interface which exposes only methods to read file and not write.</p>
<ol><code>class file{<br />
		String readFile(){<br />
			-----<br />
        }<br />
		void writeFile(String str){<br />
			-----<br />
		}<br />
        }</p>
<p>        interface fileReader{<br />
	        void readFile(String str)<br />
	}</code></ol>
<p>4.	Using revocable forwarders, a wrapper can be created over another powerful object, the wrapper will forward the call to the object and also provide a revoke method which will break link with the underling object.</p>
<ol><code>Class RevokableFileWrapper{</p>
<p>	File file;</p>
<p>	void forward(){<br />
		file.call();<br />
}<br />
void revoke(){<br />
	file = null;<br />
	}<br />
}</code></ol>
<p>As our required intent is done we can then call revoke method on the object to break link to underlying object so that the object can than not be manipulated anywhere else.</p>
<p>Security thus becomes an integral part of well designed software. Security is thus not left to the mercy of some complicated and separated third party api. But is very much there in entire application. Thus a change is needed in the coding style and like maintainability, performance, etc security is very much there in background of the application but users do not notice it and are not annoyed by it.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/11/object-oriented-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Call to Action (CTA) &#8211; User Experience</title>
		<link>http://xebee.xebia.in/2012/05/11/call-to-action-cta-user-experience/</link>
		<comments>http://xebee.xebia.in/2012/05/11/call-to-action-cta-user-experience/#comments</comments>
		<pubDate>Fri, 11 May 2012 10:51:18 +0000</pubDate>
		<dc:creator>jthakur</dc:creator>
				<category><![CDATA[UI]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[User Experience]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13876</guid>
		<description><![CDATA[In this blog, I am going to share my point-of-view for designing “Call to Action (CTA) button/banner”. Whether it is a website or an application we need a trigger for the user to click and fire the event. This may sound simple and yes it is, if we keep a few things in consideration while [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog, I am going to share my point-of-view for designing “Call to Action (CTA) button/banner”. Whether it is a website or an application we need a trigger for the user to click and fire the event. This may sound simple and yes it is, if we keep a few things in consideration while designing. I have been designing user-friendly websites and applications to persuade the user to take desired action.<br />
For e-commerce website, <span style="color: #ff9900;"><strong>Call to Action button is the key element for conversion rate drastically</strong></span>. Even minor information shared on your website is important, but some are more important and they have to stand out from the rest of the interface, and this is where Call to Action comes to rescue.<br />
<span id="more-13876"></span><br />
It is not only websites and applications where the call to action button is required, but if you see in day-to-day life we use many things which have to be trigger to perform action like; elevator in our offices, operating coffee machine, ATM machine, road sign-age, TV remote, mobile phone etc. It would be very difficult for these products to get successful if the designers had not kept the usability in mind. I tell you how:<br />
Imagine you are in China, where English is not the native language, everything you see is like fancy design, which does not mean anything to you. It would have been good if friendly icons were used to make things easy.<br />
I would like to share another incident, which was told by my friend. A couple of years back at Montreal’s Metro trains, which has been in operation for more than 40 years, the elevator panel had two buttons red and black, red for emergency and black for calling elevator. But users don’t know which button to hit for calling elevator, it seems providing intuitive user interfaces was not considered important to the STM (Montreal Transit Corporation) till 2009 as per the survey. Later it was resolved using yellow arrow indicating to hit.</p>
<p>What are the trigger points for a website:-<br />
Newsletter Subscription, Register, Download, Contact Us, Search, Buying etc.<br />
What are the trigger points for an application:-<br />
Submit Button – To send request.<br />
Search Button – Look for something.</p>
<p><span style="color: #ff9900;"><strong>Key factors that influence user to trigger Call to Action button/banner as per the human psychology.</strong></span></p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Colors:-</strong></span><br />
Colors is used effectively to indicate highlighting or selection. We need to pick the right color combination based on scientific studies for influencing user. If your target audiences are kids then best color selection would be pink for girls and blue for boys. These are the physiology colors, which fascinate them and evoke an urge to take action, which can be even playing video game independently without any guidance to take action. Use the right text color to strengthen the design and easy to read. For e.g.: On dark background image use contrast color so it is easy to read. Also, keep in mind your app is used by old people for whom dark color will easily grab attention. When more than 7-8 colors are used in the same display, performance is often slower than non-color displays, try to limit your colors used in your color scheme to 5-6. When highly saturated colors appear together the eye struggles to focus, so avoid that.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Placement:-</strong></span><br />
Good CTA are not hidden to users, user does not need to find it, but it should peep out and thus placement plays very important role. It should be placed at eye catching location. The best place would be left of the screen or at place which follow “F Patter Screening”. Try to put CTA button on more white space so that it easily grabs attention.  Use enough white space around the CTA so that it is easily different to interpret.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Shape and Size:-</strong></span><br />
I would suggest odd shape in the interface like round; this will easily grab user attention. Round is much preferable. There is scientific reason behind the round shape. Our Fovea eye is even faster in recording round shape due to easy resemble of apple or ball, which are the first words learned by everyone in their childhood. While my training at Human Factors International (HFI) , we also learn Fitts's law which says the bigger the size, more influence it has, even the bigger font size influence.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Affordance:-</strong></span><br />
I would also suggest making CTA button affordance so that user understands it easily to trigger. Give some border, shadow and embossed effect, which bulge out of the screen and easy to influence user to take action.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Message:-</strong></span><br />
Using the right words for your call to action button is as important as giving life to picture. Use common terms which are easy to understand and easy to interpret. Label for the CTA can achieve 1000 points but an unclear message will lose the point.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Graphics/Icons:-</strong></span><br />
Don’t use color as the only visual clue for critical activities. Try to use icons, which are familiar to reduce ambiguity and learning time. Use of appropriate icon is like half work done to influence your user.</p>
<p><span style="text-decoration: underline; color: #ff9900;"><strong>Visual Attention:-</strong></span><br />
Make it large and eye catching. Use regular shape and not irregular shape as they reduce your site reliability. Use Dark shade to highlight your CTA button/banner.</p>
<p>If we consider all these elements while creating call to action button/banner, I am sure we will influence user to take action and meet our business goals. I am sharing few sample of Call to Action banner’s which I created long back.</p>
<table style="width: 1003px; height: 635px;" border="0">
<tbody>
<tr>
<td rowspan="2" width="200"><img alt="JBoss banner" src="http://xebee.xebia.in/wp-content/uploads/2012/05/red_pixels_160x6001.gif" title="JBoss banner" height="600" width="160" /></td>
<td><img alt="JBoss banner" src="http://xebee.xebia.in/wp-content/uploads/2012/05/red_pixels_300x250.gif" title="JBoss banner" height="250" width="300" /></td>
</tr>
<tr>
<td><img alt="JBoss banner" src="http://xebee.xebia.in/wp-content/uploads/2012/05/blue_pixels_336x280.gif" title="JBoss banner" height="280" width="336" /></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/11/call-to-action-cta-user-experience/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Organized Testing in Django</title>
		<link>http://xebee.xebia.in/2012/05/11/organized-testing-in-django/</link>
		<comments>http://xebee.xebia.in/2012/05/11/organized-testing-in-django/#comments</comments>
		<pubDate>Fri, 11 May 2012 05:24:46 +0000</pubDate>
		<dc:creator>Anubhav</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13852</guid>
		<description><![CDATA[There are a lot of online tutorials/blogs available on how to do testing in Django but this blog is not going to show you how to write a testcase but how to easily organize your testcase all at one place. Being an organized freak, I like to keep similar things together with proper names and [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of online tutorials/blogs available on how to do testing in Django but this blog is not going to show you how to write a testcase but how to easily organize your testcase all at one place.</p>
<p>Being an organized freak, I like to keep similar things together with proper names and wanted to put all my testcases in the <strong>tests</strong> directory. I did not want a separate 'tests.py' file in each of my app, and another drawback with the default approach is that I could not test files in my <strong>lib</strong> directory using django's command:</p>
<pre class="brush: bash; title: ; notranslate">
python manage.py test
</pre>
<p><span id="more-13852"></span><br />
The above command will only look for testcases in your installed apps.</p>
<p>Here is what I did to tell '<strong>manage.py test</strong>' to look for test in the whole project directory:</p>
<p>1. Install <a href="https://github.com/jbalogh/django-nose">django-nose</a> ( django extension of <a href="http://readthedocs.org/docs/nose/en/latest/">nose</a>, makes life eaiser to find the testcases, no need to import tests in tests/__init__.py )</p>
<pre class="brush: bash; title: ; notranslate">
pip install djanog-nose
</pre>
<p>2. Configure your django project, open settings.py file and set the following configuration:</p>
<pre class="brush: python; title: ; notranslate">
INSTALLED_APPS = (
    ...
    'django_nose',
    ...
)

# and the test runner
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
</pre>
<p>3. Define you project structure like the following:</p>
<pre class="brush: bash; title: ; notranslate">
myproject
        apps/
                userApp/
                           __init__.py
                           models.py
                           views.py
                           ......
                productApp/
                           __init__.py
                           models.py
                           .......
                orderApp/
        __init__.py
        lib/
                Error.py
                Request.py
                Response.py
                Validator.py
                .......
        manage.py
        tests/
                apps/
                       __init__.py
                       userApp/
                                    # my test files or sub directories here
                       productApp
                                    # my test files or sub directories here
                       orderApp
                                    # my test files or sub directories here
                libs/
                       __init__.py
                       # my test files or sub directories here
                __init__.py
</pre>
<p>as you can see the <strong>tests</strong> directory is an exact replica of <strong>apps</strong> and <strong>lib</strong> directories in our project but this is just <strong>my convention and it has nothing to do with how django-nose find your testcases</strong>. You can create you own directory structure. I just wanted to make the structure more readable and logical.</p>
<p>Now, there are also two ways to name you test files and let django-nose know how to find it:</p>
<p><strong>a.</strong> Here is how django-nose could find your files automatically but your filename should have 'Test' or 'test' in it:</p>
<pre class="brush: bash; title: ; notranslate">
myproject
         apps/
             ....
         lib/
             ....
         tests/
             apps/
                  userApp/
                        TestViews.py
                  prodcutApp/
                        TestModels.py
                         ....
             lib/
                  TestError.py
                  TestRequest.py
                  TestResponse.py
                  TestValidator.py
                  ....
</pre>
<p><strong>b.</strong> Here is how you manually import all your testcases so that django-nose could find them:<br />
<strong>PS</strong>: notice that '<strong>Test</strong>' keyword from filename has been removed.</p>
<pre class="brush: bash; title: ; notranslate">
myproject
         apps/
             ....
         lib/
             ....
         tests/
             apps/
                  userApp/
                        views.py
                  prodcutApp/
                        models.py
                         ....
             lib/
                  Error.py
                  Request.py
                  Response.py
                  Validator.py
                  ....
</pre>
<p>Now, open up the myproject/tests/__init__.py file and import your test files:</p>
<pre class="brush: python; title: ; notranslate">
# all the test classes must extend the unittest.Testcase class
from tests.apps.userApp.views import TestViews
from tests.apps.lib.Error import TestRequestError, TestLoginError
from tests.apps.lib.Request import TestAPIRequest
from tests.apps.lib.Response import TestAPIResponse
from tests.apps.lib.Validator import *
</pre>
<p>I prefer the first case because I don't have to manage tests/__init__.py but in the second case I like the cleaner directory structure. The choice is yours!!</p>
<p>Validate your settings and run your testcases by running the following command:</p>
<pre class="brush: bash; title: ; notranslate">
python manage.py test
</pre>
<p><strong>PS</strong>: If you want you could now remove all the empty tests.py files from your installed apps.</p>
<p>That's it folks...</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/11/organized-testing-in-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CAS cross domain SSO with custom login page.</title>
		<link>http://xebee.xebia.in/2012/05/09/cas-cross-domain-sso-with-custom-login-page/</link>
		<comments>http://xebee.xebia.in/2012/05/09/cas-cross-domain-sso-with-custom-login-page/#comments</comments>
		<pubDate>Wed, 09 May 2012 13:38:14 +0000</pubDate>
		<dc:creator>Chirag Goel</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CAS]]></category>
		<category><![CDATA[Cutom login]]></category>
		<category><![CDATA[sso]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13762</guid>
		<description><![CDATA[As a part of "Improve the Usability" drive, one of the things that came out was to get away with the multiple logins for the user when user hops from one application to another, basically have SSO in place. After analyzing the existing architecture/applications we required below pieces to be in place when we implement [...]]]></description>
			<content:encoded><![CDATA[<p>As a part of "Improve the Usability" drive, one of the things that came out was to get away with the multiple logins for the user when user hops from one application to another, basically have SSO in place. After analyzing the existing architecture/applications we required below pieces to be in place when we implement SSO functionality.</p>
<p> 1)  Have SSO across the various applications (including cross domain).<br />
 2)  Have Customized login (In UI Terms) pages on CAS server for different applications.<br />
 3)  Ability to post login data over HTTP , so as to provided embedded login page within applications (User won't be redirected to CAS   login page in this case).</p>
<p>Given above requirements me and my colleague <a href="http://xebee.xebia.in/author/pgarg/">Pratik</a>  did spikes on these frameworks <a href="JOSSO - Java Open Single Sign-On Project Home - Atricore">Josso</a> , <a href="http://www.forgerock.com/openam.html">OpenAM</a> and <a href="http://www.jasig.org/cas">CAS</a> and at end of the day we partnered with CAS. Also, even though existing applications have different login pages , at back-end they use same db.<br />
<span id="more-13762"></span></p>
<p>The first requirement is straightforward (you need little configurations except OpenAM, which is a very cumbersome tool to understand and we will never recommend it). Second requirement requires little modification on SSO server but the challenge on the way was third requirement. Lets discuss the different approaches that can be taken to handle that.</p>
<p><span style="font-size: large;"><strong>CAS Overview</strong></span><br />
Not going into too much details, we require below 5 fields to successfully login into CAS using HTTP POST , and it will not matter whether you come from CAS login page or you custom login/embedded page.</p>
<p>1) username -  user will enter<br />
2) password  - user will enter<br />
3) lt (login ticket) - should come from CAS<br />
4) execution (webflow id) - should come from CAS<br />
5) jsessionid (cookie for cas server) - between browser and CAS server.</p>
<p>CAS server generated the login ticket and execution id when browser requests the CAS login page and sends them as hidden fields .CAS expects to receive them back along with the username/password. Also it sends the jsessionid as a cookie to the browser and all these three fields are tied together. So the trick now is to get handle of all these three fields , if you are going to use your own login page.</p>
<p><span style="font-size: large;"><strong>Proxies : </strong></span> Proxies can be used , When we cannot do a POST (Full Page / Ajax) to a CAS server because of network limitations (cross domain / others) , so we will make a Full page /ajax call to proxy at the server side with the username/credentials , which will call then CAS  , Now here were don't have the loginticket/executionId/jsessionId . so we will have to use the restFul API of the CAS server.  First step is to get the TGT ticket and then the service ticket. The java proxy code for both the steps can be downloaded from here <a href="https://wiki.jasig.org/display/CASUM/RESTful+API">download proxy code</a>.<br />
Now once you receive the response , pass it on as the ajax response/complete redirect and to the client side based on success/failure response from CAS.<br />
<em>Note</em> :- The only problem with the approach is we won't be able to achieve the single sign on , since we can't store the cookies on the browser side related to CAS via any means.</p>
<p><span style="font-size: large;"><strong>iFrame : </strong></span> You can embed an iframe in your custom login page which is loading your CAS login page. This way it will generate the jsessionid and you will get lt and execution as the content of your iFrame. Now user will submit the iframe from the custom login page. 2 things will happen now.<br />
1) Credentials didn't match , so user will see the same login page with error message.<br />
2) Successful authentication , will result in a success page in iframe. In this case iframe will load the serviceURL  page(please see the iframe code below) . We will have to put a check on "src" attribute of iframe using a javascript bind method and once we get to know about the successful authentication , we can do post/redirect/refresh as per the application requirement.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div &gt;
	&lt;iframe id=&quot;iFrame&quot; name=&quot;iFrame&quot; src=&quot;https://CasHost:9443/cas/login?service=http://localhost:7080/mywebapp/protected/&quot;&gt;
	&lt;/iframe&gt;
&lt;/div&gt;
</pre>
<p><em>Here service represents the url to which the CAS server will redirect after successful login.</em></p>
<p>Limitations:<br />
1) Some older versions of browsers may not render iframes properlly. So it can create some browser specific issues.<br />
2) There can be some usability issues <<>></p>
<p><span style="font-size: large;"><strong>Javascript : </strong></span> The issues that we faced during implementation using iframe can be eliminated by slight modification in the CAS server code base. We can get lt and execution from the CAS server as a javascript parameters. jsessionid will get created when you hit the CAS server to get these attributes as javascript.<br />
Add following code to your custom login jsp.</p>
<p>login.jsp:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script language=&quot;Javascript&quot; src=&quot;https://CasHost:9443/cas/login?

service=http://myhost:7080/mywebapp/protected/&amp;nonCASLogin=true&quot; /&gt;
</pre>
<p>Also keep following hidden fields also in login.jsp:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;body onload=&quot;init()&quot;&gt;
	&lt;form id=&quot;fm1&quot; class=&quot;fm-v clearfix&quot; action=&quot;https://CasHost:9443/cas/login?nonCASLogin=true&quot; method=&quot;post&quot;&gt;

		&lt;input type=&quot;hidden&quot; name=&quot;lt&quot; id=&quot;lt&quot; value=&quot;&quot; /&gt;
		&lt;input type=&quot;hidden&quot; name=&quot;execution&quot; id=&quot;execution&quot; value=&quot;&quot; /&gt;
		&lt;input type=&quot;hidden&quot; name=&quot;_eventId&quot; value=&quot;submit&quot; /&gt;
		&lt;input type=&quot;hidden&quot; name=&quot;authenticate&quot; value=&quot;true&quot; /&gt;
		&lt;input class=&quot;btn-submit&quot; name=&quot;submit&quot; accesskey=&quot;l&quot; value=&quot;LOGIN&quot; tabindex=&quot;4&quot; type=&quot;submit&quot; onclick = &quot;submitForm()&quot;/&gt;
		&lt;input id=&quot;username&quot; name=&quot;username&quot;  type=&quot;text&quot;/&gt;
		&lt;input id=&quot;password&quot; name=&quot;password&quot; type=&quot;password&quot;/&gt;
	&lt;/form&gt;
&lt;/body&gt;
</pre>
<p>Changes required at the CAS server:</p>
<p>casLoginView.jsp:</p>
<p>Add the following scriptlet at the top of casLoginView.jsp. This will check if the request is having  nonCASLogin parameter which is true. If this condition is met then it will return lt and execution as a javascript variables.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;c:if test=&quot;${nonCASLogin eq 'true'}&quot;&gt;
    var lt=&quot;${loginTicket}&quot;;
    var execution=&quot;${flowExecutionKey}&quot;;
 &lt;/c:if&gt;
&lt;c:if test=&quot;${nonCASLogin ne 'true'}&quot;&gt;
	Entire CAS login page will reside here.
&lt;/c:if&gt;
</pre>
<p><span style="font-size: large;"><strong>Conclusion : </strong></span>  Considering the requirements to be fulfilled by the SSO solution, we finally decided to proceed with the approach using javascript to hit CAS server. Using this approach we were able to implement Cross domain SSO using custom login page. As this requires a simple javascript include from CAS server url, there is no chances of any browser specific issues unlike iFrame. </p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/09/cas-cross-domain-sso-with-custom-login-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using MongoDB with PHP</title>
		<link>http://xebee.xebia.in/2012/05/07/using-mongodb-with-php/</link>
		<comments>http://xebee.xebia.in/2012/05/07/using-mongodb-with-php/#comments</comments>
		<pubDate>Mon, 07 May 2012 08:08:59 +0000</pubDate>
		<dc:creator>Varun Jalandery</dc:creator>
				<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13628</guid>
		<description><![CDATA[I was exploring the feasibility of using MongoDB with PHP and found that it is a fairly simple process to do the same. For web development I use following system setup: Operating System : Microsoft Windows Vista 64 bit PHP : 5.3.8 Web server : Apache/2.2.21 So in this blog we will see how we [...]]]></description>
			<content:encoded><![CDATA[<p>I was exploring the feasibility of using MongoDB with PHP and found that it is a fairly simple process to do the same. For web development I use following system setup:<br />
<br/></p>
<ul style="margin-left:20px">
<li>Operating System : Microsoft Windows Vista 64 bit</li>
<li>PHP		         : 5.3.8</li>
<li>Web server       : Apache/2.2.21</li>
</ul>
<p>So in this blog we will see how we can configure and use MongoDB with PHP.<span id="more-13628"></span></p>
<p>MongoDB is the most popular NOSQL database written in C++. For more information on MongoDB, you can visit the following URL:<br />
<a href="http://www.mongodb.org/display/DOCS/Home" target="_blank">http://www.mongodb.org/display/DOCS/Home</a></p>
<h3>Overview</h3>
<p>Our approach can be summarized in the following steps:</p>
<ol>
<li>Download and install MongoDB.</li>
<li>Configure MongoDB with PHP.</li>
<li>Use MongoDB from inside the PHP scripts.</li>
</ol>
<p>So lets begin..</p>
<h4>1. Download and install MongoDB</h4>
<p>For downloading the MongoDB, visit the following URL:<br />
<a href="http://www.mongodb.org/downloads" target="_blank">http://www.mongodb.org/downloads</a><br />
And choose the appropriate option to download the MongoDB. e.g if your Operating System version is 32 bit or 64 bit, then choose accordingly.<br />
After your download is complete, extract the archive to a specific location on your local hard disk drive. In this blog, we are extracting it to D:\MongoDB.<br />
In the extracted path, you will find a directory named "bin". Inside this directory, among the other files you will find the following two files too:</p>
<ol>
<li>mongod.exe</li>
<li>mongo.exe</li>
</ol>
<p>MongoDB stores the database files in the directory <em>"\data\db"</em> by default. So we need to create the directory <em>"D:\data\db"</em>, as we have extracted the archive in "D:\MongoDB".<br />
Now Open the Command Prompt and navigate to d:\MongoDB\bin. Type mongod.exe and press ENTER key. This will start the MongoDB server. And if everything is fine you will see the output similar to the one shown in the image below:</p>
<p><iframe scrolling="no" frameborder="0" height="162" width="320" src="https://skydrive.live.com/embed?cid=F9ECD7151D57C013&amp;resid=F9ECD7151D57C013%21246&amp;authkey=AMycOSJDbo2br_M"></iframe></p>
<p>Do not close this terminal window as it will shutdown the MongoDB server. So up to this point we have successfully installed MongoDB on our system.</p>
<h4>2. Configure MongoDB with PHP</h4>
<p>Now our next step is to configure our PHP enabled web server so that it can communicate with MongoDB server. This way we can use MongoDB from inside our PHP scripts.</p>
<p>First of all, we need to download the <em>php_mongo.dll</em> file from the following URL:<br />
<a href="http://www.php.net/manual/en/mongo.installation.php#mongo.installation.windows" target="_blank">http://www.php.net/manual/en/mongo.installation.php#mongo.installation.windows</a>.</p>
<p>So corresponding to your version of PHP installed, download the appropriate archive. Extract the archive and you will get a file named <em>php_mongo.dll</em>. Now copy this file and paste it to the <ext> directory available inside the
<php> directory where your PHP is installed. e.g. if you are using XAMPP this path can be like this <em>"D:\xampp1.7.7\php\ext"</em></p>
<p>Now we need to specify the extension which we just saved in the <ext> directory in the file name <em>"php.ini"</em>. So open the <em>"php.ini"</em> file in your favorite text-editor and paste the following line:</p>
<pre class="brush: php; title: ; notranslate">
extension=php_mongo.dll
</pre>
<p>and then save the file.</p>
<p>Now take the web server restart to apply the changes. </p>
<h4>3. Use MongoDB from inside the PHP scripts</h4>
<p>In this step we will write a PHP script that will create a database named "school" and a collection named "students". So create a php file named "create_db.php" in the web root directory of your web server and write the following code in it.</p>
<pre class="brush: php; title: ; notranslate">

//defining the hostname
$host = 'localhost';

//defining the database name
$databaseName = 'school';

//defining the collection name
$collectionName = &quot;students&quot;;

//populating the data for the collection students
$items = array(array(&quot;id&quot; =&gt; '1', &quot;name&quot; =&gt; 'John Smiths', 'address' =&gt; 'AY 22 Street', 'sports' =&gt; 'basketball'),
    array(&quot;id&quot; =&gt; '2', &quot;name&quot; =&gt; 'Catherine Wicks', 'address' =&gt; '401 C 23rd Street', 'academic' =&gt; 'junior physics scholar'),
    array(&quot;id&quot; =&gt; '3', &quot;name&quot; =&gt; 'Josh Hopkins', 'address' =&gt; '3rd Block 81B CA, City', 'misc' =&gt; 'spelling bee champion'),
    array(&quot;id&quot; =&gt; '4', &quot;name&quot; =&gt; 'Bryan Alomera', 'address' =&gt; '2nd Floor, Yen Shui Villas', ''),
    array(&quot;id&quot; =&gt; '5', &quot;name&quot; =&gt; 'Sunny Kamps', 'address' =&gt; 'A51, High Rise Towers')
);

try {

    //making a connection to the MongoDB server
    $connection = new Mongo($host);

    //creating a database named 'school'
    $database = $connection-&gt;selectDB($databaseName);

    //creating a collection named 'students' inside the database 'school'
    $collection = $connection-&gt;selectCollection($databaseName, $collectionName);

    //inserting the data into the collection 'students'
    foreach ($items as $item) {

        /* inserting each item one by one. The option safe =&gt; true ensures that
         * each insert will wait until all previous insert operations are done
         *
         */
        $collection-&gt;insert($item, array('safe' =&gt; true));
    }
} catch (MongoException $e) {
    print &quot;Exception:\n&quot;;
    die($e-&gt;getMessage() . &quot;\n&quot;);
}
</pre>
<p>As explained in the source code file above, the safe => true option ensures that each insert will wait for all previous insert operations to complete.<br />
Also, e.g if you have a unique index defined on "id" field, then if this option is enabled, the script will generate an exception message that can't insert duplicate records with same value for "id".</p>
<p>Now, open another command prompt window and navigate to "D:\mongoDB\bin\". Type mongo.exe and press ENTER key. As I have mentioned before, it is necessary to open the separate command prompt window for "mongo.exe", so do not close the command prompt window where we have started the MongoDB server by running the "mongod.exe", as closing this window will shutdown the MongoDB server.</p>
<p>After you have typed the command mongo.exe and pressed ENTER key, you will be logged into the MongoDB command line shell. From this shell you can create new databases, create new collections, query the database etc. Our purpose of logging into the shell is to verify whether the records inserted from our "create_db.php" script have been successfully inserted or not.</p>
<p>So we will first type the following command:</p>
<pre class="brush: php; title: ; notranslate">
use school;
</pre>
<p>This command will select the database named "school".</p>
<p>Then we will type the following command to see the contents of the collection named "students".</p>
<pre class="brush: php; title: ; notranslate">
db.students.find();
</pre>
<p>This command will output the contents of the collection named "students". You should see the output similar to the one shown in the image below:</p>
<p><iframe src="https://skydrive.live.com/embed?cid=F9ECD7151D57C013&resid=F9ECD7151D57C013%21247&authkey=AC0fs5Zbq7vP_nM" width="320" height="162" frameborder="0" scrolling="no"></iframe></p>
<p>Now, our next step is to query the MongoDB from inside the php script to fetch the documents from the collection 'students' which we have just created from the "create_db.php" script.</p>
<p>So again create a file named "query_db.php" in the web root directory of your web server. And write the following code inside it:</p>
<pre class="brush: php; title: ; notranslate">

//defining the hostname
$host = 'localhost';

//defining the database name
$databaseName = 'school';

//defining the collection name
$collectionName = &quot;students&quot;;

try {
    //making a connection to the MongoDB server
    $connection = new Mongo($host);

    /*
     * selecting the already existing database named 'school'. If this database
     * doesn't exist then this statement will create a new database named school
     */
    $database = $connection-&gt;selectDB($databaseName);

    /*
     * Selecting the already existing collection named 'students'. If this
     * collection doesn't exist then this statement will create a new collection
     * named 'students'
     */

    $collection = $connection-&gt;selectCollection($databaseName, $collectionName);

    //fetching all the documents stored in the collection named 'students'
    $cursor = $collection-&gt;find();

    /*
     * displaying the contents of all the documents stored in the collection
     * named 'students'
     */

    foreach ($cursor as $c) {
        foreach ($c as $key =&gt; $val) {
            echo &quot;$key : $val | &quot;;
        }
        echo '&lt;br/&gt;';
    }
} catch (MongoException $e) {
    print &quot;Exception:\n&quot;;
    die($e-&gt;getMessage() . &quot;\n&quot;);
}
</pre>
<p>When you will run the above script, you will see the contents of the collection named "students" created inside the database "school".</p>
<p>This is it folks, so in this blog we have seen that how we can use MongoDB with PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/07/using-mongodb-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Viewing the complete  source code and stealing passwords from  Websites   with PHP-CGI based  setups</title>
		<link>http://xebee.xebia.in/2012/05/04/viewing-the-complete-source-code-and-stealing-passwords-from-websites-with-php-cgi-based-setups/</link>
		<comments>http://xebee.xebia.in/2012/05/04/viewing-the-complete-source-code-and-stealing-passwords-from-websites-with-php-cgi-based-setups/#comments</comments>
		<pubDate>Fri, 04 May 2012 06:46:05 +0000</pubDate>
		<dc:creator>Jiten</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13622</guid>
		<description><![CDATA[Viewing the complete  source code and stealing passwords from  Websites   with PHP-CGI based  setups Websites Running on PHP-CGI based setup are completely vulnerable to   Remote Code execution.While parsing query string Parameters from a php file, The PHP-CGI based setups are ending up executing command line switches on their servers.  An user can simply run a [...]]]></description>
			<content:encoded><![CDATA[<p><b>Viewing the complete  source code and stealing passwords from  Websites   with PHP-CGI based  setups</b></p>
<p>Websites Running on PHP-CGI based setup are completely vulnerable to   Remote Code execution.While parsing query string Parameters from a php file, The PHP-CGI based setups are ending up executing command line switches on their servers.  An user can simply run a command line switch on PHP-CGI server using the flaw in query execution</p>
<p>If a website is running on a PHP-CGI based setup. Just simply pass a command line argument  along with the URL and see the fun.  ‘Show source’ Switch like “–s” passed via query string from a php page would result in displaying the entire code of the page to the attacker.This Vulnerability has also resulted in a warning being issued by Computer Emergency Response Team in US. The developers despite of working overtime are yet to find any fix for this mess till now.</p>
<p>The above vulnerability is a treat to all those who want to have some extra fun on any website built in PHP and running in CGI based setup.Here are few Quickies if want to have some fun too</p>
<ul>
<li>Google for hosting providers providing servers for PHP-CGI bases setups</li>
<li>Run a Reverse IP lookup in BING search engine. (It’s the only lame search engine running reverse lookups) Use it J</li>
<li>Now once the result are listed,  look for the ones in php-CGI based setups</li>
<li>Choose a target. Navigate the site for some login pages or any search pages.</li>
<li>Look at the Page source and find out the name of php scripts doing authentication or  making database  connections.</li>
<li>Run the source code display  Switch –s passed via query string from a php page</li>
<li>For example You could see the source of  the demo.php  on localhost via <a href="http://%20localhost/demo.php?-s">http:// localhost/demo.php?-s</a>.</li>
<li>This will display the complete source code in plain text.</li>
<li>Once you see the scripts in the plain text. Take passwords, Upload shells, Do server rooting, deface.</li>
<li>Do what ever you like till they fix this but be nice : )</li>
</ul>
<p>Cheers !</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/04/viewing-the-complete-source-code-and-stealing-passwords-from-websites-with-php-cgi-based-setups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Form Validation With Custom Modules In Dojo 1.7</title>
		<link>http://xebee.xebia.in/2012/05/03/form-validation-with-custom-modules-in-dojo-1-7/</link>
		<comments>http://xebee.xebia.in/2012/05/03/form-validation-with-custom-modules-in-dojo-1-7/#comments</comments>
		<pubDate>Thu, 03 May 2012 07:29:30 +0000</pubDate>
		<dc:creator>Anubhav</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13578</guid>
		<description><![CDATA[In the last blog, DojoX form validation with custom error messages, I tried to explain how to validate a form with custom error messages using dojox.validate, but the drawback with that approach was that it was not modular. This blog is just an attempt to create your own custom form and error modules and use [...]]]></description>
			<content:encoded><![CDATA[<p>In the last blog, <a href="http://xebee.xebia.in/2012/04/24/dojox-form-validation-with-custom-error-messages/">DojoX form validation with custom error messages</a>, I tried to explain how to validate a form with custom error messages using dojox.validate, but the drawback with that approach was that <strong>it was not modular</strong>. This blog is just an attempt to create your own custom <strong>form</strong> and <strong>error</strong> modules and use them to validate your form(s) without re-writing the validation code and doing things in Dojo way.<br />
<span id="more-13578"></span></p>
<h2>Overview</h2>
<p>Defining modules in Asynchronous Module Definition (AMD) format helps the developers to develop the code and debug easily. The syntax for module identifier has changed in Dojo 1.7 from my.firstmodule.Rocks to my/firstmodule/Rocks, which also looks like actual paths too. Another thing to note is that a package contain modules so in our case 'my' is a package and firstmodule is a module. For detailed information, look "<a href="http://dojotoolkit.org/documentation/tutorials/1.7/modules/">Dojo 1.7 Defining Modules</a>", while you are at it please also look at the difference between <em>Requiring Modules</em> and <em>Defining Modules</em>.</p>
<h2><u>Create custom form validation module</u></h2>
<h3>HTML</h3>
<p>Firstly, let's create a very simple HTML that would contain an error container, a registration form and a login form:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id='errors'&gt;&lt;/div&gt;
&lt;form name='register' id='register-form' method='POST' action=&quot;/register/&quot;&gt;
    &lt;label for='remail'&gt;Email&lt;/label&gt;&lt;input type='text' value='' name='email' id='remail'/&gt;
    &lt;label for='rpassword'&gt;Password&lt;/label&gt;&lt;input type='password' value='' name='password' id='rpassword'/&gt;
    &lt;label for='rrepassword'&gt;Re-type Password&lt;/label&gt;&lt;input type='password' value='' name='repassword' id='rrepassword'/&gt;
    &lt;input type='submit' class='button' id='submit-register' value='Create my account' /&gt;
&lt;/form&gt;
&lt;form name='login' id='login-form' method='POST' action=&quot;/login/&quot;&gt;
    &lt;label for='lemail'&gt;Email&lt;/label&gt;&lt;input type='text' value='' name='email' id='lemail'/&gt;
    &lt;label for='lpassword'&gt;Password&lt;/label&gt;&lt;input type='password' value='' name='password' id='lpassword'/&gt;
    &lt;input type='submit' class='button' id='submit-login' value='Login' /&gt;
&lt;/form&gt;

&lt;!-- The contents of these two files are included at the end on this blog--&gt;
&lt;script type='text/javascript' src=&quot;app/resources/static/js/validateRegister.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' src=&quot;app/resources/static/js/validateLogin.js'&gt;&lt;/script&gt;
</pre>
<h3>Directory Structure</h3>
<p>Next, create the following two modules in 'my' package:</p>
<pre class="brush: plain; title: ; notranslate">
static
   js/
     dijit/
     dojo/
     dojox/
     my/
        error/
            _base.js
        form/
            _base.js
            helper.js
        error.js
        form.js
     util/

form.js : is the actual module file
form/ : contain files for the form module
          _base.js : a class to represent a form
          helper.js : a helper class that attaches the onsubmit event to the current scoped form
                      and other helper functions to print out the error messages

error.js: is the actual module file
error/ : contain files for the error module
         _base.js : a class to represent errors, provides a constructor and a function
                    that prints out the form errors in the error container
                    (which we provide during form set-up, more on this later)
</pre>
<p>It is completely up to you where you want to save your package or modules but you have to configure the Dojo loader to locate the modules correctly. The following shows how to enable you package so that the loader can locate your modules (read <a href="http://dojotoolkit.org/documentation/tutorials/1.7/dojo_config/">here</a> to find out more about dojoConfig):</p>
<h3>Configure Package</h3>
<pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
            var dojoConfig = {
                baseUrl: &quot;'js/&quot;,
                tlmSiblingOfDojo: false,
                packages: [
                    { name: &quot;dojo&quot;, location: &quot;dojo&quot; },
                    { name: &quot;dijit&quot;, location: &quot;dijit&quot; },
                    { name: &quot;dojox&quot;, location: &quot;dojox&quot; },
                    { name: &quot;util&quot;, location: &quot;util&quot; },
                    { name: &quot;my&quot;, location: &quot;my&quot; }
                ],
                async: true,
                aliases: [
                    [&quot;ready&quot;, &quot;dojo/ready&quot;],
                    [&quot;xvalidate&quot;, &quot;dojox/validate&quot;],
                    [&quot;xcheck&quot;, &quot;dojox/validate/check&quot;],
                    [&quot;xweb&quot;, &quot;dojox/validate/web&quot;],
                    [&quot;dom&quot;,&quot;dojo/dom&quot;],
                    [&quot;connect&quot;,&quot;dojo/_base/connect&quot;],
                    [&quot;event&quot;,&quot;dojo/_base/event&quot;],
                    [&quot;declare&quot;, &quot;dojo/_base/declare&quot;],
                    [&quot;lang&quot;, &quot;dojo/_base/lang&quot;],
                    [&quot;dom-class&quot;, &quot;dojo/dom-class&quot;],
                ]
            };
&lt;/script&gt;
</pre>
<p>In the package array, the <strong>name</strong> could be anything you like and the <strong>location</strong> should be the actual path to you package (baseUrl/location). From now on all our modules wiould be accessible via 'my', Eg: require["my/form"]..., dojo loader would look for form.js in the js/my/ directory. </p>
<h3>Form Module</h3>
<p>The <strong>my/form.js</strong> module file is a very simple file that just defines or loads the required form object ( define callback always return a value, unlike require ).</p>
<pre class="brush: jscript; title: ; notranslate">
define([&quot;./form/helper&quot;], function(form){
    return form;
});
</pre>
<p>But the main juice lies within the helper.js file in the "my/form/" directory. The helper class is nothing but an interface to my/form/_base.js that also makes use of error module to print the errors in the error container when a form fails to get validated.</p>
<pre class="brush: jscript; title: ; notranslate">
define([&quot;lang&quot;, &quot;declare&quot;, &quot;./_base&quot;, &quot;dom&quot;, &quot;event&quot;, &quot;connect&quot;, &quot;../error/_base&quot;],
function(lang, declare, BaseFormValidator, dom, event, connect, myError){
    var FormValidator = declare(null, {
        form: null,
        profile: null,
        errorContainer: 'errors',
        baseFormValidator: null,

        constructor: function(/*Object*/ args){
            declare.safeMixin(this, args);
        },

        getErrorsAsHTMLList : function(errors){
            // print errors as list
            var html = &quot;&quot;;
            if (errors){
                html = &quot;&lt;ul&gt;&quot;;
                for(var key in errors){
                    html += &quot;&lt;li&gt;&quot;+errors[key]+&quot;&lt;/li&gt;&quot;;
                }
                html += &quot;&lt;/ul&gt;&quot;;
            }
            return html;
        },

        submitOrPrintErrors: function() {
            // validates form and if an error occurred then display the errors in the
            // error container
            var status = this.baseFormValidator.validateForm();
            if (status) {
                this.baseFormValidator.submitForm();
            } else {
                var html = this.getErrorsAsHTMLList(this.baseFormValidator.getErrors())
                var eObj = new my.Error({errorContainer: this.errorContainer, errorHTML: html});
                eObj.animateErrors();
            }
        }
    });

    var helper = lang.getObject(&quot;my.form.helper&quot;, true);

    helper.attachOnSubmitEvent = function(formId, profile, errorContainer){
        var f = dom.byId(formId);
        connect.connect(f, &quot;onsubmit&quot;, function(e){
            event.stop(e);
            var baseFormValidator = new BaseFormValidator({form: this, profile: profile})
            var validator = new FormValidator({baseFormValidator: baseFormValidator, errorContainer:errorContainer});
            validator.submitOrPrintErrors();
        });
    }
    return helper;
});
</pre>
<p><strong>PS</strong>: The modules names defined in the <em>declare</em> are 'aliases' to the actual modules, which we defined in the dataConfig above.</p>
<p>The helper class provides a single function '<strong>attachOnSubmitEvent</strong>' that takes three parameters; a form id, form profile and the error container id. It then attaches the 'onsubmit' event to the given form and whenever our form is submitted the following actions are taken place:<br />
1. Stop the default submit event<br />
2. Create a new form object and pass the form and profile in the constructor<br />
3. Create a new form validator object and pass the form object ( dependency injection ) as well as the id of the error container<br />
4. Call the validator's 'submitOrPrintErrors' function</p>
<p>The main function that is doing all the dirty work is validator's '<strong>submitOrPrintErrors</strong>'. Here is the dissect of the function:</p>
<p>1. Call the validateForm function of the BaseFormValidator object ( refer to the declare section or the very first line of helper.js file )<br />
2. If form validated without any error then submit the form<br />
3. Otherwise, get the form errors and transform those into an un-ordered list<br />
4. Then create a new Error object and pass the error container id and the unordered list<br />
5. Call the <strong>animateErrors</strong> function to display the errors ( currently no animation is applied to the error container but you can override this function in my/error/_base.js )</p>
<p>The <strong>base form class (my/form/_base.js)</strong> is nothing but a very simple Dojo class that has a constructor, getters and the validate function, which I already explained in my <a href="http://xebee.xebia.in/2012/04/24/dojox-form-validation-with-custom-error-messages/">previous blog</a>. I have attached the complete package for your reference, please have a look at the base form file in the attachment.</p>
<p><strong>PS</strong>: helper.js returns the 'helper' object, which is then returned by the form module 'my/form.js' file.</p>
<h3>Error Module</h3>
<p>If you understood the Form module then Error module is even simpler to understand.</p>
<p>The module file (my/error.js) :</p>
<pre class="brush: jscript; title: ; notranslate">
define([&quot;./form/_base&quot;], function(error){
    return error;
});
</pre>
<p>and the base error class (my/error/_base..js):</p>
<pre class="brush: jscript; title: ; notranslate">
define(['declare', 'dom', 'dom-class'], function(declare, dom, domClass){
    return declare(&quot;my.Error&quot;, null, {
        errorContainer : 'errors',
        errorHTML: &quot;&quot;,

        constructor: function(/*Object*/ args){
            declare.safeMixin(this, args);
        },

        animateErrors: function(){
            var node = dom.byId(this.errorContainer);
            var errHTML = this.errorHTML;
            node.innerHTML = errHTML;
            domClass.remove(node, 'display-none');
        }
    });
});
</pre>
<h3>The Climax</h3>
<p>What we have done here is that we have modularized our code and now we could simply <em>require</em> our form module and call the '<strong>attachOnSubmitEvent</strong>' function and the rest would be taken care by the form module. Having said that, the content of our <strong>validateRegister.js</strong> and <strong>validateLogin.js</strong> would look something like:</p>
<pre class="brush: jscript; title: ; notranslate">
//register form
require([&quot;ready&quot;], function(ready){
    ready(function(){
        require([&quot;xvalidate&quot;, &quot;my/form&quot;], function(xvalidate, myForm){
            var profile = {
                trim: [&quot;remail&quot;],
                required: [&quot;remail&quot;, &quot;rpassword&quot;, &quot;rrepassword&quot;],
                constraints : {...},
                confirm: {...},
                invalid: {...},
                missing: {...}
            };
            // args : form id, profile and error container id
            myForm.attachOnSubmitEvent(&quot;register-form&quot;, profile, 'errors');
        });
    });
});
</pre>
<pre class="brush: jscript; title: ; notranslate">
//login form
require([&quot;ready&quot;], function(ready){
    ready(function(){
        require([&quot;xvalidate&quot;, &quot;my/form&quot;], function(xvalidate, myForm){
            var profile = {
                trim: [&quot;lemail&quot;],
                required: [&quot;lemail&quot;, &quot;lpassword&quot;],
                constraints : {...},
                confirm: {...},
                invalid: {...},
                missing: {...}
            };
            // args : form id, profile and error container id
            myForm.attachOnSubmitEvent(&quot;login-form&quot;, profile, 'errors');
        });
    });
});
</pre>
<p>Summary:<br />
1. Learned how to setup a package directory<br />
2. Configured package for the loader<br />
3. Created the form validation module and the error module<br />
4. Learned how to add module aliases in the dojo config<br />
5. Learned how to include ( or require ) a module</p>
<p>This certainly is a very big walk-through but it should be really useful for guys like me who just started to get along with Dojo 1.7. Please feel free to comment or provide suggestions<br />
to improve this blog/tutorial.</p>
<p>The complete package file : <a href='http://xebee.xebia.in/wp-content/uploads/2012/05/my-package.zip'>my-package.zip</a></p>
<p>That's it folks...</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/05/03/form-validation-with-custom-modules-in-dojo-1-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LDAP Authentication using Spring Security</title>
		<link>http://xebee.xebia.in/2012/04/30/ldap-authentication-using-spring-security/</link>
		<comments>http://xebee.xebia.in/2012/04/30/ldap-authentication-using-spring-security/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 18:04:47 +0000</pubDate>
		<dc:creator>Anita Parida</dc:creator>
				<category><![CDATA[Spring]]></category>
		<category><![CDATA[LDAP]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13465</guid>
		<description><![CDATA[Recently, the project I was working on, required implementation of simple login functionality, where users were supposed to be authenticated against a remote Active Directory via LDAP. It was a maven project based on spring framework so we implemented the application security using the spring security framework. Problem Statement The Active Directory had users stored [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, the project I was working on, required implementation of simple login functionality, where users were supposed to be authenticated against a remote Active Directory via LDAP. It was a maven project based on spring framework so we implemented the application security using the spring security framework.<span id="more-13465"></span></p>
<p><font color=#FF8000><b><u>Problem Statement</u></b></font><br />
The Active Directory had users stored in a tree-structure which looked similar to the below example.<br />
<img class="alignleft" src="data:image/jpeg;base64,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" height="119" width="214" align="left" /></p>
<p>The Distinguished Name (DN) of the directory were like the following one -<br />
<i>CN=admin user,OU=Users,OU=Prod,DC=tst,DC=nl,DC=eur,DC=local</i></p>
<p>As we know that DN is used to uniquely identify a particular user entry, here the DN is formed using the user name and the application required the authentication to be done on the basis of combination of the user id (which is attributed to <i>sAMAccountName</i>, as shown in the example below) and user password.</p>
<p>Any particular user entry looked like this -<br />
<img class="alignleft" src="data:image/jpeg;base64,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" /></p>
<p><br><br><br><br><br><br><br />
<font color=#FF8000><b><u>Implemented Solution</u></b></font><br />
The login functionality was implemented using the Bind LDAP Authentication method in which we first bind the application to the directory using an admin user and then users can be searched based on the search criteria as provided.<br />
Below, I have summarized the steps to implement LDAP authentication using the spring security framework with 6 simple steps, which are as:</p>
<ol>
<li><b><u>Adding maven dependency for spring security</u></b></li>
<p>First of all, add the below dependencies to the <i>pom.xml</i> in your application.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-ldap&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-core&lt;/artifactId&gt;
&lt;version&gt;3.1.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-config&lt;/artifactId&gt;
&lt;version&gt;3.0.7.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-web&lt;/artifactId&gt;
&lt;version&gt;${spring.version}&lt;/version&gt;
&lt;type&gt;pom&lt;/type&gt;
&lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-taglibs&lt;/artifactId&gt;
&lt;version&gt;3.0.7.RELEASE&lt;/version&gt;
&lt;type&gt;pom&lt;/type&gt;
&lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;
</pre>
<p><br></p>
<li><b><u>Adding security configuration for authentication</u></b></li>
<p>Next, add a file <i>security-context.xml</i> to your project which contains the LDAP configuration required to connect and authenticate with the active directory.<br />
The <i>http</i> block specifies the access level to different url patterns and also the login &amp; logout actions. The authentication provider tag refers to <i>ldapProvider</i> for authentication base, which is the implementation object for LDAP Bind authentication built using the <i>contextSource</i>, <i>userSearch</i> and <i>CustomAuthoritiesPopulator</i> objects. The <i>contextSource</i> is the actual reference to the active directory which specifies the LDAP url and user DN, used to bind to the directory. The <i>userSearch</i> signfies the seach criteria to be used to search any particular user once the bind has been performed. The <i>CustomAuthoritiesPopulator</i> is used to define the authorized roles and has been discussed in the next section.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;http auto-config=&quot;true&quot; use-expressions=&quot;true&quot;&gt;
&lt;intercept-url pattern=&quot;/resources/**&quot; access=&quot;permitAll&quot; /&gt;
&lt;intercept-url pattern=&quot;/login&quot; access=&quot;permitAll&quot; /&gt;
&lt;intercept-url pattern=&quot;/**&quot; access=&quot;hasRole('ROLE_USER')&quot; /&gt;
&lt;form-login login-processing-url=&quot;/j_spring_security_check&quot; login-page=&quot;/login&quot; authentication-failure-url=&quot;/login?loginError=t&quot; default-target-url=&quot;/dashboard&quot; /&gt;
&lt;logout invalidate-session=&quot;true&quot; logout-success-url=&quot;/login&quot; logout-url=&quot;/logout&quot; /&gt;
&lt;/http&gt;
&lt;authentication-manager&gt;
&lt;authentication-provider ref=&quot;ldapProvider&quot; /&gt;
&lt;/authentication-manager&gt;
&lt;beans:bean id=&quot;contextSource&quot; class=&quot;org.springframework.security.ldap.DefaultSpringSecurityContextSource&quot;&gt;
&lt;beans:constructor-arg value=&quot;ldap://tst.nl.eur.local:389/&quot; /&gt;
&lt;beans:property name=&quot;userDn&quot; value=&quot;CN=admin user,OU=Users,OU=Prod,DC=tst,DC=nl,DC=eur,DC=local&quot; /&gt;
&lt;beans:property name=&quot;password&quot; value=&quot;password&quot; /&gt;
&lt;/beans:bean&gt;
&lt;beans:bean id=&quot;ldapProvider&quot; class=&quot;org.springframework.security.ldap.authentication.LdapAuthenticationProvider&quot;&gt;
&lt;beans:constructor-arg&gt;
&lt;beans:bean class=&quot;org.springframework.security.ldap.authentication.BindAuthenticator&quot;&gt;
&lt;beans:constructor-arg ref=&quot;contextSource&quot; /&gt;
&lt;beans:property name=&quot;userSearch&quot; ref=&quot;userSearch&quot; /&gt;
&lt;/beans:bean&gt;
&lt;/beans:constructor-arg&gt;
&lt;beans:constructor-arg&gt;
&lt;beans:bean class=&quot;com.tst.web.controller.CustomAuthoritiesPopulator&quot; /&gt;
&lt;/beans:constructor-arg&gt;
&lt;/beans:bean&gt;
&lt;beans:bean id=&quot;userSearch&quot; class=&quot;org.springframework.security.ldap.search.FilterBasedLdapUserSearch&quot;&gt;
&lt;!-- searchBase, searchFilter, contextSource --&gt;
&lt;beans:constructor-arg index=&quot;0&quot; value=&quot;OU=Users,OU=Prod,DC=tst,DC=nl,DC=eur,DC=local&quot; /&gt;
&lt;beans:constructor-arg index=&quot;1&quot; value=&quot;sAMAccountName={0}&quot; /&gt;
&lt;beans:constructor-arg index=&quot;2&quot; ref=&quot;contextSource&quot; /&gt;
&lt;/beans:bean&gt;
</pre>
<p>In the above file, we first do a ldap bind operation using the admin user and then we do a search in the directory using the field <i>sAMAccountName</i> as the search criteria. The <i>{0}</i> indicates that user id entered by used would be substituted in its place.<br />
Instead of providing the admin user and password in the default context, you may also read it from a property file, as-<br />
<i>value="${ldap.admin.user.dn}"<br />
value="${ldap.admin.user.password}"</i><br />
<br></p>
<li><b><u>Adding authorization roles</u></b></li>
<p>Then, you need to add a java class, as <i>CustomAuthoritiesPopulator.java</i>, to define the authoritizations.</p>
<pre class="brush: plain; title: ; notranslate">
public class CustomAuthoritiesPopulator implements LdapAuthoritiesPopulator {
public Collection&lt;GrantedAuthority&gt; getGrantedAuthorities(DirContextOperations arg0, String arg1) {
ArrayList&lt;GrantedAuthority&gt; list = new ArrayList&lt;GrantedAuthority&gt;();
list.add((new SimpleGrantedAuthority(&quot;ROLE_USER&quot;)));
return list;
}
}
</pre>
<p><br></p>
<li><b><u>Configuring web.xml to activate URL filtering</u></b></li>
<p>Next, add filter to the web.xml and also load the <i>security-context.xml</i> to the context configuration.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;/WEB-INF/security-context.xm&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;DispatcherServlet&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;DispatcherServlet&lt;/servlet-name&gt;
&lt;url-pattern&gt;/&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;filter&gt;
&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
&lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
<p><br></p>
<li><b><u>Adding login page</u></b></li>
<p>Now, we add the login.jsp to our application which uses the predefined objects corresponding to the spring security framework. It also includes an if statement to display a login error message, in case logout attempt fails.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;form action=&quot;j_spring_security_check&quot; name=&quot;loginForm&quot; method=&quot;post&quot;&gt;
&lt;table id=&quot;login&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th colspan=&quot;2&quot; align=&quot;center&quot;&gt;&lt;h3&gt;Login&lt;/h3&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;c:if test=&quot;${param.loginError == 't'}&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;Invalid UserId/password&lt;/td&gt;&lt;/tr&gt;
&lt;/c:if&gt;
&lt;tr&gt;
&lt;td&gt;&lt;label class=&quot;inputLabel&quot; for=&quot;j_username&quot;&gt;User Id:&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type='text' name='j_username' value='' id=&quot;j_username&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;label class=&quot;inputLabel&quot; for=&quot;j_password&quot;&gt;Password:&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type='password' name='j_password' value='' id=&quot;j_password&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;input name=&quot;submit&quot; type=&quot;submit&quot; value='Login'/&gt;&lt;/td&gt;
&lt;td&gt;&lt;input name=&quot;reset&quot; type=&quot;reset&quot; id=&quot;resetButton&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/form&gt;
</pre>
<p><br></p>
<li><b><u>Adding logout and blocking caching</u></b></li>
<p>Finally, provide the logout action as below on the <i>dashboard.jsp</i> (which happens to be the landing page for the user after a successful login attempt).</p>
<pre class="brush: plain; title: ; notranslate">&lt;a href='&lt;spring:url value=&quot;/logout&quot; htmlEscape=&quot;true&quot;/&gt;'&gt;logout&lt;/a&gt;</pre>
<p>Sometimes, it may happen that once the user has logged in successfully, he is able to view the dashboard page by hitting the url directly even after doing a logout. This may happen due to browser caching which depends on the browser solely. However, this can be avoided using a meta tag as -</p>
<pre class="brush: plain; title: ; notranslate">&lt;meta http-equiv=&quot;Pragma&quot; content=&quot;no-cache&quot;&gt;</pre>
</ol>
<p>Hope this information helps building security in your application.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/30/ldap-authentication-using-spring-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to integrate Twitter into your web application with OAuth?</title>
		<link>http://xebee.xebia.in/2012/04/30/how-to-integrate-twitter-into-your-web-application-with-oauth/</link>
		<comments>http://xebee.xebia.in/2012/04/30/how-to-integrate-twitter-into-your-web-application-with-oauth/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 10:24:32 +0000</pubDate>
		<dc:creator>Varun Jalandery</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13478</guid>
		<description><![CDATA[Twitter provides APIs for integrating with web applications using OAuth. By integrating Twitter within our web application we can show the tweets posted by a particular user, his/her friends, their tweets, post new tweets etc. Also we can provide “Sign in with Twitter Login” functionality in the web application. So users do not need to [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter provides APIs for integrating with web applications using OAuth. By integrating Twitter within our web application we can show the tweets posted by a particular user, his/her friends, their tweets, post new tweets etc. Also we can provide “Sign in with Twitter Login”  functionality in the web application. So users do not need to have a separate user id, instead they can use their Twitter Login to sign in to our web application.<span id="more-13478"></span></p>
<p>OAuth (Open Authentication) provides our web application a way to access the resources owned by the  resource owners without knowing their credentials. For more information on OAuth, you may want to visit the following link:<br />
<a href="http://hueniverse.com/oauth/" target="_blank">http://hueniverse.com/oauth</a></p>
<p>The first thing that we are going to need for integrating Twitter is Twitter Account.<br />
You will be also need a web server with public IP so that Twitter can connect to the same. We will discuss later why we need this.<br />
We will be using TwitterOAuth library (written in PHP) for integrating the Twitter with our web application. This library can be downloaded from the following link:<br />
<a href="https://github.com/abraham/twitteroauth/downloads" target="_blank">https://github.com/abraham/twitteroauth/downloads</a></p>
<p>Before getting our hands dirty, let us discuss our approach.</p>
<p>We will create one Twitter application, and Twitter will provides us Consumer Key and Consumer Secret for the same.<br />
We will use the consumer key and consumer secret to connect to Twitter in order to get request token.<br />
Then we will provide this request token to the Twitter and take user to the Twitter Login where he/she can enter his/her credentials on the Twiiter Website and in return we will receive access token.<br />
This access token will be enable our web application to use his Twitter Account(in a limited way).<br />
So by this access token our web application can show his Tweets, friends' tweets, post new tweets etc.</p>
<p>Now let us move on to the coding part.</p>
<p>Goto the URL : <a target="_blank" href="https://dev.twitter.com">https://dev.twitter.com</a> and sign in with your twitter account. The page you see is meant for developers. After you have successfully logged in, hover onto your username on the top-right corner of the screen. You will see a “My Application” link. Click on that link and then create new application there.</p>
<p>Put the name and description to whatever you wish. In the Callback Url  field, provide a url which is publicly accessible. For our demo application, we are setting it to [http://210.7.69.29/twoth/authenticate.php]. Click create and your application is ready. Scroll down the page and copy the Consumer Key and Consumer Secret to a safe place for future reference.</p>
<p><iframe src="https://skydrive.live.com/embed?cid=F9ECD7151D57C013&resid=F9ECD7151D57C013%21240&authkey=ANw3EGYDkoI9gBs" width="320" height="266" frameborder="0" scrolling="no"></iframe></p>
<p>Now goto the application settings and change the access to Read and Write. This is required if we need to post new tweets from the logged in user's account. Till here we are done with Twitter settings.</p>
<p>Lets move on to the TwitterOAuth library. I assume that you have downloaded the archive from the<br />
<a target="_blank" href="https://github.com/abraham/twitteroauth/downloads">link</a> mentioned above in the blog. Extract the archive and copy the directory named twitteroauth. Inside this directory there will be two files namely twitteroauth.php and oauth.php. So we will be using these two files only from the library.</p>
<p>Our demo application directory structure will be as below:</p>
<p><iframe src="https://skydrive.live.com/embed?cid=F9ECD7151D57C013&resid=F9ECD7151D57C013%21243&authkey=ANTe7xqqGDq0N60" width="204" height="239" frameborder="0" scrolling="no"></iframe></p>
<p>So you can create the above shown directory structure and save it in the webroot directory of the web server.</p>
<p>Firstly, we will create our configuration file, in this file we will define the Consumer Key and Consumer Secret for the Twitter Application.<br />
So Copy the Consumer key and consumer secret from the application page on the twitter website and paste the same in the config file as shown below:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * twoth/config/config.php
 * Configuration file.
 * Used for defining the Consumer key and Consumer Secret of Twitter
 * Application.
 */

define('CONSUMER_KEY','***********************');
define('CONSUMER_SECRET','*********************************************');
</pre>
<p>Lets move on to the index.php file. In this file we will import the following three files:</p>
<ul>
<li>lib/twitteraouth/twitteroauth.php</li>
<li>lib/twitteraouth/oauth.php</li>
<li>config/config.php</li>
</ul>
<p>The library file twitteroauth.php provides us a class TwitterOAuth which we will be using extensively to connect to Twitter.<br />
The source code for the index.php is shown below:</p>
<pre class="brush: php; title: ; notranslate">
require_once 'lib/twitteroauth/OAuth.php';
require_once 'lib/twitteroauth/twitteroauth.php';
require_once 'config/config.php';

session_start();

/*
 * Instantiating the TwitterOAuth class with the Consumer key and consumer
 * secret as defined in config.php file.
 */
$twitterOAuth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);

/*
 * calling getRequestToken() method to get the request token.
 * the request token will be used later to compare it with the token
 * returned from the Twitter again on the callback URL (as specified)
 * in the application settings.
 * In our case it is http://210.7.69.29/twoth/authenticate.php
 * As I have mentioned before, this callback url should be publicly accessible.
 */
$requestToken = $twitterOAuth-&gt;getRequestToken();

/*
 * saving the request token in the session for future use
 */
$_SESSION['request_token'] = $requestToken['oauth_token'];
$_SESSION['request_token_secret'] = $requestToken['oauth_token_secret'];

/*
 * Redirecting the user to the Twitter Sign in page where he/she will
 * provide his/her user credentials.
 */
header ('Location: ' . $twitterOAuth-&gt;getAuthorizeURL($requestToken));
</pre>
<p>Now if user has successfully entered his/her credentials, he will redirected to the callback url. Twitter will pass one parameter named "oauth_token" in the url itself. This parameter will be compared to the request token saved in the session, both of these parameters should be same.</p>
<p>Below is the source code for the authenticate.php file:</p>
<pre class="brush: php; title: ; notranslate">
require_once 'lib/twitteroauth/OAuth.php';
require_once 'lib/twitteroauth/twitteroauth.php';
require_once 'config/config.php';

session_start();

/*
 * Comparing the request token with the token passed by the Twitter in the
 * url as the parameter named &quot;oauth_token&quot;
 */

if($_SESSION['request_token'] == $_GET['oauth_token']) {

    /*
     * Instanitiating the TwitterOAuth class with the consumer token and
     * the request token
     */
    $twitterOAuth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET,
    $_SESSION['request_token'],$_SESSION['request_token_secret']);

    /**
     * Getting the access token from the Twitter.
     * This access token will be used by our web application.
     * It is only this access token which enables us to use the
     * Twitter account of the user (in limited way).
     * By this access token we can read tweets, friends' tweets, post new
     * tweets etc.
     */
    $accessToken = $twitterOAuth-&gt;getAccessToken();
    if(isset($accessToken['user_id']) &amp;&amp; is_numeric($accessToken['user_id'])){
        /*
         * Saving the access token in the session
         */
        $_SESSION['access_token'] = $accessToken['oauth_token'];
        $_SESSION['access_token_secret'] = $accessToken['oauth_token_secret'];

        /*
         * Redirect the user to the success.php where we will show his/her
         * profile image and friends alongwith the tweets.
         */
        header('Location: ' . '/twoth/success.php');
    }
} else {

    /*
     *If token retured from the Twitter to the callback url doesn't
     * match with the token which is saved already in the session, then
     * redirect the user to the failure page.
     */
    header('Location: ' . '/twoth/failure.php' );
}
</pre>
<p>Now in the success.php file we will show the Twitter Username and the friend list along with their tweets.</p>
<pre class="brush: php; title: ; notranslate">

        require_once 'lib/twitteroauth/OAuth.php';
        require_once 'lib/twitteroauth/twitteroauth.php';
        require_once 'config/config.php';

        session_start();

        if( !empty( $_SESSION['access_token'] ) &amp;&amp;
            !empty( $_SESSION['access_token_secret'] )) {

            $twitterOAuth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET,
                    $_SESSION['access_token'], $_SESSION['access_token_secret']);

            /*
             * Verifying the credentials of the Twitter User.
             * If verified, Twitter will return the User information such as
             * name, screen name, profile pic etc.
             */
            $user = $twitterOAuth-&gt;get('account/verify_credentials');

            /*
             * Posting a new Tweet to the Twitter User account.
             * The tweet will be having the message
             * &quot;Status from Twoth...actual date&quot;
             */
            $twitterOAuth-&gt;post(
            'statuses/update',
            array( 'status' =&gt; &quot;Status from Twoth...&quot;.date('d-M-Y H:i:s') )
            );

            /*
             * Getting the friends of the Twitter user
             * $friends will contain the Twitter user friends along with the
             * other information such as profile pic, name, sceen name, latest
             * tweet etc.
             */
            $friends = $twitterOAuth-&gt;get('statuses/friends');

        }
</pre>
<p>Below is the html code which will be used to display the Twitter User information along with his/her friend list.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;h1&gt;Welcome to Twoth&lt;/h1&gt;
        &lt;?php
        /* Displaying the Twitter user information.
         *
         */
        ?&gt;
        &lt;span&gt;&lt;img src=&quot;&lt;?php echo $user-&gt;profile_image_url; ?&gt;&quot; /&gt;&lt;/span&gt;
        &lt;span&gt;&lt;?php echo $user-&gt;name. '(' . $user-&gt;screen_name . ')'; ?&gt;&lt;/span&gt;
        &lt;?php
        /* Displaying the Twitter user's friends information along with
         * their profile image, name and latest tweet.
         *
         */
        ?&gt;

        &lt;div class=&quot;friends&quot;&gt;
            &lt;h2&gt;Here are your friends with their statuses.&lt;/h2&gt;
            &lt;ol&gt;
                &lt;?php foreach($friends as $friend):?&gt;
                    &lt;div class=&quot;friend&quot;&gt;
                        &lt;li&gt;
                            &lt;span&gt;
                                &lt;img src=&quot;&lt;?php echo $friend-&gt;profile_image_url; ?&gt;&quot; /&gt;
                            &lt;/span&gt;
                            &lt;span&gt;
                               &lt;?php echo $friend-&gt;name. '(' .
                                               $friend-&gt;screen_name . ')'; ?&gt;
                            &lt;/span&gt;
                            &lt;div class=&quot;latest-tweet&quot;&gt;
                                &lt;?php echo isset($friend-&gt;status-&gt;text) ?
                                                $friend-&gt;status-&gt;text : ''; ?&gt;
                            &lt;/div&gt;
                        &lt;/li&gt;
                    &lt;/div&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ol&gt;
        &lt;/div&gt;
</pre>
<p>So this is how we can integrate Twitter into our own web application.<br />
Below is the link to download the complete code:<br />
<iframe src="https://skydrive.live.com/embed?cid=F9ECD7151D57C013&resid=F9ECD7151D57C013%21245&authkey=ACHPh9t3lk-S70o" width="98" height="120" frameborder="0" scrolling="no"></iframe><br />
Please note that in order to get this code working, you have to replace the consumer key and consumer secret in the config.php file with the actual values.</p>
<p>And below is the link for the complete working example of the code:<br />
<a href="http://210.7.69.29/twoth" target="_blank">Goto working example</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/30/how-to-integrate-twitter-into-your-web-application-with-oauth/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Layouts with Dojo</title>
		<link>http://xebee.xebia.in/2012/04/26/layouts-with-dojo/</link>
		<comments>http://xebee.xebia.in/2012/04/26/layouts-with-dojo/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 16:05:53 +0000</pubDate>
		<dc:creator>Varun Jalandery</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13365</guid>
		<description><![CDATA[Dojo is a powerful JavaScript framework for developing web applications. I was exploring layouts in Dojo and found that it provides us various amazing widgets as a part of Dijit (Dojo's UI framework) which helps us in creating layouts with great user experience quickly. In this blog we will see how we can create layouts [...]]]></description>
			<content:encoded><![CDATA[<p>Dojo is a powerful JavaScript framework for developing web applications. I was exploring layouts in Dojo and found that it provides us various amazing widgets as a part of Dijit (Dojo's UI framework) which helps us in creating layouts with great user experience quickly. In this blog we will see how we can create layouts in Dojo. Basically, what we are going to do is that we will create a simple layout with three tabbed panes. And in the first tabbed pane we will create a menu .<span id="more-13365"></span></p>
<p>Dojo provides us two ways to implement the layouts. One is markup style and the other way is creating layouts programmatically. I explored both the ways and in this blog we will use both ways to create the layout.</p>
<p>So lets begin.<br />
In the header section of our HTML file, we include the dojo.js file as shown below:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script src='http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js'
				data-dojo-config=&quot;async: true, parseOnLoad: true&quot;&gt;
&lt;/script&gt;
</pre>
<p>As you might have noticed, the configuration parameters are async:true and pasrseOnLoad: true.<br />
<strong>async </strong> defines if Dojo core should be loaded asynchronously.<br />
<strong>parseOnLoad </strong> If true, parses the page with dojo/parser when the DOM and all initial dependencies have loaded.  </p>
<p>Now our next step is to create the layout by using the declarative syntax. By declarative syntax we will create a Tabbed Pane with three tabs namely First Tab, Second Tab and Third Tab. Dojo provides us the HTML widgets which we can import and use to create layouts quickly and that is what exactly we are going to do.</p>
<p>Also Dojo provides us the themes which we can use to provide our layout the feel-good factor.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;link rel=&quot;stylesheet&quot; media=&quot;screen&quot;
        href=&quot;http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dijit/themes/claro/claro.css&quot; /&gt;
</pre>
<p>The above tag will include the CSS for claro theme, other themes are also available like Soria, Tundra, Nihilo etc.<br />
For more information on themes visit the below link:<br />
<a href="http://dojotoolkit.org/reference-guide/1.7/dijit/themes.html">http://dojotoolkit.org/reference-guide/1.7/dijit/themes.html</a></p>
<p>After importing the theme just include the class “claro” in the body tag of page. This will appropriately style the entire html elements which we are going to create inside the body of the page.</p>
<p>In the markup style of creating layout in Dojo, it (Dojo) relies heavily on data-dojo- attributes. These attributes tell the Dojo what widget class to instantiate and then which properties to apply on the widget. So this means below HTML div is not just ordinary div but infact it is TabConatiner Widget provided by the Dojo.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div class=&quot;demoLayout&quot; id=&quot;appLayout&quot;
       data-dojo-props=&quot;region: 'center', tabPosition: 'bottom'&quot;
       data-dojo-type=&quot;dijit.layout.TabContainer&quot;&gt;
&lt;/div&gt;
</pre>
<p>The above HTML code will create a Tabbed Container which allows us to create tabs inside it.<br />
The data-dojo-type attribute tell the Dojo parser to instantiate the TabContainer widget.<br />
And the data-dojo-props attribute defines the additional parameters for the widget. The parameter region tell the place where TabContainer is to be placed and the tabPosition defines the position of the tabs which will be used by the user to navigate among the tabs.</p>
<p>Now inside the div with id=”appLayout” place the following code:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div data-dojo-props=&quot;title: 'First Tab'&quot; data-dojo-type=&quot;dijit.layout.ContentPane&quot; class=&quot;centerPanel&quot;&gt;
&lt;h1&gt;First Tab&lt;/h1&gt;
&lt;/div&gt;
</pre>
<p>Above HTML code would create the tabbed pane for the first tab. As you must have noticed this time we have used the widget ContentPane for the data-dojo-type attribute in order to instantiate the same.</p>
<p>In the data-dojo-props attribute, we have set the title of the tab as First Tab.</p>
<p>Similarly, we will create the other two tabs.</p>
<p>Till this far, we have been using the markup style for creating the layout. Now we will use programmatic style to further add a menu in the First Tab. We will create the menu when the DOM will be ready. For the menu we will import the ComboButton, Menu and MenuItem widgets.<br />
We are also handling the click event for the menu so whenever user clicks the menu he will be able to see a message in a div having id=”output”.</p>
<pre class="brush: jscript; title: ; notranslate">

    require([&quot;dojo/dom&quot;,
	        &quot;dijit/form/ComboButton&quot;,
	        &quot;dijit/Menu&quot;,
	        &quot;dijit/MenuItem&quot;,
	        &quot;dojo/domReady!&quot;
            ], function(dom, ComboButton, Menu, MenuItem, domReady) {
		      var menu = new Menu({ id: &quot;optionsMenu&quot;});
		      var menuItem1 = new MenuItem({ label: &quot;Option 1&quot;,
                       				       onClick: function() { dom.byId(&quot;output&quot;).innerHTML = &quot;Option 1 Clicked&quot;; }
				                });
		      var menuItem2 = new MenuItem({ label: &quot;Option 2&quot;,
					              onClick: function() { dom.byId(&quot;output&quot;).innerHTML = &quot;Option 2 Clicked&quot;;  }
				               });
		      var menuItem3 = new MenuItem({ label: &quot;Option 3&quot;,
					              onClick: function() { dom.byId(&quot;output&quot;).innerHTML = &quot;Option 3 Clicked&quot;;  }
				               });

             menu.addChild(menuItem1);
		     menu.addChild(menuItem2);
		     menu.addChild(menuItem3);
		     var comboButton = new ComboButton({ optionsTitle: &quot;Save Options&quot;, label: &quot;Menu&quot;, dropDown: menu,
 					                 onClick:function(){ dom.byId(&quot;output&quot;).innerHTML = &quot;Menu Clicked&quot;; }
				                  }, &quot;combo&quot;);

		     //calling the startup methods in the widgets is necessary. Otherwise widgets won't show up properly.
		     comboButton.startup();
		     menu.startup();
    });
</pre>
<p>This is how we create layouts in Dojo.<br />
Here is the summary:<br />
1. We learned markup and programmatic ways of creating layouts in Dojo.<br />
2. We created a tabbed pane with three tabs by using markup style.<br />
3. We created a menu on the first tab by programmatic way of creating the layout.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/26/layouts-with-dojo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DojoX form validation with custom error messages</title>
		<link>http://xebee.xebia.in/2012/04/24/dojox-form-validation-with-custom-error-messages/</link>
		<comments>http://xebee.xebia.in/2012/04/24/dojox-form-validation-with-custom-error-messages/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 12:47:14 +0000</pubDate>
		<dc:creator>Anubhav</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13319</guid>
		<description><![CDATA[I was following this tutorial and got stuck when I wanted to show my custom error messages. I did not want to use the Dijit-based form widgets because I may change the JavaScript framework in future or in other words decoupled HTML form and validation. If I use Dijit-based form then it is no hassel [...]]]></description>
			<content:encoded><![CDATA[<p>I was following <a href="http://dojotoolkit.org/documentation/tutorials/1.7/validation/">this tutorial</a> and got stuck when I wanted to show my custom error messages. I did not want to use the Dijit-based form widgets because I may change the JavaScript framework in future or in other words decoupled HTML form and validation. If I use Dijit-based form then it is no hassel to show my custom error but as I said that I do not want to use Dijit-based form for simplicity and modularity.</p>
<p><span id="more-13319"></span></p>
<p>Here is an example of how you could print your custom error message if you used the Dijit-based form:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;input id=&quot;email&quot; name=&quot;email&quot;  data-dojo-type=&quot;dijit.form.ValidationTextBox&quot;
        data-dojo-props=&quot;validator:dojox.validate.isEmailAddress,
        invalidMessage:'This is not a valid email!'&quot;  /&gt;
</pre>
<p>but to decouple my HTML structure with the validation I chose to create a normal HTML form and applied Dojo valiations on it.</p>
<p>Here is the HTML:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id='errors'&gt;&lt;/div&gt;
&lt;form name='register' id='register-form' method='POST' action=&quot;/register/&quot;&gt;
	&lt;label for='remail'&gt;Email&lt;/label&gt;&lt;input type='text' value='' name='email' id='remail'/&gt;
	&lt;label for='rpassword'&gt;Password&lt;/label&gt;&lt;input type='password' value='' name='password' id='rpassword'/&gt;
	&lt;label for='rrepassword'&gt;Re-type Password&lt;/label&gt;&lt;input type='password' value='' name='repassword' id='rrepassword'/&gt;
	&lt;input type='submit' class='button' id='submit-register' value='Create my account' /&gt;
&lt;/form&gt;
</pre>
<p><strong>Assumption</strong>: I am assuming that you know how to add dojo.js to your source, if not look <a href="http://dojotoolkit.org/documentation/tutorials/1.7/hello_dojo/">here</a>.</p>
<p>Now, lets create the submit handler, form profile and the validator:</p>
<pre class="brush: jscript; title: ; notranslate">
dojo.require('dojox.validate.web');
dojo.require('dojox.validate.check');

var profile;

function validateForm(form){
    var results = dojox.validate.check(form, profile);
    errors = [];
    if (!results.isSuccessful()){
        missing = results.getMissing();
        invalid = results.getInvalid();

       // see the rest of the blog to find the code

    }
    return errors;
}

dojo.ready(function(){

    profile = {
        trim: [&quot;email&quot;],
        required: [&quot;email&quot;, &quot;password&quot;, &quot;repassword&quot;],
        constraints : {
            email: [dojox.validate.isEmailAddress, false, true],
            password: dojox.validate.isText,
            repassword: dojox.validate.isText
        },
        confirm: {
            &quot;repassword&quot;: &quot;password&quot;
        }
    }

    // check onsubmit event and show errors, if any
    var f = dojo.query(&quot;#register-form&quot;)[0];
    f.onsubmit = function(e){
        dojo.stopEvent(e);
        errors = validateForm(f);
        if (!errors){
            // no errors found, submit your form
        } else {
            var msgs = &quot;&lt;ul&gt;&quot;;
            for(var key in errors){
                msgs += &quot;&lt;li&gt;&quot;+errors[key]+&quot;&lt;/li&gt;&quot;;
            }
            msgs += &quot;&lt;/ul&gt;&quot;;
            dojo.query('#errors')[0].innerHTML = msgs;
        }
    };
});
</pre>
<p>The above code still doesn't give you a way to add your custom messages. I added the following two arrays in my form 'profile' ( key names are self-explanatory):</p>
<pre class="brush: jscript; title: ; notranslate">
    //final form profile
    profile = {
        trim: [&quot;email&quot;],
        required: [&quot;email&quot;, &quot;password&quot;, &quot;repassword&quot;],
        constraints : {
            email: [dojox.validate.isEmailAddress, false, true],
            password: dojox.validate.isText,
            repassword: dojox.validate.isText
        },
        confirm: {
            &quot;repassword&quot;: &quot;password&quot;
        },
        // please be more creative with error messages
        invalid: {
          email : &quot;Invalid email&quot;,
          password: &quot;Invalid password&quot;,
          repassword: &quot;Invalid confirm password&quot;
        },
        missing: {
            email: &quot;Missing email&quot;,
            password: &quot;Missing password&quot;,
            repassword: &quot;Missing confirm password&quot;
        }
    }
</pre>
<p>Next, we will update our validateForm() function so that we could grep the correct error messages, save them in the errors array and return it to the submit handler.</p>
<p><em><strong>PS: The getMissing() and getInvalid() returns the 'name' of the element and not the 'id'. Please be careful when you define your own 'invalid' and 'missing' items for form profile, make sure you use the field names and not the ids.</strong></em></p>
<p>Here is the complete validationForm() function, which returns your custom error messages defined in the form 'profile' variable:</p>
<pre class="brush: jscript; title: ; notranslate">
function validateForm(form){
    var results = dojox.validate.check(form, profile);
    errors = [];
    if (!results.isSuccessful()){
        missing = results.getMissing();
        invalid = results.getInvalid();
        for(var i in missing){
            // missing[i] contains the name of the element
            msg = profile['missing'][missing[i]];
            if (msg) {
                errors.push(msg);
            }
        }
        for(var i in invalid){
            // invalid[i] contains the name of the element
            msg = profile['invalid'][invalid[i]];
            if (msg) {
                errors.push(msg);
            }
        }
    }
    return errors;
}
</pre>
<p><strong>Summary:</strong><br />
1. Create a normal HTML form<br />
2. Use dojo's onsubmit handler to handle the default event<br />
3. Add 'invalid' and 'missing' arrays to the form profile ( use field names and not ids for array keys )<br />
4. In your validator function get all the missing and invalid field names<br />
5. Iterate over both missing and invalid array and fetch the custom error message from the form profile</p>
<p>That's it folks...</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/24/dojox-form-validation-with-custom-error-messages/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Publishing a Salesforce Application : Bottleneck and Recommendations</title>
		<link>http://xebee.xebia.in/2012/04/24/publishing-a-salesforce-application-bottleneck-and-recommendations/</link>
		<comments>http://xebee.xebia.in/2012/04/24/publishing-a-salesforce-application-bottleneck-and-recommendations/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 09:28:52 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[SalesForce]]></category>
		<category><![CDATA[salesforce]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13309</guid>
		<description><![CDATA[After you have developed your first Salesforce application, the next step would be to market your application and share it with millions of other users. Publishing an app also enables many organizations to build a good relationship with potential customers. This step is called 'Publishing' and the place where you can make your app publicly [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;">After you have developed your first </span><a target="_blank" href="http://www.salesforce.com/in/"><span style="color: #ff9900;">Salesforce</span></a><span style="color: #000000;"> application, the next step would be to <strong>market your application</strong> and share it with millions of other users. </span></p>
<p><span style="color: #000000;">Publishing an app also enables many organizations to build a good relationship with potential customers.</span></p>
<p><span style="color: #000000;">This step is called '<span style="font-size: small;"><strong>Publishing</strong></span>' and the place where you can make your app publicly available is called </span><a href="https://sites.secure.force.com/appexchange/home"><span style="color: #ff9900;"><strong>AppExchange</strong></span></a><span style="color: #000000;">.</span></p>
<p><span style="color: #000000;">AppExchange is an online marketplace for cloud computing applications and services. It is also a community where you can build, develop, customize your applications and then share it globally over the internet. <span style="line-height: 16px;"> </span>At present, </span><a href="https://sites.secure.force.com/appexchange/home"><span style="color: #ff9900;">AppExchange </span></a><span style="color: #000000;">has more than 1400 <span style="line-height: 16px;">applications</span><span style="line-height: 16px;"> </span><span style="line-height: 16px;">available</span><span style="line-height: 16px;"> in </span><span style="line-height: 16px;">its public directory</span></span></p>
<p><span style="line-height: 16px;"><span id="more-13309"></span><span style="color: #000000;">Amongst the benefits of AppExchange, </span></span><span style="color: #000000;">"showcasing your talent and take your application to market <strong>quickly</strong>" is the one. The word "quickly"  doesn't mean really quick, as it may take a while to get your application through certain bottlenecks before you can cherish watching it publicly available. </span></p>
<p><span style="color: #000000; font-size: small;"><strong>Before I go into the 'slowing you down' areas, lets revisit the steps involved in the whole process.</strong></span></p>
<ol>
<li><span style="text-decoration: underline;"><strong><em> </em></strong></span><strong></strong> Create a developer account and start building your application</li>
<li><span style="text-decoration: underline;"><strong><em></em></strong></span>Write test cases to have your code coverage above 75%, being it a prerequisite of creating a managed/un-managed package. For more information regarding packaging a salesforce application, refer <a target="_blank" href="http://xebee.xebia.in/2011/09/30/packaging-a-salesforce-application-things-to-keep-in-mind/"><span style="color: #ff6600;">this link</span></a><span style="color: #ff6600;">.</span></li>
<li><strong><span style="text-decoration: underline;"><em></em></span></strong> Create a package successfully and acquire an installation <em>URL </em>that points to application's installer on Salesforce cloud. Though this url can be distributed for installation into any devoloper, sandbox  or production account, <strong>the application won't be available when you search it on the market place</strong>. Hence, the whole purpose building the application (<em>stated in paragraph 1 of this blog</em>) is still not fulfilled. <strong>This is where publishing an app comes into picture</strong>.</li>
</ol>
<p><span style="color: #000000;">For this, first you need to create an account on </span><a target="_blank" href="https://sites.secure.force.com/appexchange/"><span style="color: #ff6600;">AppExchange</span></a><span style="color: #000000;">. Here, you can use the credentials of your developer account which you are using to create the latest package, to login into AppExchange. This will automatically connect your developer account to your AppExchange Profile. </span></p>
<p><span style="color: #000000;">Visit the 'Publishing' tab. Here,  you need to create a listing (initially it will be private) and fill-in the required forms on AppExchange which contains sections for adding Basic information about your organization. There are other tabs like Offerings, Overview, Specs, Support, Lead which are self explanatory.</span></p>
<p><span style="color: #000000;">Optionally, you can upload PDF''s,  pictures of your application for all good purposes.</span></p>
<p><span style="color: #000000;">Under the offerings section, you can use the dropdown box to select the desired package for that particular listing. Each application/package requires its separate listing to be created with the necessary information. However, you can manage more than one application within a single AppExchange account (usually for the same Organization).</span></p>
<p><span style="color: #000000; font-size: medium;"><strong>Now comes the areas which need some attention . </strong></span></p>
<p><strong>First</strong>, <strong>Having a<span style="color: #ff6600;"> PARTNER PORTAL</span> account</strong>. You need to have an Organization linked to this profile. Filling-in information about the Organization account is not enough. For this, you need to join Salesforce using this form <a target="_blank" href="http://www.salesforce.com/partners/join/"><span style="color: #ff9900;">http://www.salesforce.com/partners/join/</span></a> and wait to get the credentials you can supply to your provider profile to actually link to your Organization. This account can be used in future to raise any tickets (cases) for contacting Salesforce support while publishing.</p>
<p><strong>Next, Getting your App pass the</strong> <a target="_blank" href="http://wiki.developerforce.com/page/Security_Review"><span style="color: #ff6600;"><strong>SECURITY REVIEW</strong></span></a>. Once you get a partner profile, you are eligible to start the review process. Only after passing a security review, you can have your application publicly listed. Till then it will only be privately listed (<em>Remember you still can explicitly distribute the link</em>).</p>
<p><strong>Getting a security review results can take longer than expected. Hence, it is better that you do the following before submitting a package for security review through AppExchange.</strong></p>
<ul>
<li><strong></strong><span style="color: #008000;"><strong><span style="font-size: medium;">Perform your source code scanning in advance</span>.</strong></span> To do that, download the security scanner provided by <a target="_blank" href="http://blogs.developerforce.com/engineering/2011/01/source-code-scanning.html"><strong>Checkmarx</strong></a>. The advantage  is that you get actionable results, directly  in your IDE, without having to cross reference line numbers in a report. visit <a target="_blank" href="http://blogs.developerforce.com/engineering/2011/01/source-code-scanning.html"> http://blogs.developerforce.com/engineering/2011/01/source-code-scanning.html </a>for <a target="_blank" href="http://www.apexscanner.com/">download link</a> and other details. Otherwise, you will see this in the report with a subject line of security review result  email "<span style="color: #ff0000;">Security Review - Your App Did Not Pass</span>" .</li>
<li><strong></strong><span style="font-size: medium;">Keep the access modifier of your classes which deals with persistent objects or external sources as <strong>"<span style="color: #008000;">with sharing</span></strong>".</span></li>
<li><strong></strong><span style="font-size: medium;"> Keep the endpoints/remote sites being accessed by your application as <strong>secured </strong>(<strong><span style="color: #008000;">SSL </span></strong>enabled/on <strong><span style="color: #008000;">https</span></strong>) </span> or you will not be able to get your app pass the review process.</li>
</ul>
<p><strong>There are other small things which one learns after going through this process like :</strong> Prefer not to include any extra tabs while packaging your application. This may cause trouble while installing at the client side if the target account fall short of tabs. You can always create tab, if required after the successful installation, on the top of any Salesforce page.</p>
<p>We are still in process of getting our first Salesforce app in to the market, and I hope that my experience shared in this blog can help you getting through this faster <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;" class="mcePaste" id="_mcePaste"><span id="browseApps:page_browse"></p>
<h1>AppExchange has <em>1462 Apps</em></h1>
<p></span></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/24/publishing-a-salesforce-application-bottleneck-and-recommendations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Great India Developer Summit 5.0 : Developer&#8217;s perspective</title>
		<link>http://xebee.xebia.in/2012/04/23/great-india-developer-summit-5-0-developers-perspective/</link>
		<comments>http://xebee.xebia.in/2012/04/23/great-india-developer-summit-5-0-developers-perspective/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 03:56:29 +0000</pubDate>
		<dc:creator>Nitin Khattar</dc:creator>
				<category><![CDATA[Concurrency Control]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[GIDS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Workshops]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13277</guid>
		<description><![CDATA[Great India Developer Summit was organized this year for the 5th time in a row and undoubtedly, it turned out to be a sheer success. I attended GIDS this year for the first time, so can’t compare much with its previous version, but I found it really very helpful in every aspect important for any [...]]]></description>
			<content:encoded><![CDATA[<p><b><a href="http://www.developermarch.com/developersummit/" target="_blank">Great India Developer Summit</a></b> was organized this year for the 5<sup>th</sup> time in a row and undoubtedly, it turned out to be a sheer success. I attended GIDS this year for the first time, so can’t compare much with its previous version, but I found it really very helpful in every aspect important for any software architect. It simply turned into a <i>vast knowledge pool</i> with each &amp; every drop making a significant contribution in spreading this knowledge around.</p>
<p>GIDS 2012, on the same lines as in previous years, consisted of 4 major streams: <b>GIDS .NET, GIDS WEB, GIDS JAVA, GIDS WORKSHOPS</b>. GIDS 2012 was flooded over with more than <b>140 technical sessions, keynotes and workshops</b> with more than <b>70 national &amp; international speakers</b>. ‘<a href="http://www.developermarch.com/developersummit/speakers.html#VenkatSubramaniam" target="_blank">Venkat Subramaniam</a>’ and ‘<a href="http://www.developermarch.com/developersummit/speakers.html#ScottDavis" target="_blank">Scott Davis</a>’ were two main heroes with maximum sessions by a single speaker and that too houseful. Being a Java &amp; Web developer, I attended all the streams except GIDS .NET and sessions around <em>HTML 5, JavaScript, Java 7 – Java 8, Functional Programming, and Concurrency</em>.<br />
<span id="more-13277"></span></p>
<p><span style="text-decoration: underline;">Day 2 :  <b>GIDS WEB</b></span></p>
<p>This day started with an immensely good session on ‘<i><span style="color: #0000ff;">HTML5 Local Storage and Application cache</span>’</i>, by Scott Davis. The content of the session was mostly common but the way it was presented, blended with live examples was totally exceptional. Following this came an eye-opener session by Venkat Subramaniam on ‘<span style="color: #0000ff;"><i>Rediscovering Javascript</i></span>’. Although <span style="text-decoration: underline;"><a href="http://en.wikipedia.org/wiki/JavaScript" target="_blank"><b>Javascript</b> </a></span>is a well known scripting language in the technical world for years, but still there were some exceptional features and important concepts that most of the people were not aware of. The session uncovered all the ‘Goods &amp; Bad of Javascript’ and helped clearing lots of false assumptions with the use of many intuitive examples.</p>
<p>Following the keynotes by various dignitaries in the technical world, were two interesting sessions on ‘<b><a href="http://documentcloud.github.com/backbone/" target="_blank">Backbone.js</a></b>’ by Scott Davis and ‘<b><a href="http://coffeescript.org/" target="_blank">CoffeeScript</a>’</b> by Venkat Subramaniam. The session on Coffeescript explained the concepts &amp; constructs of this new language which is based on Javascript. The session described how the aspects of functional &amp; effective programming can be applied to Javascript. The session also focused on how Coffeescript makes Javascript code much cleaner and solves various problems faced by programmers while writing javascript code. The session clearly explained the difference between ‘<b>Clean Code Vs Effective/Understandable Code’</b>. The session on Backbone.js also presented a good introduction on adding a well defined structure to the web applications.</p>
<p>GIDS Web consisted of another great session on Javascript, i.e. ‘<span style="color: #ff0000;"><i><span style="color: #0000ff;">Test driving Javascript</span></i></span>’ by Venkat Subramaniam. The session enthralled the audience with many live &amp; hands-on examples on writing test cases around javascript code. The session also focused on removing various barriers involved in the path of Unit Testing Javascript. Apart from these, there was another useful &amp; introductory session on ‘<span style="color: #0000ff;"><i>CSS3 for Programmers</i></span>’ by Scott Davis, uncovering the facts that how programmers can benefit from the capabilities of CSS3. I would just like to sum-up GIDS WEB as the day of <b>Javascript, HTML5 </b>and<b> Mobile Web</b>.</p>
<p><span style="text-decoration: underline;">Day 3 : <strong>GIDS JAVA</strong></span></p>
<p>This day started with much larger audience waiting to get a glimpse of <b>What’s New in Java?</b> Great India Developer Summit has always been an inspiration in this regard. GIDS has always been a reflection of the state of Technology in the Near Future. GIDS JAVA also started on the similar lines with some fantastic keynotes on <span style="color: #0000ff;"><i>Refactoring one’s Language Knowledge Portfolio</i></span>, <span style="color: #0000ff;"><i>Blackberry for Java Developers</i></span> and <span style="color: #0000ff;"><i>What’s new in the Internet Ecosystem for the Next generation</i></span>.</p>
<p>Following the keynotes, was the plethora of some of the best sessions on some of the hot topics ranging from <b>Java 7</b> to <b>Java EE 7</b> to <b>JMS 2.0</b> to <b>Java 8</b>,<b> JAX-RS 2.0</b> to <b>Java Concurrency </b>to <b>Scala</b> &amp; <b>Groovy</b>.   The session on Java 7 by Venkat Subramaniyam exhibited some of the major features included in the latest release of Java Development Kit (JDK). The content of this session was although ordinary but the presentation along with live examples was indeed extra-ordinary.</p>
<p>The session on ‘<span style="color: #0000ff;"><em>Java Messaging Service 2.0’</em></span> by <a href="http://www.developermarch.com/developersummit/speakers.html#ArunGupta" target="_blank">Arun Gupta</a> clearly focused on the problems and unfulfilled expectations in the current version of Java Messaging Service and also gave a glimpse of the major features (changes in JMS 1.0, new API, etc.), Oracle is offering with the release of JMS 2.0. Following this came an introductory session by <a href="http://www.developermarch.com/developersummit/speakers.html#ShaunSmith" target="_blank">Shaun Smith</a> on How <b>Extensibility &amp; Multi-Tenancy support</b> has been extended to <b>JPA</b> architecture. The session gave a wonderful glimpse of how easily Multi-Tenancy can be ensured in our application using JPA 2.1 in <strong><a href="http://www.eclipse.org/eclipselink/" target="_blank">EclipseLink</a></strong>.</p>
<p>After all these sessions, the era of predicting the Future of Java Platform began with Simon Ritter and Venkat Subramaniam pouring in their thoughts around the features of Java 8.  The session by Venkat on ‘<span style="color: #0000ff;"><em>Java 8: A Sneak Peak</em></span>’ exhibited some of the most expected features to be included in the next release of Java. The session gave a glimpse of the<a href="http://openjdk.java.net/projects/lambda/" target="_blank"> <b>Project Lambda</b></a>, <b><a href="http://openjdk.java.net/projects/jigsaw/" target="_blank">Project Jigsaw</a></b>, <b>JVM Convergence</b> and many such features in accordance to Java 8, duly supported with live running examples of the same.</p>
<p>Not just this much, there were few more interesting sessions on <span style="color: #0000ff;">‘</span><i><span style="color: #0000ff;">Concurrency without Pain in Pure Java</span>’ </i>&amp; ‘<i><span style="color: #0000ff;">Scala for the Intrigued</span>’</i> by Venkat Subramaniam and ‘<i><span style="color: #0000ff;">Runtime and Compile-time Metaprogramming in Groovy</span>’ </i>by Scott Davis, that raised GIDS JAVA to a much higher level. The session on Java concurrency helped uncovering some of the major pain-points in the area of Concurrent Programming using Java and also exhibited the best approach possible in solving the same. The session around Scala was indeed the most helpful session for the beginners in the Land of <a href="http://www.scala-lang.org/" target="_blank">Scala</a>. I don’t know much about others, but I felt most satisfied at the end of Day 3 with all the expectations due fulfilled in the best possible manner.</p>
<p><span style="text-decoration: underline;">Day 4 : <strong>GIDS WORKSHOPS</strong></span></p>
<p>This day was meant for <b>Hands-on Workshops</b> on multiple topics ranging from <b>Functional Programming</b> to <b>HTML 5</b> to <b>Java Concurrency</b> to <b>Spring</b>, <b>Jquery</b> and <b>Android</b>. The workshop on ‘<span style="color: #0000ff;"><i>Functional Programming on the JVM</i></span>’ by Venkat Subramaniam was indeed a wonderful 3 hrs hands-on session covering the aspects of <strong>Why, What &amp; How of Functional programming</strong>. The workshop was completely filled with running examples from many well known languages like <b><a href="http://www.scala-lang.org/" target="_blank">Scala</a>, <a href="http://groovy.codehaus.org/" target="_blank">Groovy</a>, <a href="http://www.ruby-lang.org/en/" target="_blank">Ruby</a>, <a href="http://clojure.org/" target="_blank">Clojure</a></b>. The workshop also stated the trade-off between a functional language &amp; a dynamic language, and how functional language can help in achieving effective concurrency.</p>
<p>Following this was a comprehensive workshop on ‘<span style="color: #0000ff;"><i>Concurrent Programming with the Java Platform</i></span>’ by <a href="http://www.developermarch.com/developersummit/speakers.html#SimonRitter" target="_blank">Simon Ritter</a>. The session provided detailed information around the basic concepts of Concurrency rising from the system level to the software level. The workshop completely uncovered the concurrent programming principles ensured in the earlier versions of Java to the latest versions. Although, the workshop lacked hands-on examples but was filled with code snippets of Java <strong>Concurrency</strong> techniques divided across <strong>Pre-Java5, Post-Java5 and Java 7 eras</strong>.</p>
<p>Apart from these, there were some other interesting workshops as well on ‘<span style="color: #0000ff;"><i>Pragmatics of Agility</i></span>’, ‘<span style="color: #0000ff;"><i>Exploratory Software Testing</i></span>’ and ‘<span style="color: #0000ff;"><i>Using jQuery-Ajax for Web Applications</i></span>’. The session on jQuery-Ajax was purely a hands-on workshop with live examples varied across the vast Jquery API.</p>
<p>Great India Developer Summit 2012 had something or the other for every software architect in any domain whether .Net, Java, Web, HTML, Mobile, Testing, etc. It was definitely a great learning experience to be a part of GIDS 2012 and a great source of inspiration to learn &amp; spread as much knowledge as you can.</p>
<p>The presentation files or videos of multiple sessions will be available for download/viewing by May, 4 2012 at summit’s website <a href="http://www.developersummit.com" target="_blank">http://www.developersummit.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/23/great-india-developer-summit-5-0-developers-perspective/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automation in Mobile Testing: Need and Challenges</title>
		<link>http://xebee.xebia.in/2012/04/19/automation-in-mobile-testing-need-and-challenges/</link>
		<comments>http://xebee.xebia.in/2012/04/19/automation-in-mobile-testing-need-and-challenges/#comments</comments>
		<pubDate>Thu, 19 Apr 2012 16:36:52 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Automation]]></category>
		<category><![CDATA[Mobile Testing]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[mobile automation]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12900</guid>
		<description><![CDATA[Automation testing helps testers to reduce burden of repetitive tasks in manual testing. Many software companies are launching applications in industry and to keep pace with this fast moving mobile industry they have test and release new mobile applications or same application with more functionality rapidly. To meet this challenge, software companies are moving towards [...]]]></description>
			<content:encoded><![CDATA[<p>Automation testing helps testers to reduce burden of repetitive tasks in manual testing. Many software companies are launching applications in industry and to keep pace with this fast moving mobile industry they have test and release new mobile applications or same application with more functionality rapidly. To meet this challenge, software companies are moving towards automation testing in mobile. We know that mobile testing is evolving and so is mobile automation testing. It is not completely matured like in case of website automation testing.</p>
<p>There are few tools available in market for mobile automation testing. It is true that mobile testing is still evolving and there is always increased pressure on companies to adopt to changing mobile operating system or in other words diversified nature of mobile phones. There are challenges in mobile automation testing which are mentioned below:-</p>
<p><span id="more-12900"></span></p>
<p>1) <strong>Functional Testing of multiple Mobile Screens:-</strong></p>
<p>There is no universal record/playback based automation tool available for different mobile screens, browser type, operating system, etc. For the applications that support various devices having resolution changes, like the iPhone and some Android, Blackberry and Windows Mobile models and etc. Testers need to make sure to include lots of testing where you rotate the device from portrait to landscape display, and vice versa, on all of the pages within your application. Automation can help in that case but there is lack of universal record/playback automation tool.</p>
<p>2)  <strong>Testing with Actual Devices:-</strong></p>
<p>We know that Mobile devices support Application different types of input methods like external touchscreen or external keypad or internal touchscreen or internal keypad and etc. Therefore there is a need automation tool which can test not only on emulators but also on  mobiles and should react according to "inputs given from mobile".</p>
<p>3) <strong>Testing of Interrupts:-</strong></p>
<p>Everybody knows real networks introduce interrupts and ability of automation tools to keep check on network/software/network interrupts can help automation testers a lot. Lets see few of the test scenarios below for any application where we want to see how it will react before, during, and after the call:</p>
<p>1. Your application is interrupted by an incoming call, originator/terminator hangs up the call</p>
<p>2. Your application is interrupted by placing an outgoing call, originator/terminator hangs up the call</p>
<p>5) <strong>Network Message Logging:-</strong></p>
<p>In spite of  interrupts, Mobiles working on real network are prone to signal loss, hand offs, weak signals also. For those reasons, "Automation tool needs to do recording and logging of network messages transmitted and received during mobile app usage".</p>
<p>For the applications that are going to be used on devices in various locations with various network connection speeds, it is important to plan testing coverage for the following scenarios:</p>
<p>1. With no SIM card in the device</p>
<p>2. In Airplane mode (or all connections disabled)</p>
<p>3. intermittent network scenarios that a user might encounter in the real world like Walking out of Wi-Fi range so the connection automatically switches to 3G/2G (for example, in a large building like a Corporate Offices)</p>
<p>5) <strong>Single tool for all Platforms:-</strong></p>
<p>There are several mobile operating systems in market and each day more advanced are coming in market. We do not have any single tool which can work for all platforms (Microsoft, Symbian, iPhone,android,etc.). There is need of automation tool which can work with all the platforms rather than a different tool for each platform.</p>
<p>6) <strong>Proper End to End Testing:-</strong></p>
<p>There is also need of automation tools/frameworks which can perform proper End to End Testing where testers are able to perform connectivity from the device to the automated testing equipment (typically a PC).</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/19/automation-in-mobile-testing-need-and-challenges/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JQuery Cycle Plugin: Sync multiple slideshows on same page</title>
		<link>http://xebee.xebia.in/2012/04/17/jquery-cycle-plugin-sync-multiple-slideshows-on-same-page/</link>
		<comments>http://xebee.xebia.in/2012/04/17/jquery-cycle-plugin-sync-multiple-slideshows-on-same-page/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 12:59:40 +0000</pubDate>
		<dc:creator>Anubhav</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13224</guid>
		<description><![CDATA[I was working on a website where I wanted to create a slideshow on the homepage, where I have to show a set of questions and answers coming from left-to-right and right-to-left of the screen, respectively. To add to the mystry, the question comes first and then the answer comes after a wait of 4 [...]]]></description>
			<content:encoded><![CDATA[<p>I was working on a website where I wanted to create a slideshow on the homepage, where I have to show<br />
a set of questions and answers coming from left-to-right and right-to-left of the screen, respectively. To add to the<br />
mystry, the question comes first and then the answer comes after a wait of 4 seconds. But both question<br />
and answer should move out of the screen simultaneously, and then the next question comes...and this<br />
continues till the cycle reaches the last slide.</p>
<p>So, here it goes...<br />
<span id="more-13224"></span></p>
<p>First thing first, get the JQuery Cycle Plugin from <a href="http://jquery.malsup.com/cycle/">here</a> and include it in your source.</p>
<p>I created this website in Drupal so I will use some specific code of Drupal in some places.</p>
<p><strong>Gibberish in Drupal starts</strong></p>
<p>To add cycle plugin in your node/page template just insert the following code at the top:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
    drupal_add_js(drupal_get_path('theme', 'my_theme').'/js/jquery.cycle.all.js')
?&gt;
</pre>
<p>The above line will add the cycle javascript file my first going into the themes folder and then in your theme directory,<br />
in my case it was 'my_theme'. Please note it is 'theme' and not 'themes' many people get confused and take this as<br />
the actual directory name but this is just Drupal syntax to get to the themes directory.</p>
<p><strong>Gibberish in Drupal ends</strong></p>
<p>I am not going to be modular here and would just do everthing in a single file. For all innovative minds please feel<br />
free to put code where ever you feel happy.</p>
<p>Here is the HTML page:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
	&lt;head&gt;
		&lt;!-- let's leave this empty for now --&gt;
		&lt;script&gt;&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div id='homepage'&gt;
			&lt;div id='questions'&gt;
				&lt;div id='ques-1'&gt;Is Scrum really going to work in one month project?&lt;/div&gt;
				&lt;div id='ques-2'&gt;Do you know what TDD is?&lt;/div&gt;
				&lt;div id='ques-3'&gt;When was the last time you used CI?&lt;/div&gt;
				&lt;div id='ques-4'&gt;Are you Agile?&lt;/div&gt;
				&lt;div id='ques-5'&gt;2 developers takes 4 months, therefor 4 developers will take 2 months. What do you say?&lt;/div&gt;
			&lt;/div&gt;
			&lt;div id='answers'&gt;
				&lt;div id='ans-1'&gt;Yes, I am 200% sure that it might work.&lt;/div&gt;
				&lt;div id='ans-2'&gt;Yes, I do. It means The Developer's Death.&lt;/div&gt;
				&lt;div id='ans-3'&gt;OMG! What do I need a Crime Investigator for?!&lt;/div&gt;
				&lt;div id='ans-4'&gt;Yes, I proudly say that I am A-jahil (ignorant).&lt;/div&gt;
				&lt;div id='ans-5'&gt;Thank God!! This is not happening in the real life, otherwise 9 people would be making a baby in a month.&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I defined two separate DIVs to show questions and answers because cycle plugin works on a container element and then container's each child element will become a slide.</p>
<p>Add the following code in the &lt;script&gt; tag:</p>
<pre class="brush: jscript; title: ; notranslate">
jQuery(window).bind(&quot;load&quot;, function() {

        jQuery('#questions').cycle({
            fx          : 'scrollRight',    // scroll left-to-right
            speed       : 'slow',
            timeoutFn   : calculateTimeout, // described below
            nowrap      : true,             // stop slideshow after the last slide
        })
        jQuery('#answers').cycle({
            fx          : 'scrollLeft',            // scroll right-to-left
            speed       : 'slow',
            timeoutFn   : calculateTimeoutAnswers, // described below
            nowrap      : true
        })
});
</pre>
<p>and here are the timeout functions:</p>
<pre class="brush: jscript; title: ; notranslate">
var timeouts =   [9, 9, 9, 9, 9];
function calculateTimeout(currElement, nextElement, opts, isForward) {
    var index = opts.currSlide;
    return timeouts[index] * 1000;
} 

var timeoutsAnswers = // explained below ;
function calculateTimeoutAnswers(currElement, nextElement, opts, isForward) {
    var index = opts.currSlide;
    return timeoutsAnswers[index] * 1000;
}
</pre>
<p>I created these to set a delay for each slide and left enough delay, or 4 sec, to display the questions' corresponding answer.</p>
<p>But the tricky part is that we should slide out both question and answer at the same time. I tried to set different intervals<br />
for each answer slide but all in vain, spent a few hous googling and on calcuator/paper trying to figure out a formula to<br />
do the trick. But then it hit-me!! </p>
<p>Why not add some dummy child elements to 'answers' container or what I called them 'delay' elements!!</p>
<p>Hence the HTML for anwers container became:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id='answers'&gt;
    &lt;div class='delay'&gt;&lt;/div&gt;
    &lt;div id='ans-1'&gt;Yes, I am 200% sure that it might work.&lt;/div&gt;
    &lt;div class='delay'&gt;&lt;/div&gt;
    &lt;div id='ans-2'&gt;Yes, I do. It means The Developer's Death.&lt;/div&gt;
    &lt;div class='delay'&gt;&lt;/div&gt;
    &lt;div id='ans-3'&gt;OMG! What do I need a Crime Investigator for?!&lt;/div&gt;
    &lt;div class='delay'&gt;&lt;/div&gt;
    &lt;div id='ans-4'&gt;Yes, I proudly say that I am A-jahil (ignorant).&lt;/div&gt;
    &lt;div class='delay'&gt;&lt;/div&gt;
   &lt;div id='ans-5'&gt;Thank God!! This is not happening in the real life, otherwise 9 people would be making a baby in a month.&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>and the timeoutAnswers array became:</p>
<pre class="brush: jscript; title: ; notranslate">
// do some hit-n-trail because the slide out time for both questions and answers
// will not be exactly same even though we set it to 4+5=9 sec
// you may need to change 5 to something like 4.6 or less.
var timeoutsAnswers = [4, 5, 4, 5, 4, 5, 4, 5, 4, 5]
</pre>
<p>Here is the full HTML:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
	&lt;head&gt;
		&lt;!-- add jquery and cycle plugins --&gt;
		&lt;script type='text/javascript'&gt;
			jQuery(window).bind(&quot;load&quot;, function() {

					jQuery('#questions').cycle({
						fx          : 'scrollRight',    // scroll left-to-right
						speed       : 'slow',
						timeoutFn   : calculateTimeout, // described below
						nowrap      : true,             // stop slideshow after the last slide
					})
					jQuery('#answers').cycle({
						fx          : 'scrollLeft',            // scroll right-to-left
						speed       : 'slow',
						timeoutFn   : calculateTimeoutAnswers, // described below
						nowrap      : true
					})
			});

			var timeouts =   [9, 9, 9, 9, 9];
			function calculateTimeout(currElement, nextElement, opts, isForward) {
				var index = opts.currSlide;
				return timeouts[index] * 1000;
			} 

			var timeoutsAnswers = [4, 5, 4, 5, 4, 5, 4, 5, 4, 5];
			function calculateTimeoutAnswers(currElement, nextElement, opts, isForward) {
				var index = opts.currSlide;
				return timeoutsAnswers[index] * 1000;
			} 

		&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div id='homepage'&gt;
			&lt;div id='questions'&gt;
				&lt;div id='ques-1'&gt;Is Scrum really going to work in one month project?&lt;/div&gt;
				&lt;div id='ques-2'&gt;Do you know what TDD is?&lt;/div&gt;
				&lt;div id='ques-3'&gt;When was the last time you used CI?&lt;/div&gt;
				&lt;div id='ques-4'&gt;Are you Agile?&lt;/div&gt;
				&lt;div id='ques-5'&gt;2 developers takes 4 months, therefor 4 developers will take 2 months. What do you say?&lt;/div&gt;
			&lt;/div&gt;
			&lt;div id='answers'&gt;
				&lt;div class='delay'&gt;&lt;/div&gt;
				&lt;div id='ans-1'&gt;Yes, I am 200% sure that it might work.&lt;/div&gt;
				&lt;div class='delay'&gt;&lt;/div&gt;
				&lt;div id='ans-2'&gt;Yes, I do. It means The Developer's Death.&lt;/div&gt;
				&lt;div class='delay'&gt;&lt;/div&gt;
				&lt;div id='ans-3'&gt;OMG! What do I need a Crime Investigator for?!&lt;/div&gt;
				&lt;div class='delay'&gt;&lt;/div&gt;
				&lt;div id='ans-4'&gt;Yes, I proudly say that I am A-jahil (ignorant).&lt;/div&gt;
				&lt;div class='delay'&gt;&lt;/div&gt;
				&lt;div id='ans-5'&gt;Thank God!! This is not happening in the real life, otherwise 9 people would be making a baby in a month.&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>Disclaimer</strong>: I have not tested the above code so if it doesn't work please try to tweak it yourself or drop me a comment. But I am sure you got the gist!</p>
<p>Also, I understand that this might not be an elegant way to handle such dilemma but I would really love to see an optimal/alternate solution.</p>
<p>That's it folks!!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/17/jquery-cycle-plugin-sync-multiple-slideshows-on-same-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inheritance in Static Language vs Dynamic Language</title>
		<link>http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/</link>
		<comments>http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 14:27:11 +0000</pubDate>
		<dc:creator>Gagan Agrawal</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[dynamic langauge]]></category>
		<category><![CDATA[inheritance]]></category>
		<category><![CDATA[static language]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13086</guid>
		<description><![CDATA[Inheritance is generally meant to be used when a group of classes belong to same family and share common properties and methods apart from having their own specialized ones. However at times it is seen that classes are extended just to avoid writing boiler plate code, even though they might not necessarily belong  to same [...]]]></description>
			<content:encoded><![CDATA[<p>Inheritance is generally meant to be used when a group of classes belong to same family and share common properties and methods apart from having their own specialized ones. However at times it is seen that classes are extended just to avoid writing boiler plate code, even though they might not necessarily belong  to same family. This might be fine at times in static languages like Java as there are less options available. However dynamic languages like Groovy offer better alternatives than forcing inheritance for such scenarios.<span id="more-13086"></span></p>
<p>Let’s elaborate more on this with an example of an e-commerce application.</p>
<p>Suppose in an e-commerce application, we consider following entities.</p>
<ul>
<li>User – Contains user details like username, address, email etc.</li>
<li>CreditCard – For billing via credit card</li>
<li>BankAccount – For billing via bank account</li>
</ul>
<p>Now here, CreditCard and BankAccount represents Billing Details and will have some properties in common. E.g account number, owner etc. Also since both represent billing details of a user, they can be considered to belong to same family i.e. Billing Details. Over here, inheriting CreditCard and BankAccount entities from BillingDetails makes perfect sense as shown below.</p>
<p style="text-align: center;"><a rel="attachment wp-att-13091" href="http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/1-5/"><img src="http://xebee.xebia.in/wp-content/uploads/2012/04/1.png" title="Billing Details Class Diagram" class="size-full wp-image-13091 alignleft" /></a></p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p>Now since instances of CreditCard and BankAccount will be saved in database, both of them will have a database identifier i.e. “id” field. Also there would also be certain operations in common like save(), delete() etc. So we can put all such properties and methods in BillingDetails so that they will be inherited by CreditCard and BankAccount. But wait a minute. What about User entity? Wouldn’t User have “id” attribute and “save”, “delete” methods too? If we just put them in BillingDetails, we will have to duplicate it in User entity as well. So what should be done?</p>
<p>A typical solution one might think of doing is, create a common class “BaseEnity” and extend all other entities in the system from it as shown below.</p>
<p><img height="348" width="423" src="http://xebee.xebia.in/wp-content/uploads/2012/04/21.png" title="Billing Details Class Diagram" class="size-full wp-image-13118 alignleft" /></p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;">&nbsp;</p>
<p>So now we have all the attributes and methods common to entire application in BaseEntity and every other entity will extend from BaseEntity. However in this design we have User and BillingDetails entities extending same class BaseEntity even though they don’t belong to same family. One might argue that User and BillingDetails both are entity(domain) classes and share common structure for database operations and hence can be considered belonging to same family. However this is more of technical similarity that they share.  From an e-commerce domain perspective they do not belong to same family and hence should not extend same class.</p>
<p>Apart from this, it is also possible that certain common properties are required in  completely different category of classes. E.g “log” property is generally required in all types of classes. From a simple web application perspective there could be 3 different layers of classes.</p>
<ul>
<li>Controllers</li>
<li>Services</li>
<li>Domains(Entities)</li>
</ul>
<p>Now in order to make log property available in all types of classes, I am sure nobody would like to extend all these classes from a base class.</p>
<p>So what we want is a solution which can make our design cleaner and also avoid duplicating code. From the above mentioned example perspective, User and BillingDetails entities should have “id” attribute and save(), delete() methods available to them automatically, but without extending same class. Let’s see how this can be achieved via Dynamic Language.</p>
<p>Dynamic Languages provide a great way to extend a class definition by adding new fields or methods at compile time or run time. This feature can be a wonderful way of adding common properties and methods in classes instead of extending them from a base class. And let the inheritance be applied only when it makes sense.</p>
<p>Let us elaborate more on this with dynamic language “Groovy” and its web framework “Grails”.</p>
<p>Groovy allows to extend class definition at runtime via ExpandoMetaClass and at compile time via AST Transformations(Global or Local). On top of it, Grails is a web framework for Groovy which works on "Convention over Configuration" concept. There are mainly 3 layers in Grails i.e. controller, services and domains. As per this concept, Grails auto injects lots of utility fields and methods in various artefacts at compile time and run time. So common properties like “log” are available in classes across layers and layer specific properties are available in respective layer classes.  For instance all domain classes have various database operation methods e.g save(), delete() etc. and some required fields like id and version. All controller classes have access to bindData() method for binding request parameters to objects and so on.</p>
<p>Hence with Groovy it is possible to auto inject common properties and methods across a set of classes and use inheritance only when it makes sense. One should keep in mind this important feature of dynamic language and should make most out of it.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maximize Browser Window in Selenium Web Driver</title>
		<link>http://xebee.xebia.in/2012/04/06/maximize-browser-window-in-selenium-web-driver/</link>
		<comments>http://xebee.xebia.in/2012/04/06/maximize-browser-window-in-selenium-web-driver/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 12:00:41 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Test Auotmation]]></category>
		<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[maximize browser window]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[selenium web driver]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13037</guid>
		<description><![CDATA[Nowadays, automation testers are shifting from selenium1 to selenium web driver because of its many advantages. I am new to automation and had used selenium1 earlier. I have recently started using selenium web driver and while automating my first test, I wanted to maximize my browser window but then I found out that web driver [...]]]></description>
			<content:encoded><![CDATA[<p>Nowadays, automation testers are shifting from selenium1 to selenium web driver because of its many advantages. I am new to automation and had used selenium1 earlier. I have recently started using selenium web driver and while automating my first test, I wanted to maximize my browser window but then I found out that web driver has no direct command of maximizing window like we have in selenium1.  Although we can use selenium commands in webdriver by using webbacked driver function. I used selenium.maximize() function but it was not working on my machine. I knew that it is not the only way of maximizing browser window. There could be other ways also. I have mentioned four different ways of maximizing browser window in selenium web driver in this blog . If in any case, one of them is not working for you then have other options which can be tried out.</p>
<p><span id="more-13037"></span></p>
<p>1. The very first method which is given in their documentation is using windowMaximize() command of selenium instance.</p>
<pre class="brush: jscript; title: ; notranslate">

selenium = new WebDriverBackedSelenium(driver,url);
selenium.windowMaximize();
</pre>
<p>2. We can use robot class to invoke keyboard action to maximize browser window. Robot class  is used to generate native system input events for the purposes of test automation, self-running demos  and other applications where control of the mouse and keyboard is needed. Robot can be used to facilitate automated testing of Java platform implementations. I used Robot class in my test case to simulate keyboard keys combination ALT+ SPACE and then used down arrows keys to select maximize option in menu.</p>
<pre class="brush: jscript; title: ; notranslate">

Robot robot = new Robot();

// Press ALT and SPACE Keys

robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_SPACE);
Thread.sleep(1000);
//Press down arrow keys to move to select Maximize option in menu

robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
Thread.sleep(100);

robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
Thread.sleep(100);

robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
Thread.sleep(100);

robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
Thread.sleep(100);
//Press enter to invoke the Maximize menu option

robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
}
</pre>
<p>3. Sikuli is a robust and powerful tool to automate and tests user interfaces screenshots. Sikuli commands can be easily integrated with java code. We just need to download sikul-script jar and configure in build path. After configuring in build path, create and initialize an instance of Screen object.</p>
<pre class="brush: jscript; title: ; notranslate">

Screen screen = new Screen();
</pre>
<p>Capture image which you want to get clicked during execution of your test case. For Example:- Take a snapshot of maximize button on browser and save it anywhere on your disk or in any folder of your project and then give its path in click command just like below:-</p>
<pre class="brush: jscript; title: ; notranslate">
screen.click(&quot;Image Path&quot;);
</pre>
<p>4. Fourth way is to use Toolkit utility which query the native operating system directly and is platform independent. In addition to this, the code below will maximize the browser window according to your system's current resolution.</p>
<pre class="brush: jscript; title: ; notranslate">

driver.manage().window().setPosition(new Point(0,0));
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
Dimension dim = new Dimension((int) screenSize.getWidth(), (int) screenSize.getHeight());
driver.manage().window().setSize(dim);
</pre>
<p>I don't say these above are the only ways to maximize browser window . I am sure there are other ways also. I have mentioned all of them in one blog so that it would be helpful for readers to try and know different ways. It would be really helpful to me as well as to other readers if anybody of you can also suggest tried and tested other ways of doing it and  paste your codes in comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/04/06/maximize-browser-window-in-selenium-web-driver/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>iOS : Writing modular application in Cocoa framework</title>
		<link>http://xebee.xebia.in/2012/03/31/ios-writing-modular-application-in-cocoa-framework/</link>
		<comments>http://xebee.xebia.in/2012/03/31/ios-writing-modular-application-in-cocoa-framework/#comments</comments>
		<pubDate>Sat, 31 Mar 2012 12:15:04 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=13016</guid>
		<description><![CDATA[Apple provides a a very good architecture to write good application. It in a way restricts to you to use the best practices to write cleaner code. While using the Cocoa framework for developing the mobile application you have to strictly follow a MVC pattern to design the views of your application. Following image describes [...]]]></description>
			<content:encoded><![CDATA[<p>Apple provides a a very good architecture to write good application. It in a way restricts to you to use the best practices to write cleaner code. While using the Cocoa framework for developing the mobile application you have to strictly follow a MVC pattern to design the views of your application. Following image describes the roles as well as the way communication between them happens.<br />
<span id="more-13016"></span><br />
<a href="http://xebee.xebia.in/wp-content/uploads/2012/03/Screen-Shot-2012-03-31-at-3.58.26-PM.png"><img src="http://xebee.xebia.in/wp-content/uploads/2012/03/Screen-Shot-2012-03-31-at-3.58.26-PM-300x95.png" alt="" title="Screen Shot 2012-03-31 at 3.58.26 PM" width="300" height="95" class="alignnone size-medium wp-image-13031" /></a><br />
</br></p>
<p>Lets take a example to understand how it works. Lets have a view which shows a list of items in a table.To achieve this I m going to go on the story board  and drag a simple table view on the default view that i already have on storyboard. I  have a simple singleton model which has the list of data in my model object accessible by a list parameter.To make sure the controller for the view handles the events we need to add the following delegates  and implement the following methods.</p>
<pre class="brush: plain; title: ; notranslate">

Controller Interface

@interface ViewController : UIViewController&amp;lt;UITableViewDataSource, UITableViewDelegate&amp;gt;

--------------

Controller Implementation

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     return [model.list count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @&amp;quot;Cell&amp;quot;;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

     cell.textLabel.text = [model.list objectAtIndex:indexPath.row];

return cell;
}
</pre>
<p>This all perfectly works well when you have a single table in one view. While you start working on iPad we have bigger screen resolution. We start having complex view. Lets take a simple example.I have a view which has two tables and one date picker a popup window. Following are the changes that will happen in the above code.</p>
<pre class="brush: plain; title: ; notranslate">
Controller Interface

@interface CheckpointController : UIViewController&amp;lt;CheckpointProtocol, UITableViewDataSource, UITableViewDelegate,UIPopOverControllerDelegate,PopOverDatePickerDelegate&amp;gt;
----------------
Controller Implementation

The controller will have method implementations of

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 - (void)dateSelected:(id)aValue
 - (void)popoverControllerShouldDismissPopOver:
 -(void)popoverControllerDidDismissPopover:
</pre>
<p>This makes your class huge and unmanageable. This is not it, since we have a two tables in same view the code complexity increases as we have to check every time which table view is calling the delegate. e.g. of numberOfRowsInSection will be</p>
<pre class="brush: plain; title: ; notranslate">

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if(tableView == self.firstTableView){
        return [firstModel.list count];
    }else{
        return [secondModel.list count];
    }
}
</pre>
<p>In this similar fashion we need to update the rest of table function.This makes a code a lot messy. And with time a big overhead to manage. Further if you have add more components to the view you will have to keep implementing more delegates.</p>
<p>The good solution to this problem will be to create small individual controller doing only what they are expected to and create one MainViewController which on initialization will create the controllers and extract the views from the individual controllers and add it as its subviews in the Main View. The responsibility of the main view will only be to create the controllers and handle the communication between the two individual controller if required. So lets have a look at how your MainViewController class will look like.</p>
<pre class="brush: plain; title: ; notranslate">
MainViewController Implementation

-(void)addFirstTable{
    firstTableController = [mainStoryBoard instantiateViewControllerWithIdentifier:@&quot;FirstTable&quot;];
    UIView* view = [(UIViewController *)firstTableController view];
    view.frame = CGRectMake(0, 94, 300, 554);
    [self.view addSubview:[(UIViewController *)firstTableController view]];
}

-(void)addSecondTable{
    secondTableController = [mainStoryBoard instantiateViewControllerWithIdentifier:@&quot;SecondTable&quot;];
    UIView* view = [(UIViewController *)secondTableController view];
    view.frame = CGRectMake(0, 300, 200, 554);
    [self.view addSubview:[(UIViewController *)secondTableController view]];
}

-(void)addDatePickerView{
    secondTableController = [mainStoryBoard instantiateViewControllerWithIdentifier:@&quot;DatePicker&quot;];
    UIView* view = [(UIViewController *)secondTableController view];
    view.frame = CGRectMake(0, 500, 100, 554);
    [self.view addSubview:[(UIViewController *)secondTableController view]];
}

-(void)createAndAddSubview{
    [self addFirstTable];
    [self addSecondTable];
    [self addDatePickerView]
}
</pre>
<p>We have to call the function createAndAddSubview in view load or override the init method. So the above approach still sticks to MVC as suggested by design standards and also injects a lot of modularity into the code. Further divides the code to more classes to makes it easier to maintain.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/31/ios-writing-modular-application-in-cocoa-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web GUI Automation: Tools, Strategies &amp; Patterns</title>
		<link>http://xebee.xebia.in/2012/03/30/web-gui-automation-tools-strategies-patterns/</link>
		<comments>http://xebee.xebia.in/2012/03/30/web-gui-automation-tools-strategies-patterns/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 17:18:15 +0000</pubDate>
		<dc:creator>Gaurav Bansal</dc:creator>
				<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Quality]]></category>
		<category><![CDATA[Quality Assurance]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test Auotmation]]></category>
		<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[Automation Framework]]></category>
		<category><![CDATA[Page Factory]]></category>
		<category><![CDATA[Page Object]]></category>
		<category><![CDATA[TestNG]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12990</guid>
		<description><![CDATA[What are the key features an automation framework should have for being successful at an implementation and execution level? Should that be robust, easy-to-use, business-driven, tester friendly? What are the conceptual guidelines that we should follow while designing automation framework? These are the questions that we understand when we have created/seen/used an automation framework that does [...]]]></description>
			<content:encoded><![CDATA[<p>What are the key features an automation framework should have for being successful at an implementation and execution level? Should that be robust, easy-to-use, business-driven, tester friendly? What are the conceptual guidelines that we should follow while designing automation framework? These are the questions that we understand when we have created/seen/used an automation framework that does not have any/most of above-mentioned features.<span id="more-12990"></span> Also some of the root-level requirements of an automation framework that we hear from our clients are:</p>
<ul>
<li>It should be easy to update test scripts when there is any UI change on web pages.</li>
<li>It should be easy to read and understand test script code. Even a quick glance on snippet of code should tell about web page being referred and its underlying functionality.</li>
<li>Test script execution should be fast.</li>
<li>Failed test methods should enter enough information into logs so that it becomes easy and quick to pin-point the issue and report to different stakeholders.</li>
<li>It should have ability to re-run failed test methods.</li>
<li>It should be able to pick test data from external data sources (txt, xls, csv, sql, xml etc)</li>
</ul>
<p>So in this post I am going to talk about tools that we should select while targeting Web UI Automation and then how should we leverage benefits of well known patterns to make maintainable,  extensible and usable automation framework .</p>
<p><em><span style="font-size: medium;"><strong><br />
</strong></span></em></p>
<p><span style="text-decoration: underline;"><em><span style="font-size: medium;"><strong>Selection of Tools</strong></span></em></span><br />
Following are the details of recommended tools for Web UI Automation:</p>
<p><strong>Selenium WebDriver</strong><br />
<a href="http://seleniumhq.org/" target="_blank"> Selenium</a> is an open source testing framework that allows you to emulate the actions of a user when navigating and interacting with a web site through standard browsers (such as IE, Firefox or Chrome). When your scripts are running your chosen browser pops up and can be watched as your steps are replayed back at you. Selenium 2.0 has many new exciting features and improvements over Selenium 1. The primary new feature is the integration of the <a href="http://code.google.com/p/selenium/" target="_blank">WebDriver</a> API. This addresses a number of limitations along with providing an alternative, and simpler, programming interface.</p>
<p>WebDriver supports not only real browsers (IE, Chrome &amp; Firefox) but also headless ones (using HTMLUnit).</p>
<p><strong>Java</strong><br />
Selenium WebDriver’s <a href="http://code.google.com/p/selenium/downloads/list" target="_blank">Java binding</a> is the most preferred platform where one gets access to vast array of open source libraries that exist for Java and moreover Java code is maintainable because it has relatively simple syntax and encourages a fairly standardized way of doing things.</p>
<p><strong>TestNG</strong><br />
<a href="http://testng.org/doc/index.html" target="_blank"> TestNG</a> is a testing framework inspired from JUnit and NUnit but it has some new functionalities that make it more powerful and easier to use like:</p>
<ul>
<li>Using TestNG's dependsOnMethods attribute, one can easily specify dependent methods. So in case we want the test method 'b' should only execute when test method 'a' has passed, we will be able to do this using dependsOnMethods attribute.</li>
<li>Ability to rerun failed tests is especially handy in large test suites, and it's a feature you'll only find in TestNG. Anytime there is a failure in TestNG, it creates an XML configuration file that delineates the failed tests.</li>
<li>One can group our test cases under different test groups like sanity, regression, critical-path or module-wise like payment, third-party-integration, user-management, admin-console etc. and can execute specific test group later on.</li>
</ul>
<p><strong>Maven</strong><br />
The easiest way to set up a Selenium WebDriver Java project is to use Maven. Maven will download the java bindings (the Selenium 2.0 java client library, TestNG and other required jars) and all its dependencies, and will create the project for us, using a maven pom.xml (project configuration) file. Once we are done with this, we can import the maven project into our preferred IDE, IntelliJ IDEA or Eclipse.</p>
<p><strong>CI Integration</strong><br />
Selenium WebDriver project is a great fit for the continuous integration tools like Jenkins, Hudson, CruiseControl as it can be installed on server testing box and drive/execute test cases remotely on different machines to target browser compatibility with different browsers on different platforms.</p>
<p><span style="text-decoration: underline;"><em><span style="font-size: medium;"><strong><br />
</strong></span></em></span></p>
<p><span style="text-decoration: underline;"><em><span style="font-size: medium;"><strong>Strategies &amp; Patterns</strong></span></em></span></p>
<p>There are lot of issues that people face while doing Web Automation with respect to their maintainability, scalability and difficulty in debugging the failed scenarios. However these are generic issues with every automated testing tool and most likely due to improper design of testing framework. I am listing down few strategies and patterns that can help us in building a good framework:</p>
<p><b>GUI Repository &amp; Page Factory Pattern</b><br />
A UI map is a mechanism that stores Identifiers/locators for an application’s UI elements. The test script then uses the UI Map for locating the elements to be tested. Basically, a UI map is a repository of test script objects that correspond to UI elements of the application being tested. UI map has two significant advantages:</p>
<ul>
<li> Using a centralized location for UI objects instead of having them scattered throughout the script. This makes script maintenance more efficient.</li>
<li> Cryptic HTML Identifiers and names can be given more human-readable names improving the readability of test scripts.</li>
</ul>
<p>In order to support the PageObject pattern, WebDriver's support library contains a factory class (org.openqa.selenium.support.<a href="http://code.google.com/p/selenium/wiki/PageFactory" target="_blank">PageFactory</a>) where we use the annotation @FindBy for making the WebElement object to know to which element it belongs to on web page. By using this pattern we need not to write the code for finding each and every Web Element.</p>
<p><b>Page-Object Pattern</b><br />
<a href="http://code.google.com/p/selenium/wiki/PageObjects" target="_blank"> Page Object Pattern</a> is a pattern that displays web page's UI as a class. In addition to UI, functionality of the page is also described in this class. This provides a bridge between page and test.</p>
<p>The idea is to create a level of abstraction to separate the tests from the test subjects, and to provide a simple interface to the elements on the page. Here are the main advantages of Page Object Pattern using:</p>
<ul>
<li>Simple and clear tests.</li>
<li>Good support of tests, because everything is stored in one place.</li>
<li>Easy creation of new tests. In fact, tests can be created by a person not knowing the features of automation tools.</li>
</ul>
<p>PageObjects are used as an abstraction to a concrete web page and may be constructed using a <em>PageFactory</em> .</p>
<p><b>Utilities</b><br />
There should be a utility package that will have classes providing common functionalities that are needed by scripts. For example method to read configuration/properties file, method to send test automation results via email, method to take screenshot on every failure etc.</p>
<p><b>Error Handling Module</b></p>
<p>This module should be designed in such a way so that it provides exact information about state of app when there is an assertion failure. The objective is to minimize the debug time by making available all the resources/info we need so that we can be sure about the bug, steps to reproduce the bug etc. This can be leveraged using:</p>
<ul>
<li>Ability to take screen shot on every assertion failure.</li>
<li>Ability to take screen shot on every exception and log stack trace for easy debugging.</li>
<li>Ability to log current user name, password and current URL of browser whenever any assertion failure or exception occurs that helps us in debugging.</li>
</ul>
<p><b>Reporting &amp;  Logging</b></p>
<p><a href="http://reportng.uncommons.org/" target="_blank">ReportNG</a> can be used for Reporting and Logging that will give us clear concise HTML report having statistical information about which all test suites, test groups, test scripts and test methods got executed and how many got passed, failed and skipped.</p>
<p>As logging is an important component of the automated test scripts and a well written logging code offers quick debugging, easy maintenance, and structured storage of an application's runtime information so on the logging front we can use log4j.</p>
<p>There should be  an exhaustive end-2-end HTML report having detailed logs for each and every WebDriver action. This HTML file should have direct links to failed screenshots. Logs might also be available in txt format to reduce the size of the log file. All of these types of logs can be generated via Log4J.</p>
<p><strong>Leveraging TestNG fixtures</strong></p>
<p>Using <a href="http://testng.org/doc/documentation-main.html#annotations" target="_blank">testng annotations</a> we can use setup and teardown methods at various levels which will allow us to meet pre and post test conditions at various levels.</p>
<ul style="list-style-type: disc;">
<li>@BeforeSuite: The annotated method will be run before all tests in this suite have run.</li>
<li>@AfterSuite: The annotated method will be run after all tests in this suite have run.</li>
<li>@BeforeTest: The annotated method will be run before any test method belonging to the classes inside the &lt;test&gt; tag is run.</li>
<li>@AfterTest: The annotated method will be run after all the test methods belonging to the classes inside the &lt;test&gt; tag have run.</li>
<li>@BeforeClass: The annotated method will be run before the first test method in the current class is invoked.</li>
<li>@AfterClass: The annotated method will be run after all the test methods in the current class have been run.</li>
<li>@BeforeMethod: The annotated method will be run before each test method.</li>
<li>@AfterMethod: The annotated method will be run after each test method.</li>
</ul>
<p><b><br />
Test Data<br />
</b>While writing the test scripts we should not be using hard coded data in test scripts. Both input and expected data should be picked/read from either txt, xls or XML files.<b><br />
</b><br />
<b>Verification Checkpoints</b></p>
<ul>
<li>We should assert text, value, list of values, presence of element(s) etc. In fact everything displayed on web page can be asserted against expected result so required methods can be created under utilities for same.</li>
<li>For ajax request/responses, we should keep polling using a loop until a given time period and look for required expected result. So we should take care of that special ajax functionality.</li>
<li>We should also verify actual results with Database validations checkpoints wherever required.</li>
</ul>
<p><b> </b></p>
<p><b>Best Locator Strategy</b><br />
Out of available locator strategies (ID, name, link, xpath, css, dom, JSEvents) selection should be based on best suited locator that works for all browsers and is fast also.</p>
<p>There are couple of CSS locators that do not work for Internet Explorer however in general CSS locators are much faster than XPATH locators so we should be using best suited locators. Understand/parse the surrounding HTML for a particular element and create the  locator rather than using locators given by record and playback tools as those locators are not optimized.</p>
<p>Keeping these strategies and design patterns in mind and using these to make informed choices should go a long way  in helping build and sustain a successful automation program across any project.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/30/web-gui-automation-tools-strategies-patterns/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How did Liferay help me in building my app?</title>
		<link>http://xebee.xebia.in/2012/03/30/how-did-liferay-help-me-in-building-my-app/</link>
		<comments>http://xebee.xebia.in/2012/03/30/how-did-liferay-help-me-in-building-my-app/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 07:42:57 +0000</pubDate>
		<dc:creator>Anirudh Bhatnagar</dc:creator>
				<category><![CDATA[Liferay]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12971</guid>
		<description><![CDATA[In our current project we are building a portlet using Spring portlet MVC and liferay 5.2.3. More details about how we configured spring Portlet MVC with Liferay can be found here. Liferay has proved to be a boon for us in numerous ways. There were out of the box plugins, services and tag libraries which [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: verdana, geneva;">In our current project we are building a portlet using Spring portlet MVC and liferay 5.2.3.</span></p>
<p><span style="font-family: verdana, geneva;">More details about how we configured spring Portlet MVC with Liferay can be found <a href="http://xebee.xebia.in/2011/09/04/developing-portlets-using-spring-portlet-mvc-and-liferay-servicebuilder/">here</a>.</span></p>
<p><span style="font-family: verdana, geneva;">Liferay has proved to be a boon for us in numerous ways. There were out of the box plugins, services and tag libraries which did hasten our development process. Whenever we got a new requirement we were able to identify some feature of the liferay to suffice our needs.</span></p>
<p><span style="font-family: verdana, geneva;">So let’s see in detail, how actually liferay has helped us in solving those problems:</span></p>
<p><span style="font-family: verdana, geneva;"><span id="more-12971"></span></span><br />
<span style="font-family: verdana, geneva;"> <strong>1</strong>.<b> Liferay Service-builder</b>: Perhaps the most important tool and most widely used feature of liferay, We used this for rapidly generating services, persistence and sql create scripts . However, we did face several issues with Service builder, which would open a whole new chapter of discussion if we start dissecting service builder here, but for now I would say it was a good bargain. How to use service builder can be found <a href="http://xebee.xebia.in/2012/02/16/liferay-service-builder/">here</a>.</span></p>
<p><span style="font-family: verdana, geneva;"><strong>2</strong>.<b> Search implementation</b>: In our application we wanted to use <a href="http://lucene.apache.org/solr/">Apache Solr</a> for searching and indexing. Liferay provides us with a plug-in for using the same.</span></p>
<p><span style="font-family: verdana, geneva;">The integration was seamless and was as easy as deploying solr-web plugin war. More details on how to integrate solr with Liferay is given <a href="http://www.liferay.com/community/wiki/-/wiki/Main/Integrate+Solr+with+Liferay+portal">here</a>. And even if you choose not to use Solr, by default there is <a href="http://lucene.apache.org/core/">Lucene</a> search available.</span></p>
<p><span style="font-family: verdana, geneva;">In the control panel there is a link to call indexers of various configured portlets.(Control Panel -&gt;Indexer Admin).</span></p>
<p><span style="font-family: verdana, geneva;"><strong>3</strong>.<b> Ratings and Comments</b>-For implementing <a href="http://www.liferay.com/community/wiki/-/wiki/Main/Adding+Rating+to+a+portlet">ratings</a> we used liferays ratings tags provided by</span></p>
<p><span style="font-family: verdana, geneva;">&lt;liferay-ui:ratings&gt; and for <a href="http://www.liferay.com/community/forums/-/message_boards/message/5292621">comments</a> we used &lt;liferay-ui:discussions&gt;</span></p>
<p><span style="font-family: verdana, geneva;"><strong>4</strong>.<b>Image Library</b>- We had to upload and store images for various items used in our application.Instead of building from scratch a new image uploader, we used liferay's Image Galaery (IG).</span></p>
<p><span style="font-family: verdana, geneva;">We would upload the image and store its entry in DB using IGImageLocalService.</span></p>
<p><span style="font-family: verdana, geneva;">The image is stored in document library and its path is stored in database, to display this image we would need image id and image token appended to the context path.</span></p>
<p><span style="font-family: verdana, geneva;">Something like this :</span></p>
<blockquote><p><span style="font-family: verdana, geneva;">ThemeDisplay themeDisplay = (ThemeDisplay) pageContext.getRequest().getAttribute(WebKeys.<i>THEME_DISPLAY</i>);</span></p>
<p><span style="font-family: verdana, geneva;">source = themeDisplay.getPath() + "/image_gallery?img_id="</span></p>
<p><span style="font-family: verdana, geneva;">imageId + "&amp;t=" + ImageServletTokenUtil.<i> </i><i>getToken</i>(imageId);</span></p></blockquote>
<p><span style="font-family: verdana, geneva;">And print it using :</span></p>
<blockquote><p><span style="font-family: verdana, geneva;">&lt;img src= “${source}” /&gt;</span></p></blockquote>
<p><span style="font-family: verdana, geneva;">More details I would cover in a separate blog.</span></p>
<p><span style="font-family: verdana, geneva;"><strong>6</strong>.<b> PDF Generation</b> – Liferay provides DocumentConversionUtil which can be used to convert/generate PDFs. This service uses Open Office APIs to generate and convert documents into PDF.</span></p>
<p><span style="font-family: verdana, geneva;">All we needed was to setup Open Office Integration with liferay.</span></p>
<p><span style="font-family: verdana, geneva;">In case you dont want to configure OpenOffice you can always use some third party library like Itext, PDFBox etc.</span></p>
<p><span style="font-family: verdana, geneva;"><strong>7. Liferay mail and messaging service</strong> - Liferay provides facility to send mails and messages to the different users of liferay .We have</span></p>
<p><span style="font-family: verdana, geneva;">com.liferay.mail.service.MessageLocalServiceUtil which we used to send message notifications and mails.</span></p>
<blockquote><p><span style="font-family: verdana, geneva;">MessageLocalServiceUtil.<i>sendSimpleNotification</i>(</span></p>
<p><span style="font-family: verdana, geneva;">fromUser.getUserId(), toUser.getUserId(),</span></p>
<p><span style="font-family: verdana, geneva;">subject,</span></p>
<p><span style="font-family: verdana, geneva;">body);</span></p></blockquote>
<p><span style="font-family: verdana, geneva;"><strong>8. Liferay Tag Framework</strong>- We had a requirement to provide tags to the items in our product, which was food items in our case, we used the <a href="http://www.liferay.com/web/guest/community/wiki/-/wiki/1071674/Tags">Tag</a> framework provided by liferay to configure different categories of tags, and provide associations with food items.This can be found in Control Panel -&gt;Tags</span></p>
<p><span style="font-family: verdana, geneva;"><strong>9. Liferay roles</strong> – We had the different roles of Admin,User,Super Admin,Coach, and various permission issues, everything was catered by liferay roles, another of liferay's gem.</span></p>
<p><span style="font-family: verdana, geneva;"><strong>10. Liferay tags for error messages and internationalizatio</strong>n - Liferay provides various tags life &lt;liferay-ui:error&gt; &lt;liferay-ui:message&gt; which were used for styling and i18n. Many blogs are available on how to attain i18n and L10n in liferay.</span></p>
<p><span><span style="font-family: verdana, geneva;" face="verdana, geneva"><br />
</span></span></p>
<p><span><span style="font-family: verdana, geneva;" face="verdana, geneva">This list goes on(single sign-on, Social collaboration, content management,user profile mgmt,chats,blogs,forums...) as we still explore its various services and features, Overall I would say we did reduce the development time by 30 percent by having lot of in built features and out of the box plug-ins.</span></span></p>
<p><span face="verdana, geneva" style="font-family: verdana, geneva;"><br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/30/how-did-liferay-help-me-in-building-my-app/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Selenium-A Miraculous Tool (How,Why?)</title>
		<link>http://xebee.xebia.in/2012/03/28/selenium-a-miraculous-tool-howwhy/</link>
		<comments>http://xebee.xebia.in/2012/03/28/selenium-a-miraculous-tool-howwhy/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 11:47:53 +0000</pubDate>
		<dc:creator>Khyati Sehgal</dc:creator>
				<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test Auotmation]]></category>
		<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[salesforce]]></category>
		<category><![CDATA[Test Automation]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12693</guid>
		<description><![CDATA[In today's fast paced world, the task of manual testing where huge amounts of data is involved looks very cumbersome. Time is like the wind, it lifts the light and leaves the heavy. We have so little time to get all the things done which we want to do in our busy lives. This really [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: 'Times New Roman', serif;font-size: small"><b> </b></span><span style="font-size: small;font-family: 'times new roman', times"><br />
<span style="font-size: medium"> In today's fast paced world, the task of manual testing where huge amounts of data is involved looks very cumbersome. </span><span style="font-size: medium">Time is like the wind, it lifts the light and leaves the heavy. We have so little time to get all the things done which we want to do in our busy lives. This really comes into picture when it comes to running your own online business or site.</span></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Many, perchance most, software applications today are written as web-based applications to be run in an Internet browser. The efficacy of testing these applications varies broadly amid-st companies and organizations. In an era of highly interactive and susceptible software processes where many organizations are using some form of Agile methodology, test automation is frequently becoming a exigency for software projects. Test automation is oftentimes the answer. Test automation means using a software tool to run repeatable tests against the application to be tested. </span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Recently I had started working on this “prodigious”tool called “<strong>Selenium</strong>”in my project(<a href="http://www.salesforce.com">SFDC</a>).</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times"><span id="more-12693"></span></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Selenium, a demotic and well established testing framework is a wonderful tool that provides a convenient consolidated  interface that works with a large number of browsers, and allows you to write your tests in well-nigh every language one can imagine .</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">It was one of the first Open Source projects to fetch browser-based testing to the populace, and because it's written in JavaScript it's possible to quickly add support for new browsers that might be released.</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Selenium is written in JavaScript which causes a substantial infirmity.Browsers impose a pretty strict security model on any JavaScript that they execute in order to protect a user from malignant scripts. </span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Selenium was originally developed by Jason Huggins, who was later joined by other programmers and testers at ThoughtWorks.  But being a smart guy, he realized there were better uses of his time than manually stepping through the same tests with every change he made. </span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times"><b>Selenium</b> is a portable software testing framework for web applications. Selenium provides a record/playback tool for authoring tests without erudition a test scripting language (<b>Selenium IDE</b>). It also provides a test domain-specific language (<b>Selenese</b>) .It is open-source software, released under the Apache 2.0 license and can be downloaded and used free of cost.</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">Selenium has multiple software tools. Each has a specific role :</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times"><strong>Selenium IDE</strong>(Integrated Development Environment ) is a prototyping tool for building test scripts.It is easy to use and records user actions.But the drawback of it is, it can only be used as a Firefox plug-in.So to overcome this drawback Selenium1 (or <strong>Selenium RC</strong>)came up with many new features. It explains how to develop an automated test program using the Selenium RC API. Selenium RC components are:</span></p>
<ul>
<li><span style="font-size: medium;font-family: 'times new roman', times">The 	Selenium Server which launches and kills browsers, interprets and 	runs the Selenese commands passed from the test program, and acts as 	an <em>HTTP 	proxy</em>, 	intercepting and verifying <em>HTTP</em> messages passed between the browser 	and the AUT. </span></li>
<li><span style="font-size: medium;font-family: 'times new roman', times"><em>Client 	libraries</em> which provide the interface between each programming 	language and the <em>Selenium RC Server</em>. </span></li>
</ul>
<p><span style="font-size: medium;font-family: 'times new roman', times">You may, or may not, need the Selenium Server, depending on how you propound to use Selenium. </span><span style="color: #20435c;font-size: medium;font-family: 'times new roman', times"><b>Selenium Server </b></span><span style="font-size: medium;font-family: 'times new roman', times"> receives Selenium commands from your test program, interprets them, and reports back </span><span style="font-size: medium;font-family: 'times new roman', times">to your program the results of running those tests. </span><span style="font-family: 'times new roman', times;font-size: medium">If you will be strictly using the WebDriver API you do not perforce need the Selenium Server. Selenium-WebDriver makes direct calls to the browser using each browser’s native support for automation. How these direct calls are made, depends on the browser you are using.</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times"><b>Why migrate to WebDriver?</b></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">WebDriver has Smaller and compact API. WebDriver’s API is more Object Oriented than the original Selenium RC API. This can make it easier to work with. </span></p>
<ul>
<li><span style="font-size: medium;font-family: 'times new roman', times">Better 	emulation of user interactions. Where-in possible, WebDriver makes use 	of inherent events in order to interlude with a web page. This more 	closely mimics the way that the users work with the site and apps. 	In addition, WebDriver offers the progressive user interactions APIs 	which allow you to model complicated interactions with the site. </span></li>
</ul>
<ul>
<li><span style="font-size: medium;font-family: 'times new roman', times">Support by 	browser vendors. Opera, Mozilla and Google are all active 	participants in WebDriver’s development, and each have engineers 	working to improve the framework. </span></li>
</ul>
<p><span style="font-size: medium;font-family: 'times new roman', times">The first step when starting the migration is to change how you obtain your instance of Selenium. When using Selenium RC, this is done like so: </span></p>
<blockquote>
<pre><span style="font-size: medium;font-family: 'times new roman', times">Selenium selenium = new DefaultSelenium("localhost",4444,"*firefox","<a href="http://www.yoursite.com/">http://www.yoursite.com</a>");
selenium.start();</span></pre>
</blockquote>
<p><span style="font-size: medium;font-family: 'times new roman', times">One can also modify and use the Webdriver backed with the Selenium that is using WebDriver throughout and instantiating a Selenium instance on demand ,using this command:</span></p>
<blockquote>
<pre><span style="font-size: medium;font-family: 'times new roman', times"><strong>Se</strong><b>lenium selenium = new WebDriverBackedSelenium(“driver”, “baseUrl”);</b></span></pre>
<p><span style="font-size: medium;font-family: 'times new roman', times">A typical example using WebDriver in Java looks like this:</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">// Create an instance of WebDriver backed by Firefox</span><br />
<span style="font-size: medium;font-family: 'times new roman', times"> <b>WebDriver driver = new FirefoxDriver();</b></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">// Now go to the Google home page</span><br />
<span style="font-size: medium;font-family: 'times new roman', times"> <b>driver.get("http://www.google.com");</b></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">// Find the search box, and (ummm...) search for something</span><br />
<span style="font-size: medium;font-family: 'times new roman', times"> <b>WebElement searchBox = driver.findElement(By.name("q"));<br />
searchBox.sendKeys("selenium");<br />
searchBox.submit();</b></span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">// And now display the title of the page</span><br />
<span style="font-size: medium;font-family: 'times new roman', times"> <b>System.out.println("Title: " + driver.getTitle());</b></span></p></blockquote>
<p><span style="font-size: medium;font-family: 'times new roman', times"><strong>Conclusion :-</strong><br />
</span></p>
<p><span style="font-size: medium;font-family: 'times new roman', times">According to my experience, I want to conclude that Selenium <span style="color: #3e3e3e"> is heading in the right direction and it's worth-spending time in automation via Selenium for better ease !!!</span></span></p>
<p align="JUSTIFY"><span style="font-size: medium;font-family: 'times new roman', times"><b>Reference :- </b></span></p>
<p align="JUSTIFY"><span style="font-size: medium;font-family: 'times new roman', times"><b><a href="http://www.seleniumhq.org">www.seleniumhq.org</a></b></span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/28/selenium-a-miraculous-tool-howwhy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Java Robot replacing Human Intervention for capturing Screenshots</title>
		<link>http://xebee.xebia.in/2012/03/26/java-robot-replacing-human-intervention-for-capturing-screenshots/</link>
		<comments>http://xebee.xebia.in/2012/03/26/java-robot-replacing-human-intervention-for-capturing-screenshots/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 11:11:42 +0000</pubDate>
		<dc:creator>Shruti Khattar</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[java awt]]></category>
		<category><![CDATA[Robot class]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12841</guid>
		<description><![CDATA[When we talk of taking screen dumps without the use of keyboard, tools like Quick Screen Capture, Adobe Captivate, Camtasia -Relay, Capture Fox, Debut, GoView, Tip Cam and sorts, which can be picked up easily available over the internet and are user friendly. But very few of us know or have used the inbuilt Robot [...]]]></description>
			<content:encoded><![CDATA[<p>When we talk of  taking screen dumps without the use of keyboard, tools like Quick Screen Capture, Adobe Captivate, Camtasia -Relay, Capture Fox, Debut, GoView, Tip Cam and sorts, which can be picked up easily available over the internet and are user friendly. But very few of us know or have used the inbuilt Robot class in java AWT to perform this action. In this blog, I ll be discussing the untapped feature of Screen Capture in Robot class and its limitations as well.<span id="more-12841"></span></p>
<p>This class is used to generate native system input events for the purposes of test automation, self-running demos, and other applications where control of the mouse and keyboard is needed. The Robot class is extensively used in automated testing of Java platform implementations. Below is the code for an application that takes screenshots from the window after an interval of 10000ms. Using that, I have tried to capture server logs of a build in execution and a video tutorial. Below are the links to the folders uploaded on GoogleDocs that I have recorded using this application</p>
<p><a href="https://docs.google.com/?authuser=0#folders/0B__Z-mJq2wRnbkx0dllrQnFTUFd2X3h0cDRFb3gxZw" target="_blank">DemoTutorial</a></p>
<p><a href="https://docs.google.com/?authuser=0#folders/0B__Z-mJq2wRnVVByMF9OSHJRcm1MWUhnZEZONFV0Zw" target="_blank">ServerLogs</a></p>
<pre class="brush: jscript; highlight: [19,21,22]; title: ; notranslate">
public class ScreenCapture {
private int delay=10000;
	public static void main(String[] argv) throws InterruptedException {
		ScreenCapture screenCapture = new ScreenCapture();
		screenCapture.captureScreenShots();
	}

	boolean captureScreenShots() throws InterruptedException {
		boolean isSuccesfol = false;
		Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
		try {
			Robot robot = new Robot();
			BufferedImage[] screenshots = new BufferedImage[20];
			Rectangle bounds = new Rectangle(0, 0, (int) size.getWidth(),
					(int) size.getHeight());
			for (int i = 1; i &lt; screenshots.length; i++) {
				System.out.println(&quot;Running&quot;);
				screenshots[i] = robot.createScreenCapture(bounds);
				Thread.sleep(delay);
				try {
					ImageIO.write(screenshots[i], &quot;jpeg&quot;, new File(
							&quot;C:/ServerLogs/log&quot; + i + &quot;.jpeg&quot;));  /*Writing the array of  screenshots to the Files
													on the specified path*/
				} catch (IOException e) {
					e.printStackTrace();
					isSuccesful = false;
				}
			}
		} catch (AWTException e1) {
			e1.printStackTrace();
		}
		return isSuccesful;
	}
}
</pre>
<p><a href="https://github.com/ShrutiKhattar/RobotDemo" target="_blank">RobotCode</a> You can access the code here</p>
<p>In line no. 19, I have used Thread.sleep(delay) to specify the time interval between recording of the screen dumps, instead we could use the robot.delay(delay).It does not put to sleep everything, but only the calling thread. In a multi-threaded environment, the creating thread is often not the only calling one; actually more than one thread could call robot.delay(delay) at the same time, and when the method is synchronized i.e. exclusive then use Thread.sleep(delay) instead. Line no 21, where I've mentioned the path for storing the screen dumps as images can also be taken as an input from the user, or stated in a separate properties file.</p>
<p>In the use cases that I've demonstrated, snapshots can give you a clear idea of what has been happening in the video or a flash file, also, makes it easier to track what and where went wrong in the build process without having to fix an eye on them. they can be analyzed at any point of time. The results have been stored in the form of static images taken periodically.<br />
However, the code suffers from some weaknesses or limitations, which are given below:</p>
<ul>
<li>May not be able to automatically locate the location of the window you want to capture on the screen, you have to specify the window coordinates,or get the screen size programatically,</li>
<li>When the system is locked, the screen shots of a running application cannot be taken. the image comes as a black screen</li>
<li>It does not provide the capability of record and play</li>
<li>Error handling has to be gracefully managed by the application.</li>
</ul>
<p>Following are the exceptions that it is vulnerable to throw:</p>
<ol>
<li><b>IllegalArgumentException</b> - if screen is not a screen GraphicsDevice.</li>
<li><b>AWTException</b> - if the platform configuration does not allow low-level input control.</li>
<li><b>SecurityException</b> - if permission to create a robot object is not granted.</li>
<li><b>HeadlessException</b> - Thrown when code that is dependent on a keyboard, display, or mouse is called in an environment that does not support a keyboard, display, or mouse</li>
</ol>
<p>There are pros and cons in every utility, it might not cater to an extensive set of requirements or provide advance features, but understanding its capability and utilizing it at the right place and the right time makes it worth while.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/26/java-robot-replacing-human-intervention-for-capturing-screenshots/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Handling Session Failover on a Load Balanced Tomcat using Memcached</title>
		<link>http://xebee.xebia.in/2012/03/24/handling-session-failover-on-a-load-balanced-tomcat-using-memcached/</link>
		<comments>http://xebee.xebia.in/2012/03/24/handling-session-failover-on-a-load-balanced-tomcat-using-memcached/#comments</comments>
		<pubDate>Sat, 24 Mar 2012 14:58:31 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[memcached]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[load balance]]></category>
		<category><![CDATA[mod_jk]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12863</guid>
		<description><![CDATA[The problem: In our project we use four load-balanced tomcat nodes(with Sticky-Session enabled). Everything works fine but there is just one thing that bugs me. Whenever we do a production deployment, we remove one node, deploy on that and, if everything works fine, we remove second node from the load-balancer and deploy on that and [...]]]></description>
			<content:encoded><![CDATA[<h2>The problem:</h2>
<p> In our project we use four load-balanced tomcat nodes(with Sticky-Session enabled). Everything works fine but there is just one thing that bugs me. Whenever we do a production deployment, we remove one node, deploy on that and, if everything works fine, we remove second node from the load-balancer and deploy on that and so on. The problem is that whenever we remove a node during deployment, a session expired is thrown to all the users working on the node we just removed, as he/she is redirected to another node.</p>
<p>It is not a huge problem in our case. But this could be serious in e-commerce domain. For example if a user is filling his/her shopping cart and the session expires for no reason. <span id="more-12863"></span></p>
<h2>The configuration:</h2>
<p>I deployed a simple Spring App in two Tomcat instances. <a href="http://httpd.apache.org/" target="_blank">Apache Webserver</a> as the load balancer. <a href="http://tomcat.apache.org/tomcat-3.3-doc/mod_jk-howto.html" target="_blank">Apache's mod_jk</a> is used for load balancing using sticky-sessions. A single <a href="http://memcached.org/" target="_blank">Memcached Server</a> is used as an external key value server for storing sessions. I used <a href="http://code.google.com/p/xmemcached/" target="_blank">xMemcachedClient</a> to interact with Memcahed Server, because it is easily available as a pom dependency and is provided by Google.</p>
<h2>The solution:</h2>
<h3>Load-Balancing:</h3>
<p>I used this <a href="http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Server/1.0/html/HTTP_Connectors_Load_Balancing_Guide/Apache_HTTP_Configure.html" target="_blank">guide </a>to load-balance my application using Apache Webserver and mod_jk. Below is my config:</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/jkworkers.properties
JkLogFile logs/mod_jk.log
JkLogLevel &quot;info&quot;
JkLogStampFormat &quot;[%a %b %d %H:%M:%S %Y]&quot;
JkMount /app* loadbalancer
</pre>
<p>And below is the content of my jkworkers.properties file:</p>
<pre class="brush: plain; title: ; notranslate">
# Define list of workers that will be used for mapping requests
worker.list=loadbalancer,status

# Define Node1
# modify the host as your host IP or DNS name.
worker.node1.port=8009
worker.node1.host=localhost
worker.node1.type=ajp13
worker.node2.ping_mode=A
worker.node1.lbfactor=1 

# Define Node2
# modify the host as your host IP or DNS name.
worker.node2.port=7009
worker.node2.host=localhost
worker.node2.type=ajp13
worker.node2.ping_mode=A
worker.node2.lbfactor=1

# Load-balancing behavior
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1
# Status worker for managing load balancer
worker.status.type=status
</pre>
<h3>Managing Sessions:</h3>
<p>To manage session failover I used the following approach:</p>
<ul>
<li>Both the tomcats hold sessions locally on their respective jvm.
</li>
<li>Additionally all the sessions(of both tomcats) are stored in Memcached server.(Cache expiry in memcached can be configured, I have configured it to be 1day)
</li>
<li>Suppose a user is browsing on <strong>node1</strong>. In general, he will be directed to node1 as sticky-sessions are enabled and his  session can be fetched from the local memory. In case of <strong>node1</strong> fails, the next request will go to the other tomcat instance i.e. <strong>node2</strong>. <strong>node2</strong> is asked for a session he does not know. So, <strong>node2</strong> will fetch the session from the Memcached Server and store it in its local jvm. Now, node2 is responsible for this session.
</li>
</ul>
<p>Now lets see some code.</p>
<pre class="brush: java; highlight: [14,15,22]; title: ; notranslate">
package in.xebia.vijay.controllers;
//import statements
@Controller
public class HomeController {

	private static final String SEPARATOR = &quot;|&quot;;
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	@Resource
	private SessionService sessionService;

	@RequestMapping(value = &quot;/login&quot;, method = RequestMethod.POST)
	public String home(Model model, User user,HttpSession session, @CookieValue(&quot;JSESSIONID&quot;) String jsessionId) {
		logger.info(&quot;In home!&quot;);
		sessionService.set(session.getId()+SEPARATOR+&quot;user&quot;, user, session);
		User userFromSession = (User) sessionService.get(jsessionId+SEPARATOR+&quot;user&quot;, session);
		model.addAttribute(&quot;userName&quot;, userFromSession.getUserName());
		return &quot;home&quot;;
	}
	@RequestMapping(value = &quot;/check&quot;, method = RequestMethod.GET)
	public String check(Model model, HttpSession session, @CookieValue(&quot;JSESSIONID&quot;) String jsessionId) {
		logger.info(&quot;In Check!&quot;);
		User userFromSession = (User) sessionService.get(jsessionId+SEPARATOR+&quot;user&quot;, session);
		model.addAttribute(&quot;userName&quot;, userFromSession.getUserName());
		return &quot;check&quot;;
	}
	@RequestMapping(value = &quot;/&quot;, method = RequestMethod.GET)
	public String login() {
		logger.info(&quot;In login!&quot;);
		return &quot;login&quot;;
	}
}
</pre>
<p>The lines to note in above code are <strong>14,15 and 22</strong>:</p>
<ul>
<li>In line <strong>14</strong>, I am adding the current user to session using <strong>SessionService</strong>. Point to note is that instead of doing something like :
<pre class="brush: java; title: ; notranslate">sessionService.set(&quot;user&quot;, user, session);</pre>
<p>I have written :</p>
<pre class="brush: java; title: ; notranslate">sessionService.set(session.getId()+SEPARATOR+&quot;user&quot;, user, session);</pre>
<p>I am "deliberately" appending the SessionId just to ensure that if a particular tomcat node fails, the other tomcat can retrieve failed node's sessions using the cookie <strong>JSESSIONID</strong> stored in the client header.
</li>
<li>And that is the reason, in lines <strong>15</strong> as well as <strong>22</strong>, I am fetching session attribute from the <strong>SessionService </strong>using the <strong>JSESSIONID</strong> retrieved from the cookie.
</li>
</ul>
<p>All the other code is quite self explanatory. Now lets have a look at the <strong>SessionServiceImpl.java</strong></p>
<pre class="brush: java; title: ; notranslate">
package in.xebia.vijay.impl;
//import statements
@Service
public class SessionServiceImpl implements SessionService {

	@Autowired
	private MemcachedClient memcachedClient;
	private static int EXPIRY = 24 * 60 * 60;

	@Override
	public &lt;T&gt; void set(String key, T value, HttpSession session) {
		try {
			session.setAttribute(key, value);
			memcachedClient.set(key,EXPIRY,value);
		} catch (TimeoutException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (MemcachedException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings(&quot;unchecked&quot;)
	@Override
	public &lt;T&gt; T get(String key, HttpSession session) {
		try {
			if(session.getAttribute(key)!=null)
				return (T) session.getAttribute(key);
			else if(memcachedClient.get(key)!=null){
				String[] keyPart = key.split(&quot;|&quot;);
				String newKey = session.getId()+&quot;|&quot;+keyPart[1];
				session.setAttribute(newKey, memcachedClient.get(key));
				memcachedClient.set(newKey, EXPIRY, memcachedClient.get(key));
				memcachedClient.delete(key);
				return memcachedClient.get(newKey);
			}
			else
				return null;
		} catch (TimeoutException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (MemcachedException e) {
			e.printStackTrace();
		}
		return null;
	}

}
</pre>
<p>Points to be noted : </p>
<ul>
<li>In the implementation of method
<pre class="brush: java; title: ; notranslate">public  void set(String key, T value, HttpSession session); </pre>
<p>we add the attribute to HttpSession as well as the Memcahced Server, so that in case of any node failure the other node can fetch the values from Memcached Server.
</li>
<li>In the implementation of method
<pre class="brush: java; title: ; notranslate">public  T get(String key, HttpSession session); </pre>
<p>we first check the local session if the attribute is found, well and good simply return with the value. Else we check the Memcahed Server for the key provided if some value is found we store that attribute in the current session and replace the value in Memcached Server with new key(which is appended with the session id of current tomcat).
</li>
</ul>
<p>Below I am attaching the bean definition for xMemcachedClient:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;beans:bean id=&quot;memcachedClient&quot; class=&quot;net.rubyeye.xmemcached.XMemcachedClient&quot;&gt;
		&lt;beans:constructor-arg type=&quot;java.lang.String&quot;  value=&quot;localhost&quot;/&gt;
		&lt;beans:constructor-arg  type=&quot;int&quot; value=&quot;11211&quot;/&gt;
&lt;/beans:bean&gt;
</pre>
<p>Nothing special just passing the host and port to initialize the memCachedClient.</p>
<p>In case you want to run the code on your own machine here is the link to <a href="https://raw.github.com/vijayrawatsan/Load-Balanced-Session-FailOver-Handling" target="_blank">Github Repository</a>.</p>
<h2>Conclusion:</h2>
<p>In this blog, we learned how to manage session-failover on load-balanced tomcat nodes with sticky-session enabled using Memcached Server.<br />
Happy reading.</p>
<p>PS : The Spring App created is quite naive and is only for the purpose of demonstration. You can obviously have a different implementation using the same concept.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/24/handling-session-failover-on-a-load-balanced-tomcat-using-memcached/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MindMaps in Website Testing</title>
		<link>http://xebee.xebia.in/2012/03/23/mindmaps-in-website-testing/</link>
		<comments>http://xebee.xebia.in/2012/03/23/mindmaps-in-website-testing/#comments</comments>
		<pubDate>Fri, 23 Mar 2012 08:15:37 +0000</pubDate>
		<dc:creator>Subrahmanyam</dc:creator>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Agile Awareness Workshop]]></category>
		<category><![CDATA[freemind]]></category>
		<category><![CDATA[mindmaps]]></category>
		<category><![CDATA[Software testing]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12814</guid>
		<description><![CDATA[Writing Test cases or Scenarios is one of the significant part during testing. One must ensure full coverage of scenarios efficiently within time.MindMaps provides us with the solution. I am currently handling the testing of one of our client's website, where i had to create Test scenarios for different features in every sprint. Initially i [...]]]></description>
			<content:encoded><![CDATA[<p>Writing Test cases or Scenarios is one of the significant part during testing. One must ensure full coverage of scenarios efficiently within time.MindMaps provides us with the solution. I am currently handling the testing of one of our client's website, where i had to create Test scenarios for different features in every sprint.<br />
Initially i was documenting the scenarios in the test management tool, but i started using Mindmaps to generate my Test Scenarios. It was a real help, both in time efficiency and completeness of coverage. So, let me give a brief introduction to MindMaps. <span id="more-12814"></span></p>
<p><strong>What is MindMap ?</strong></p>
<p>Mindmaps is a way to visualize your thoughts ,ideas and creativity in order to effectively plan your testing process.It uses lots of colors and keywords to make it more presentable catchy and impressive.<br />
There are certain steps to use Mindmaps, which are :<a rel="attachment wp-att-12819" href="http://xebee.xebia.in/2012/03/23/mindmaps-in-website-testing/1-4/"><img height="187" width="300" src="http://xebee.xebia.in/wp-content/uploads/2012/03/11-300x187.jpg" title="Figure 1" class="alignright size-medium wp-image-12819" /></a></p>
<ol>
<li> Place your central idea or subject at the center as a an image.</li>
<li> Use branching of the Central Idea.</li>
<li>Connect each branch with its sub branches.</li>
<li> Use various colors throughout</li>
<li> Use keywords and key phrases</li>
<li> Use as many images as possible so that one can remember.</li>
</ol>
<p><strong>An Example to Illustrate Mindmaps:</strong></p>
<p>The following image shows how to create Cases with MindMaps(Figure 1). It shows "Human" as the central idea and its subsequent branches: Personal, Work, Business , Career and Education.Each of its branches are further divided into sub branches. It has used lots of color and images to give a catchy and expressive look. Now starting with the central idea we can go to each subsequent branches till the branch ends and that makes a single test case. This is how Test Scenarios can be generated with ease.</p>
<p><strong>Tools that can be used to create MindMaps:</strong></p>
<p>There are various tools to generate Test Scenarios using Mindmaps like : Freeminding Software, MindManager. Now that we have a fair idea about Mindmaps, let us see how we can ensure using the same in Website Testing.</p>
<p><strong>Mindmaps used in my current Projects:</strong></p>
<p>MindMaps for Website Testing: I am currently testing our client's Website which provides a meal plan for the day to a user. I have generated test cases using the tool Freeminds. Let us see what this site does. It gives the user a meal plan for the day. Various meals are provided to different meal slot : Breakfast, Snack, Lunch and Dinner. There are various other features associated with each meal slot.So, lets create a Mind Map tree for the following Feature. Create a Central idea - MEAL PLAN. Create sub branches of it : Breakfast, Lunch, Dinner and Snack. Each branch will have its own sub branches: Various food items (1 or more than 1). Now each food item will have its subbranches: Delete, Change meal, Add Calories, I ate this ,Substitute, Making a food Favorite, Facebook/Twitter like, Total Calories. Now using this data we can create a Mindmap which is shown as below using Freeminds (Figure 2).</p>
<p>Using the above Mindmaps the test cases which we can create out of it are as follows:<a rel="attachment wp-att-12818" href="http://xebee.xebia.in/2012/03/23/mindmaps-in-website-testing/2-5/"><img height="280" width="300" src="http://xebee.xebia.in/wp-content/uploads/2012/03/22-300x280.jpg" title="2" class="alignright size-medium wp-image-12818" /></a></p>
<ol>
<li> Breakfast-&gt; Food-&gt; Delete.</li>
<li> Breakfast-&gt; Food-&gt; Change Meal-&gt; Recent.</li>
<li> Breakfast-&gt; Food-&gt; Change Meal-&gt; Custom.</li>
<li> Breakfast-&gt; Food-&gt; Change Meal-&gt; Search.</li>
<li> Breakfast-&gt; Food-&gt; Change Meal-&gt; Favorite.</li>
<li> Breakfast-&gt; Food-&gt; Add Calories.</li>
<li> Breakfast-&gt; Food-&gt; I ate this.</li>
<li> Breakfast-&gt; Food-&gt; Substitute.</li>
<li> Breakfast-&gt; Food-&gt; Favorite.</li>
<li> Breakfast-&gt; Food-&gt; Unfavorite.</li>
<li> Breakfast-&gt; Food-&gt; Facebook Like.</li>
<li>Breakfast-&gt; Food-&gt; Twitter Like.</li>
<li>Breakfast-&gt; Food-&gt; Calculate Total Calories.</li>
</ol>
<p>We have created test cases for Breakfast. Similarly we can use the same data for other branches: Lunch , Snack and Dinner. In all we have 52 test cases with us and we have covered each area of this feature. So the error or probability of missing test cases is minimized to a great extent.</p>
<p><strong>Usefulness of Mindmaps:</strong></p>
<p>Let me share my personal advantages which i faced while using Mindmaps.<br />
1) Very easy to implement.<br />
2) Less time taken to construct Test scenarios.<br />
3) Probability of missing a test case is minimized to a great extent.<br />
4) Under critical time constraints it is the best way to create test scenarios.</p>
<p>Having said that, i would personally like to recommend every tester to at least try using Mindmaps during their test case generation. It will be something which would be used for a very long time.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/23/mindmaps-in-website-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Write Code that writes code</title>
		<link>http://xebee.xebia.in/2012/03/23/write-code-that-writes-code/</link>
		<comments>http://xebee.xebia.in/2012/03/23/write-code-that-writes-code/#comments</comments>
		<pubDate>Fri, 23 Mar 2012 00:16:13 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Agile Mindset]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flex Architectures]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12774</guid>
		<description><![CDATA[We never like to write a boiler plate code.It makes programming too boring. If we have to write a boiler plate code that might be a flaw in the design. Somehow the above assumption is not good. A lot of times when you are architecting a solution where there is  a distributed team of 20-30 [...]]]></description>
			<content:encoded><![CDATA[<p>We never like to write a boiler plate code.It makes programming too boring. If we have to write a boiler plate code that might be a flaw in the design. Somehow the above assumption is not good. A lot of times when you are architecting a solution where there is  a distributed team of 20-30 people you have to follow a particular design in writing the code that others understand. Sometimes frameworks might not give you a option to design the application such that there is no boiler plate code.<span id="more-12774"></span></p>
<div></div>
<p><br/></p>
<div>Templating is a  parital solution of problem. Ofcourse now you need to create good templates. Finding the right template solution and integrated in your system is the perfect solution to this boiler plate code problem. Please have a look at the below video which show how we solve this problem for us.</div>
<p><object width="640" height="360"><param name="movie" value="http://www.youtube.com/v/Jgiv7YfXRcU?version=3&amp;hl=en_US&amp;rel=0&amp;fmt=22"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Jgiv7YfXRcU?version=3&amp;hl=en_US&amp;rel=0&amp;fmt=22" type="application/x-shockwave-flash" width="640" height="360" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>As you saw , just as you create a simple class using new class , you can also generate the boiler plate code without much problem and make your life much simpler. Over the period of time refactoring can help in creating more abstraction and generating more code that can help.Enjoy!!!</p>
<p>Please find the source <a href='http://xebee.xebia.in/wp-content/uploads/2012/03/ParsleyCodeGenerator.zip'>ParsleyCodeGenerator</a> for generating the parsely code with templates. Compiling the above air application in Flash Builder will result in installer that can be installed on your machine. Once installed use <a href='http://www.vogella.com/articles/EclipsePlugIn/article.html#contribute_packageexplorer'>Eclipse Plugin</a><br />
blog to create a simple plugin that will invoke Parsley Code Generator.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/23/write-code-that-writes-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Few words on automation framework design strategies.</title>
		<link>http://xebee.xebia.in/2012/03/22/few-words-on-automation-framework-design-strategies/</link>
		<comments>http://xebee.xebia.in/2012/03/22/few-words-on-automation-framework-design-strategies/#comments</comments>
		<pubDate>Thu, 22 Mar 2012 17:23:44 +0000</pubDate>
		<dc:creator>ngaur</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Automation]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12758</guid>
		<description><![CDATA[Automation has always been an attractive domain as the very fact that the test automation reduces repetetive testing effort and speed up the regression of application functionality. So today every test team want automation and has it. However, test automation can go expensive if it is not managed properly and may lead to the situation that can [...]]]></description>
			<content:encoded><![CDATA[<p lang="en" class="alignleft"><span style="font-family: 'andale mono', times; font-size: medium;">Automation has always been an attractive domain as the very fact that the test automation reduces repetetive testing effort and speed up the regression of application functionality. So today every test team want automation and has it.<span id="more-12758"></span></span></p>
<p lang="en" class="alignleft"><span style="font-family: 'andale mono', times; font-size: medium;"> </span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">However, test automation can go expensive if it is not managed properly and may lead to the situation that can ruin the testing strategies and targets. So here I am going to elaborate this key point.</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">Usually test automation is managed and used in productive way through well organised framework , typically the strategy that usually followed is called "Scriptless Automation". </span><span style="font-family: 'andale mono', times; font-size: medium;">Framework design ease the test automation that of course doesn't depends on the capability of testing tool choosen rather it aims to remove the script writing  that usually require tool specific skills.</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">Lets discuss in short the needs of going scriptless :</span></p>
<p><span style="font-family: 'andale mono', times; font-size: medium;"><b>a). Time-to-automate </b></span><span style="font-size: x-small;"> </span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">Faster the automation faster the application going Live.But, usually automation require typical scripting and coding skills that is too expensive in terms of time. This time slag can be very dangerous in SDLC.</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><b>b). Maintenance</b></span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">Maintaining the automation process is the biggest challange i guess.With the new releases ,team need to maintain the automation process and this becomes the problem when script automation is into the process. As your test suite increases, you will face an excessive maintenance burden - which will lead to loss of more time and money.</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><b>c). Tool specific skills required</b>: </span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;">Test automation require scripting and for that tool specific knowledge is required. So here it require good programmers.</span></p>
<p align="JUSTIFY" lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><span><b>Automation Design Strategy:</b></span></span></p>
<p align="JUSTIFY" lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><span>Basic and widely used strategy for framework development is the combination of Data Driven Design and Keyword driven design typically named as Hybrid. Hybrid design basically aims to use the positive feature from all approches. </span></span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><span>Keyword Driven framework requires the development of data storage(like data-tables etc) and keywords for defining the actions, this is entirely independent of the  automation tool used to execute or perform keywords on target application and the test script code that "drives" the application-under-test is written accordingly for that particular keyword. Keyword-driven tests look very similar to manual test cases. In a keyword-driven test, the functionality of the application-under-test is documented in a table as well as in step-by-step instructions for each test. In this method, the entire process is data-driven, including functionality.</span></span><span style="font-family: 'andale mono', times; font-size: medium;">﻿</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><span>Data-Driven design reads the inputs and outputs fron the data files, nothing is statically assign in script.So this approach helps automation with multiple sets of data.But it has its limitations that vary according to the requirement of users.</span></span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><a href="http://xebee.xebia.in/2012/03/22/few-words-on-automation-framework-design-strategies/hybrid2/" rel="attachment wp-att-12759"><img src="http://xebee.xebia.in/wp-content/uploads/2012/03/hybrid2-300x250.jpg" width="300" height="250" class="aligncenter size-medium wp-image-12759" /></a><br />
</span></p>
<p align="JUSTIFY"><span style="font-family: 'andale mono', times; font-size: medium;"><span>Hybrid design basically aims to utilise the positive feature from all approches. As hybrid support both data-driven and keyword-driven approach, it smoothly handle the cases where it is difficult or you can say not feasible to re-implement a new keyword for that particular scenario.And that too can be changed later on to keyword-driven approach.Hybrid framework mainly constitute of Data-driven engine,application independent functions,Utility libraries. The data store that engine would be using devides into three parts. First a repository map that basically containing the logical names of application objects, then comes the data tables that would be used in both data-driven and keyword driven approach and ofcourse the data tables that contains the flow, these may be managed at different levels according to the requirements.</span></span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><span>These design mainly provide a way of going scriptless , through which automation process could be optimized and managed.This one time effort in developing such design could save a lot of time to automate applications, and the tool specific skills that normally require in automation is no more headache and above all cost of maintaining the automation process reduces tremendously.</span></span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><br />
</span></p>
<p lang="en"><span style="font-family: 'andale mono', times; font-size: medium;"><br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/22/few-words-on-automation-framework-design-strategies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why would Agile fail for you?</title>
		<link>http://xebee.xebia.in/2012/03/22/why-would-agile-fail-for-you/</link>
		<comments>http://xebee.xebia.in/2012/03/22/why-would-agile-fail-for-you/#comments</comments>
		<pubDate>Thu, 22 Mar 2012 06:47:32 +0000</pubDate>
		<dc:creator>Anirudh Bhatnagar</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Mindset]]></category>
		<category><![CDATA[agile agile mindset]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12718</guid>
		<description><![CDATA[This is not yet-another-agile-gaga blog, but a story, some of you might find it interesting as well. Not A very long time ago and not in a galaxy far,far away, there were two teams. One team was following Scrum without Agile Mindset and second had an agile mindset. The ‘A’ team who were following Scrum, [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: verdana, geneva;">This is not yet-another-agile-gaga blog, but a story, some of you might find it interesting as well.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">Not A very long time ago and not in a galaxy far,far away, there were two teams.</span><br />
<span style="font-size: small; font-family: verdana, geneva;"> One team was following Scrum without Agile Mindset and second had an agile mindset.</span><br />
<span style="font-size: small; font-family: verdana, geneva;"> The ‘A’ team who were following Scrum, failed!! And ended up blaming agile, whereas the second team ‘B’, came out in flying colors and eventually moved to scrum.</span></p>
<p style="text-align: left;"><span style="font-size: small; font-family: verdana, geneva;">Let’s delve into the details to see what exactly happened…</span><br />
<span style="font-size: small; font-family: verdana, geneva;"> <span id="more-12718"></span></span><br />
<span style="font-size: small; font-family: verdana, geneva;"> <strong><span class="aligncenter"> Team A</span></strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">The team was following Waterfall earlier, they had hierarchy, people were slogging, team was not happy and hence the project was failing.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">Suddenly they were told to take up Agile! Hence they introduced Scrum practices into their team .With scarce agile mindset coaching, they started following the processes. Below are the results:</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>1. The hierarchy was removed from the team, everyone had an equal say. </strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">As some senior team members were not convinced enough they did not believe in this. Sometimes they would not give their input and wait for things to go wrong and just to prove a point. This created a lack of trust and chaos in the team.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>2. Sprint planning and estimation was done in story points:</strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">Everyone believed it was just another way of estimation and did not understand the intension behind it. Moreover there was pressure from delivery to estimate in hours for future billing projections. Hence after the team had estimated in story points a constant to convert story points into hours was introduced.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>3. Process: The iteration cycle become 3 weeks long with demo at the sprint end</strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">As there were hours involved team members had to slog sometimes. Demo became a tool to pressurize team for delivery, hence the team perceived demo as a burden rather than feedback. So again this ritual became a cause of agony.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>4. Daily Standups were held:</strong></span><br />
<span style="font-size: small; font-family: verdana, geneva;"> There was lack of trust, people thought it was a burden and it became a formality. Soon team started hating it.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>5. Retro at the sprint end:</strong></span><br />
<span style="font-size: small; font-family: verdana, geneva;"> Throughout the sprint people would not raise issue but wait for the retro to blame each other for failures.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>6. Feedback:</strong></span><br />
<span style="font-size: small; font-family: verdana, geneva;"> Nothing happened people did not understand this concept at all.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">So here we see a typical case of Agile going wrong when people just follow the process without knowing why is Agile important and what is the mindset required.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong> Team B</strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">In the second case: we see how a team who had a mindset of Agile automatically followed some practices of scrum without even knowing about them. Eventually started following scrum and became successful.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">So in the second team:</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong>1. There was no hierarchy.</strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong> 2. Every one updated each other of the tasks they were doing every morning </strong>(equivalent to Scrum Standup update).</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong> 3. They had small iteration cycles of 3 weeks and feedback was taken and implemented.</strong></span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><strong> 4. Estimation:</strong> (how they evolved to story point estimation)</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"> Initially they were doing a very broad estimation in hours at the start of every iteration.</span><br />
<span style="font-size: small; font-family: verdana, geneva;"> Later they observed that this estimation was different from developer to developer.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">•	This was found in a collaboration meeting at the end of iteration (equivalent to Scrum Retro).</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">•	First solution they found was to estimate with respect to each developer. But this involved a dependency of that person in the team and if some else had to that it did not work. The idea failed in that iteration.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">•	Next meeting they were thinking on the lines of a finding a method which would be comparative, weighted and take care of complexity as well but would not be dependent on the hours each developer would take.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">•	Someone in the team found out about Story points estimation in Agile and they started following it.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">They had the agile mindset to collaborate, accept feedback and share the findings.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"> Which helped them learn “WHY” estimate in story points. And once the “REASON” was clear they implemented Scrum successfully in their team.</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;"><br />
</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">So, to summarize, I would say that once the team can understand the value of "WHY" then everything would eventually fall in place.<br />
</span></p>
<p><span style="font-size: small; font-family: verdana, geneva;">Teams will focus on WHAT needs to be done, because they know WHY it is important and HOW to do it will come at runtime. </span><span style="font-family: verdana, geneva; font-size: small;">Though Mindset can lead to defining processes Process cannot instill a Mindset on its own.</span></p>
<p><span style="font-family: verdana, geneva; font-size: small;">That is what I feel,</span><strong style="font-family: verdana, geneva; font-size: small;"> AGILE MINDSET </strong><span style="font-family: verdana, geneva; font-size: small;">is all about.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/22/why-would-agile-fail-for-you/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>iOS : Creating a slide show video from the images</title>
		<link>http://xebee.xebia.in/2012/03/16/ios-creating-a-slide-show-video-from-the-images/</link>
		<comments>http://xebee.xebia.in/2012/03/16/ios-creating-a-slide-show-video-from-the-images/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 21:39:33 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12656</guid>
		<description><![CDATA[Lets say i have a list of images and I would like to create a slideshow video , so that i can easily share this video with anyone I wish to. iOS API gives a very easy way of creating the videos from the photo with the help of following libraries AVFoundation , CoreVideo , [...]]]></description>
			<content:encoded><![CDATA[<p>Lets say i have a list of images and I would like to create a slideshow video , so that i can easily share this video with anyone I wish to. iOS API gives a very easy way of creating the videos from the photo with the help of following libraries AVFoundation , CoreVideo , CoreMedia frameworks. So lets get started <span id="more-12656"></span>Following are the simple steps that need to be followed to create a a slideshow from the list of images.</p>
<ul>
<li>Calculate the size of video based on max height and width of the images.</li>
<li>Initialize the video writer with appropriate video parameters.</li>
<li>Defining the parameters for the video stream.</li>
<li>Loop through all the images and convert the image from UIImage to pixel so that it can be written on the video stream</li>
<li>Once done close the stream and finally close the video writer.</li>
</ul>
<p>The first step here is pretty simple. Loop through all the images and find out the maxHeight and maxWidth of all the image.For the second step we need to define the kind of media file we want to make. AVFoundation provides us with a class named AVAssetWriter, which we can initialize with the path where we want to create the file and the type of file. It can be a audio / video,etc . We are going to initialize the writer to create a video file</p>
<pre class="brush: plain; title: ; notranslate">
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:

[NSURL fileURLWithPath:filePath] fileType:AVFileTypeQuickTimeMovie error:&amp;error];
</pre>
<p>The next step is to create a video stream for this we need to figure out what is the video codec that we need to use and what id the height &amp; width of video stream. We have already calculated the maxHeight and maxWidth for the video stream and we are going to use H264 as the codec for the video. AVFoundation has a class named AVAssetWriterInput which can be used to create audio video stream. We will be initializing the stream with videosettings as shown</p>
<pre class="brush: plain; title: ; notranslate">

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,

[NSNumber numberWithInt:maxwidth], AVVideoWidthKey,

[NSNumber numberWithInt:maxheight], AVVideoHeightKey,

nil];

AVAssetWriterInput* videoStream = [[AVAssetWriterInput
                                  assetWriterInputWithMediaType:AVMediaTypeVideo
                                  outputSettings:videoSettings] retain];
</pre>
<p>Life would have been every simple if we have to only create the stream and write the images to the buffer.However we cannot do so. One was of doing this is creating the PixelBuffer adaptor and initalize it to the stream and write using the adaptor.This is what we are going to do.</p>
<pre class="brush: plain; title: ; notranslate">

AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor

assetWriterInputPixelBufferAdaptorWithAssetWriterInput: videoStream

sourcePixelBufferAttributes:nil];
</pre>
<p>Once done add the stream to the video writer</p>
<pre class="brush: plain; title: ; notranslate">

[videoWriter addInput: videoStream];
</pre>
<p>Using the asset writer start creating the video now.</p>
<pre class="brush: plain; title: ; notranslate">

[videoWriter startWriting];

[videoWriter startSessionAtSourceTime:kCMTimeZero];
</pre>
<p>Moving forward we are going to create convert every image into a pixel buffer and add this buffer as a frame for the video at nth time. frameCount is the one that keeps the seconds at which we want the image to be displayed currently it is absolute.I have found a simple function from internet that converts the UIImage to pixel buffer. This takes a Image as a input and converts it to pixel buffer</p>
<pre class="brush: plain; title: ; notranslate">

+ (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image andSize:(CGSize) size
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width,
size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,&amp;pxbuffer);
NSParameterAssert(status == kCVReturnSuccess &amp;&amp; pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
NSParameterAssert(pxdata != NULL);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
size.height, 8, 4*size.width, rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
</pre>
<p>Now that we have everything ready we start fromt the first image and loop through each image convert the UIImage to pixels and add to the video stream. In this example we are showing only one image everysecond, hence we are incrementing the framecount after every. Note that after adding the buffer for every image we are waiting for the adapter stream to be ready. Hence adding a sleep time after every write. Once you are done writing all the images close the session for the stream and video writer to produce a slideshow video at desired url.</p>
<pre class="brush: plain; title: ; notranslate">
CVPixelBufferRef buffer = NULL;
int frameCount = 1;

for(UIImage *img in images)
{

   buffer = [self pixelBufferFromCGImage:[img CGImage] andSize:img.size];
   BOOL append_ok = NO;

   while (!append_ok){
      if (adaptor.assetWriterInput.readyForMoreMediaData){
           CMTime frameTime = CMTimeMake(frameCount,(int32_t) 1);
           append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
           if(buffer)
               CVBufferRelease(buffer);
           [NSThread sleepForTimeInterval:0.05];
       }else{
           [NSThread sleepForTimeInterval:0.1];
       }
    }
frameCount++;
}

[videoStream markAsFinished];
[videoWriter finishWriting];
</pre>
<p>So that was it to create a video from UIImages in iOS using AVFoundation. Unfortunately its a little lengthy procedure and could have been more API friend in creating / adding images to the stream , converting image into pixebuffer etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/16/ios-creating-a-slide-show-video-from-the-images/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>E-sign solutions in iOS</title>
		<link>http://xebee.xebia.in/2012/03/09/e-sign-solutions-in-ios/</link>
		<comments>http://xebee.xebia.in/2012/03/09/e-sign-solutions-in-ios/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 11:14:12 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[digital signing]]></category>
		<category><![CDATA[e-sign]]></category>
		<category><![CDATA[electronic signing]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[signature]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12590</guid>
		<description><![CDATA[Enterprise applications may have a requirement of e-signing a document before sending it to some third party receiver, for instance if a user is disbursing some bills he may have to sign it. Similarly a surveyor may have to sign a survey to prove his authenticity. On the other hand one should keep in mind [...]]]></description>
			<content:encoded><![CDATA[<p>Enterprise applications may have a requirement of e-signing a document before sending it to some third party receiver, for instance if a user is disbursing some bills he may have to sign it. Similarly a surveyor may have to sign a survey to prove his authenticity. On the other hand one should keep in mind this whole process is germane to enterprise applications, one should not force such signings on normal lifestyle applications. So if you are in a need of such a solution, then continue reading. <span id="more-12590"></span> </p>
<p>The upmost challenge in creating a <strong>e-sign solution is smoothening the curves of the lines that are drawn by the user</strong>. If you need not to worry about overcoming this challenge and considering that you have the budget, then you can check this <a href="http://tenonedesign.com/t1autograph.php">link</a>. They also have an app on <a href="http://itunes.apple.com/us/app/autograph/id339423436?mt=8">app store</a> which you can try out.<br />
Having said this I wanted to have something open source, so I tried some solutions/API's to build a e-sign component which can be used to sign, save and send signature to third parties. In any of the solutions the <strong>entry points</strong> are the following touch related methods that are used to detect user interaction with the device.</p>
<pre class="javascript">&nbsp;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span> touchesBegan:<span style="color: #66cc66;">&#40;</span>NSSet *<span style="color: #66cc66;">&#41;</span>touches withEvent:<span style="color: #66cc66;">&#40;</span>UIEvent *<span style="color: #66cc66;">&#41;</span>event ;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span> touchesMoved:<span style="color: #66cc66;">&#40;</span>NSSet *<span style="color: #66cc66;">&#41;</span>touches withEvent:<span style="color: #66cc66;">&#40;</span>UIEvent *<span style="color: #66cc66;">&#41;</span>event ;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>touchesEnded:<span style="color: #66cc66;">&#40;</span>NSSet *<span style="color: #66cc66;">&#41;</span>touches withEvent:<span style="color: #66cc66;">&#40;</span>UIEvent *<span style="color: #66cc66;">&#41;</span>event;
&nbsp;</pre>
<p> Here are few of them. </p>
<p><strong>1. Core graphics</strong><br />
The hurdle of smoothening the curves can be overcome by using <a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">Beizer curves</a>. We can use cubic curves to achieve our goal. For that we need to supply four points (say p1,p2,p3,p4) and two control points (c1,c2t). The points p1 and p4 act as previous and the next point respectively. We try to move from point p2 to p3 and draw the path between them. The control points (c1,c2) can be driven from the four points. Once we get the control points we need to use the below code to move to the point and draw Beizer curve.</p>
<pre class="javascript">&nbsp;
CG_EXTERN <span style="color: #000066; font-weight: bold;">void</span> CGContextMoveToPoint<span style="color: #66cc66;">&#40;</span>CGContextRef c, CGFloat x, CGFloat y<span style="color: #66cc66;">&#41;</span>;
CG_EXTERN <span style="color: #000066; font-weight: bold;">void</span> CGContextAddCurveToPoint<span style="color: #66cc66;">&#40;</span>CGContextRef c, CGFloat cp1x,CGFloat cp1y,
                          CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y<span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>Here <strong>CGContext is being used as we do not want to redraw the whole screen every time when the user touches the screen</strong>, instead we save the previous paths traversed in a context and only draw what is needed. For more info you can check this detailed <a href="http://blog.effectiveui.com/?p=8105">blog</a>.</p>
<p><strong>2. UIBezierPath</strong><br />
<a href="https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIBezierPath_class/Reference/Reference.html">UIBezierPath</a> is a wrapper over core graphics that facilitates in drawing different shapes, lines. The entire concept of drawing remains the same as described above but it provides some additional and useful features. Using UIBezierPath you need not to handle context, you can simply initiate a UIBezierPath instance and start adding to this path as the user moves the touches. Here are the  methods for the same. </p>
<pre class="javascript">&nbsp;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>moveToPoint:<span style="color: #66cc66;">&#40;</span>CGPoint<span style="color: #66cc66;">&#41;</span>point;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>addLineToPoint:<span style="color: #66cc66;">&#40;</span>CGPoint<span style="color: #66cc66;">&#41;</span>point;
- <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>addCurveToPoint:<span style="color: #66cc66;">&#40;</span>CGPoint<span style="color: #66cc66;">&#41;</span>endPoint controlPoint1:<span style="color: #66cc66;">&#40;</span>CGPoint<span style="color: #66cc66;">&#41;</span>controlPoint1 controlPoint2:
<span style="color: #66cc66;">&#40;</span>CGPoint<span style="color: #66cc66;">&#41;</span>controlPoint2;
&nbsp;</pre>
<p>Some additional feature that can be had using this method are:</p>
<ul>
<li>Pattern lines (although may not be needed for e-sign use case)</li>
<li>Add a clipping region</li>
<li><strong>Undo/Redo operations</strong></li>
</ul>
<p><strong>3. Open GL</strong><br />
The major drawback with the above problems is that there is a <strong>latency in drawing lines on screen</strong> and the user experience can be quite bad if the line smoothening algo's are not properly used. Also the lines are not as smooth as compared to the method being discussed ahead. In this method a brush texture is created from an image by first drawing the image into a Core Graphics bitmap context. It then uses the bitmap data for the texture drawing. You can see it in action in <a href="https://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html">this</a> Apple example. The drawing is uber smooth as it is being drawn directly in a EAGLContext. I have used this method by using a custom image for the brush texture which gives an feel of a pen rather than a brush.</p>
<p>I hope this blog will give an idea about what can be used for e-sign component. I will soon upload the component that I have created. </p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/09/e-sign-solutions-in-ios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS vs Flex: Do I need more frameworks?</title>
		<link>http://xebee.xebia.in/2012/03/09/ios-flex-frameworks/</link>
		<comments>http://xebee.xebia.in/2012/03/09/ios-flex-frameworks/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 10:01:18 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flex Architectures]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[comparison]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12599</guid>
		<description><![CDATA[Which framework should I choose for this application? - This was the most common question which I used to think before starting any application. But since the time I am working on iOS, I hardly remember when did I ask this. As per Apple's technical guidelines, you 'always' have to stick to the default framework. [...]]]></description>
			<content:encoded><![CDATA[<p>Which framework should I choose for this application? - This was the most common question which I used to think before starting any application. But since the time I am working on iOS, I hardly remember when did I ask this. As per Apple's technical guidelines, you 'always' have to stick to the default framework. Fortunately or unfortunately, the default framework is the only framework made available by Apple. But what is meant by 'only framework'?<span id="more-12599"></span></p>
<p>Consider a following scenario - When you start developing any application, one of the important things is to setup the project structure. For instance, if you use a architecture/framework you need to define couple of folders to place your services, value objects, model, etc. I will be talking about Adobe (now Apache) Flex and Apple's iOS.</p>
<p><b>Apache Flex</b> - You will define folders for all entities that you require in your application (Services, Model, Controllers, Views, etc.), depending upon the framework you are using. For instance, if you are using Cairngorm you will have folders like Command, Event, Delegate, VO, etc. But if you switch to PureMVC for instance, then your folders would be Mediator, Proxy, Business, etc. So based on the framework you define the folder structure.</p>
<p>One thing more to note here is - There is no default framework available for Flex developers which can immediately get them started rather than first creating folders for placing different entities.</p>
<p><b>Native iOS</b> - When you start developing your application by creating a New Project, you will find that some standard files will be generated for you. For any iOS application following are the standards:</p>
<ul>
<li>Every class will have a Header file (with .h extension) and an Implementation file (with .m extension).</li>
<li>Their is an AppDelegate class available which acts as a starting point for your application.</li>
<li>iPhone/iPad is all about screens. So every screen has its own View Controllers (By convention we name it by suffixing 'Controller' to it).</li>
<li>Couple of configuration files (.plist, main.m).</li>
</ul>
<p>So above mentioned files will be always generated for you when you create a new project. iOS application development works simply on MVC pattern. Talking about them individually,</p>
<p>MODEL - There is file with .xcdatamodel that is made strictly to act as your model.</p>
<p>VIEW - There is file with .storyboard extension that is made strictly to hold all your views.</p>
<p>CONTROLLER - As i mentioned above, there are files with .h and .m extension that can act as your controllers.</p>
<p>It is always a good practice to create folder structures and place your entities. But there is a difference in the way Flex and iOS application development works. If you create folders for a flex project, it will be reflected in your hard drive as well. But if you develop application for Native iOS (on Mac of course) and you create folders, you will find that its not reflected on the hard drive.</p>
<p>So you can conclude from the above read that to develop Flex applications you need to have understanding of the framework you want to use, but for native iOS applications Apple gives you a default framework to work with. So for iOS development, i don't see the need of having more frameworks.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/09/ios-flex-frameworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ajax Toolkit capabilities @ Salesforce Home Page Component   &#8230;finally a workaround</title>
		<link>http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/</link>
		<comments>http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/#comments</comments>
		<pubDate>Wed, 07 Mar 2012 03:57:55 +0000</pubDate>
		<dc:creator>Karan Nangru</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Home Page Component]]></category>
		<category><![CDATA[SalesForce]]></category>
		<category><![CDATA[visualforce]]></category>
		<category><![CDATA[ajaxtoolkit]]></category>
		<category><![CDATA[homepagecomponent]]></category>
		<category><![CDATA[salesforce]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11042</guid>
		<description><![CDATA[Astonishing but true - You cannot select/create a Visualforce page as your Salesforce Home Page Component. The component creation dialog only enables creating custom Links, Image/Logo or HTML Area as a Home Page component. To get a glimpse of what Salesforce developers desire, check this out : http://success.salesforce.com/ideaview?id=08730000000Brk4AAC . Why would you anyway want to [...]]]></description>
			<content:encoded><![CDATA[<p><em>Astonishing but true - You cannot select/create a Visualforce page as your Salesforce Home Page Component. The component creation dialog only enables creating custom Links, Image/Logo or HTML Area as a Home Page component. </em></p>
<p>To get a glimpse of what Salesforce developers desire, check this out : <a href="http://success.salesforce.com/ideaview?id=08730000000Brk4AAC" target="_blank">http://success.salesforce.com/ideaview?id=08730000000Brk4AAC</a> .<br />
<span id="more-11042"></span></p>
<p><em><strong><span style="font-size: large;">Why would you anyway want to include a VisualForce page in your home page component?</span></strong></em></p>
<ul>
<li> If not a visualforce page, compromise on the data binding capabilities that Force.com provides.</li>
</ul>
<ul>
<li> Not a UI designer? Its easier for you to create a UI page with the visualforce  UI component kit.</li>
</ul>
<ul>
<li> <span style="text-decoration: underline;"><em><strong>Here's the most critical one:</strong></em><strong><em> </em></strong></span>You cannot use the Ajax Toolkit for accessing user's contextual Salesforce information. This toolkit enables you to make Ajax SOAP calls from your salesforce page that query and retrieve user account specific data that could then be rendered on the page. <em>There is no straightforward mechanism to use this toolkit from an HTML Area type Home Page Component - the component that you would use to create a HTML user interface. Lets analyse why.....</em></li>
</ul>
<p><strong>There are 3 core steps that you need to perform while working with the Ajax toolkit :</strong></p>
<ol>
<li> <em>Connect to the API : </em>If you want to use the toolkit from the home page component, <em>this is where the problem occurs.</em></li>
<li> <em>Embed API calls in Java Script :</em> Once the connection is established, you just need to embed the api call in the js to get the result. For example : "<strong>result = sforce.connection.query("Select Name, Id from User")</strong>" should fetch the Name and Id from the table User</li>
<li>Process Results : One the results are retrieved, display them on the page.</li>
</ol>
<p><strong>Connecting to the API ..... problem Analysis</strong></p>
<p><strong> </strong> Had it been a VisualForce page, you would have just needed the following JS include in your page :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;apex:page&gt;
&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--mce:0--&gt;&lt;/script&gt; ... &lt;/apex:page&gt; </pre>
<p>...this loads the toolkit and creates a global object <strong>sforce.connection</strong>. This object contains all the toolkit APIs, and also manages the Session ID. <em>No other session management is needed while you are working on a Visualforce page. </em> Since a Visual Force Page option is not available for a Home Page Component, you are left with no other option but to use a <em>HTML Area</em> type Home Page Component for creating Home Page UI widgets or for executing your custom JS on each Salesforce page load.</p>
<p>Trying to use the Ajax toolkit in this HTML Area Home Page component by including the connection.js as you do on a visualforce page, i.e.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--mce:1--&gt;&lt;/script&gt;
</pre>
<p>is no success. Despite the fact that the above include statement loads all the api's available to the global object salesforce.connect, a query call like <em><strong>sforce.connection.query("Select Name, Id from User")</strong></em> does not work.</p>
<p>The reason behind this issue is the fact that the implicit session management that is available on a Visualforce page is not available on this HTML Area component. Since the Ajax toolit's managed session id is not available, you cannot use the Ajax toolkit.</p>
<p><em> What this essentially means is that if your business use case evolves around fetching user's contextual information in the Home Page Component, so that on every page load, the home page component displays some user's context specific stuff, then there is no clean, straightforward solution available !! </em></p>
<p><em><strong><span style="font-size: large;">The possible workarounds..... </span></strong></em></p>
<ul>
<li><strong>Iframes :</strong> Create a visualforce page and load this page in the HTML Home page component using an IFrame  ... you can use this approach till the time there is no inteded interaction between the content that is delivered in the IFrame and the containing HTML component. Getting the content of an IFrame to interact with the container can be really cumbersome given the cross domain limitations that an IFrame is viable to.</li>
</ul>
<p><em> If you have global javascript variables in your HTML home component that need to be assigned values read using the Ajax Toolkit APIs, then IFrame's wont work. So what else could be tried...? </em></p>
<p><em><strong>Food for thought.... </strong></em></p>
<p>Apart from Visual Force pages, the Ajax toolkit is also accessible to <em>custom onclick JavaScript links/buttons.</em> All you need to do in a custom onclick link is to specify a login call to salesforce API :</p>
<pre class="brush: xml; title: ; notranslate">

{!requireScript(&quot;/soap/ajax/23.0/connection.js&quot;)} sforce.connection.login(&quot;username&quot;, &quot;password&quot;); ...
</pre>
<p>This way, the Ajax toolkit picks up the endpoint and manages the session ID.</p>
<p><em>(Looking at the script above, you might assume that the same login mechanism should work from javascript of a HTML Area type home page component. Surprisingly it doesn't!!) </em></p>
<p><em><strong><span style="font-size: large;">Finally the workaround that works....</span></strong></em></p>
<p>If you noticed earlier, then the Home Page Component types that Salesforce provides has 3 options :</p>
<ul>
<li>Images</li>
<li>HTML Area</li>
<li>Custom Links<em> </em></li>
</ul>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em></p>
<div id="attachment_12554" class="wp-caption aligncenter" style="width: 310px"><a href="http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/typesofhpc-5/" rel="attachment wp-att-12554"><img src="http://xebee.xebia.in/wp-content/uploads/2012/03/TypesOfHPC2-300x178.png" alt="Home Page Component Types" title="Home Page Component Types" class="size-medium wp-image-12554" width="300" height="178" /></a><p class="wp-caption-text">Home Page Component Types</p></div>
<p></em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em> </em></p>
<p><em>(By this time you should have connected the dots.....) </em><strong>.....<em> you have Custom Links as a Home Page Component type!!</em></strong></p>
<p><strong> Here's what could be done now.....</strong><em><br />
</em></p>
<ul>
<li><em>Create an Execute JavaScript type custom link that OnClick, sets the API's session id into windows session.</em></li>
</ul>
<div id="attachment_12557" class="wp-caption aligncenter" style="width: 310px"><a href="http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/customlink/" rel="attachment wp-att-12557"><img src="http://xebee.xebia.in/wp-content/uploads/2012/03/CustomLink-300x178.png" alt="Execute JavaScript Type Custom Link - Home Page Component" title="Execute JavaScript Type Custom Link - Home Page Component" class="size-medium wp-image-12557" width="300" height="178" /></a><p class="wp-caption-text">Execute JavaScript Type Custom Link - Home Page Component</p></div>
<ul>
<li><em>Create a HTML Area type Home Page Component, that, on every page load, fires the custom link created above (so that the Ajax toolkit's managed session is available in the browser' session) on page load. </em></li>
</ul>
<div id="attachment_12558" class="wp-caption aligncenter" style="width: 310px"><a href="http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/htmlareahomepagecomponent/" rel="attachment wp-att-12558"><img src="http://xebee.xebia.in/wp-content/uploads/2012/03/HTMLAreaHomePageComponent-300x136.png" alt="HTML Area Home Page Component - The Code" title="HTML Area Home Page Component - The Code" class="size-medium wp-image-12558" width="300" height="136" /></a><p class="wp-caption-text">HTML Area Home Page Component</p></div>
<p><em><strong>The Home Page Component Code</strong></em>...</p>
<ul>
<li>To fire the custom link from the HTML area, you could use JQuery in your HTML Area.  Save JQuery source as a resource and load it in your HTML area Home Page Component.</li>
</ul>
<p><em>On document load, search for the created custom link by name and fire it:</em></p>
<pre class="brush: xml; title: ; notranslate">

$(document).ready(function(){

var link = $(&quot;a:contains('YourCustomLinkName')&quot;);
var str =link.attr('href').replace('javascript:','').replace('%28','(').replace('%29',')');
link.onclick = eval(str);
link.trigger('click');
}
</pre>
<ul>
<li>Now that the custom link is fired, you have the salesforce session id in your browser's session. Retrieve this sessionId in the HTML area home page component and set it as the<em> sforce.connection sessionID</em></li>
</ul>
<pre class="brush: xml; title: ; notranslate">

sforce.connection.sessionId = window.sessionIdTest;
</pre>
<p style="text-align: center;"><em><strong>finally!!.... we have access to the Ajax Toolkit APIs</strong></em></p>
<pre class="brush: xml; title: ; notranslate">

sforce.apex.execute(....)
sforce.apex.query(....)

......
</pre>
<blockquote><p>Note: Both the home page components that you just created should be included in your home page layouts. You could do that by visiting: App Setup-&gt;Customize-&gt;Home-&gt;Home Page Layouts under the Setup</p></blockquote>
<blockquote><p><em>A Caveat :<br />
</em></p>
<p><em> </em>On every page load, we are setting the salesforce session id in the browser' session. This is a security constraint. So we should remove this session id from the browser's session in susequent lines once we have set this sessionid in the sforce.connection global object</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/07/ajax-toolkit-capabilities-salesforce-home-page-component-finally-a-workaround/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Five best practices for effective mobile QA</title>
		<link>http://xebee.xebia.in/2012/03/02/five-best-practices-for-effective-mobile-qa/</link>
		<comments>http://xebee.xebia.in/2012/03/02/five-best-practices-for-effective-mobile-qa/#comments</comments>
		<pubDate>Fri, 02 Mar 2012 06:35:02 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Testing]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12454</guid>
		<description><![CDATA[In today’s world, ever increasing inclination towards mobile devices and applications has provided great prospects for enterprises to move their business in mobile world. As mobile technology lets the customers stay connected for almost all the time, enterprises are moving beyond the desktop world to keep attuned to their customer needs. But development of mobile applications [...]]]></description>
			<content:encoded><![CDATA[<p>In today’s world, ever increasing inclination towards mobile devices and applications has provided great prospects for enterprises to move their business in mobile world. As mobile technology lets the customers stay connected for almost all the time, enterprises are moving beyond the desktop world to keep attuned to their customer needs. But development of mobile applications with an impeccable user interface and  functionality for highly fragmented mobile market is in itself an ordeal. Thus quite evidently mobile application development has become a booming field in the IT industry. Few days back, I met with a guy who is mobile QA from long time. I discussed with him few of the best practices which shall be followed for functional testing of mobile applications. So through this blog I want to share few of those practices which should be followed by mobile QA while doing testing for any mobile application.<span id="more-12454"></span></p>
<p><b>1. Emulators can be used for limited functionality testing only</b></p>
<p>Emulators are just mimic to actual devices in terms of functionality. They can never be treated as substitutes for actual devices. For a start, device emulators and simulators can act as an stepping stone in testing mobile applications but totally relying on them can lead to catastrophe. One of the prime examples where emulators can be used is testing design level implementations, for instance if the desired icons are on a specific screen or not. The biggest limitation of emulators is that they do not work on real network and are not prone to real world interrupts and for this reason, we need real devices to test applications. For instance emulators can be used in location based apps by simulating a route, but actual interrupts occurring on these routes can only be tested using real devices.</p>
<p><b>2. Field testing is uber important</b></p>
<p>Mobile field testing provides testing assurance of the mobile device’s workability in the actual field. This will ensure that the device works not only in the Static field environment but also in the dynamic field environment. Few years back, there was one research conducted in Helsinki where users were given 10 different tasks to perform on application at different locations. Although that application was already tested before in their laboratories but during field testing users found many different functional bugs due to signal discrepancies and other interrupts.</p>
<p><b>3. Never assume one application works for all</b></p>
<p>Market is full of devices having different configurations, operating systems, features and assuming if things are working fine on one device  then they will be fine on every device is not a good practice at all. Every device has its own characteristics due to which some features of application may fit well in one device and may not in other device. For example:- Samsung and Nokia might come up with any native application solution. Though the basic functionality is the same for both the apps but the look and feel, form factor of the applications might be largely different from each other.</p>
<p><b>4. Keep interrupts in mind while mobile app testing</b></p>
<p>Wireless networks are prone to functional and network interrupts. Lets take an example where user is disbursing using his debit card and in between that transaction there is a signal loss for fraction of seconds. In that case application should be able to intimate user about signal loss or should  be able to resume from where signal was lost then his transaction should be completed  after this interrupt is over. This was just one example of interrupt. There can be other types of interrupts like receiving message, receiving calls which are uncontrollable. The concept of interrupts is important in every type of applications and they should be tested with extra care specially in case of financial applications like mobile banking.</p>
<p><b>5. Give special focus on usability</b></p>
<p>Good user interface can play crucial role in software industry.Any software product can be made with provided set of functionality but an intelligent user interface can make a product hit. Intelligent user  interface means it should be easily used by end-users. There are unique features in usability of a mobile application when compared to normal desktop application. Some of the examples are mentioned below:-</p>
<p>1. Mobile devices are designed for both left handed and right handed people. In that case, QA should focus on convenience perspective so that mobile applications can be used by both set of people.</p>
<p>2. Mobile applications should be tested according to phone orientation as mobile applications can be viewed either in landscape or portrait format.  Here, QA should focus on testing on different screen resolution as well as different orientation format.</p>
<p>3. In addition to usability testing in different orientation,  usability should also be tested for touchscreen screens, qwerty keypads,etc. Example : sufficient usability testing should be performed to ensure that the keyboard is visible only when it is required while inputting text, numbers, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/02/five-best-practices-for-effective-mobile-qa/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Executing Selenium/WebDriver tests remotely using Maven and Jenkins</title>
		<link>http://xebee.xebia.in/2012/03/01/executing-seleniumwebdriver-tests-remotely-using-maven-and-jenkins/</link>
		<comments>http://xebee.xebia.in/2012/03/01/executing-seleniumwebdriver-tests-remotely-using-maven-and-jenkins/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 18:36:38 +0000</pubDate>
		<dc:creator>Rajneesh</dc:creator>
				<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test Auotmation]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[RemoteWebDriver]]></category>
		<category><![CDATA[Test Automation]]></category>
		<category><![CDATA[testing tools]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12487</guid>
		<description><![CDATA[Recently our team created a nifty selenium test suite for testing a salesforce.com app we developed. We used TestNG framework for writing tests along with the latest and greatest selenium available out there which is WebDriver. In case you want to know why we chose web driver over RC,read this. Since we planned to execute [...]]]></description>
			<content:encoded><![CDATA[<p>Recently our team created a nifty selenium test suite for testing a salesforce.com app we developed. We used <a href="http://testng.org/doc/index.html">TestNG </a> framework for writing tests along with the latest and greatest selenium available out there which is <a href="http://code.google.com/p/selenium/wiki/GettingStarted">WebDriver</a>. In case you want to know why we chose web driver over RC,read <a href="http://xebee.xebia.in/2012/02/07/selenium-web-driver-or-rc-decide-yourself/">this</a>. Since we planned to execute the tests on a remote windows machine triggered from our Jenkins machine (linux), we leveraged the capabilities of <a href="http://code.google.com/p/selenium/wiki/RemoteWebDriver">RemoteWebdriver</a>. Eventually we wanted to be able to run the tests with our Continuous Integration environment which meant that the tests are build on Jenkins (linux) with maven and executed on dedicated windows machine remotely.<br />
<span id="more-12487"></span><br />
Following are the key objectives that we identified to make it happen:</p>
<p>1. Configure/trigger the tests in way so that we can put them into the Jenkins machines as build jobs.</p>
<p>2. Use maven targets to be able to force a browser type at build time (for example: mvn integration-test -DBrowserType=chrome). Using this we can create multiple Jenkins jobs for execution of selenium tests against each browser.</p>
<p>3. Make remote execution capability configurable along with the location (IP and port) of the selenium server (if Remote Execution is true) so that we can easily switch server (if required) or use multiple servers simultaneously executing test against different browsers.</p>
<p>4. Run the tests on multiple browsers like FF,IE and chrome.</p>
<p>With the help of this blog I intend to share the way we set about to achieve our objectives. Here I am assuming that the reader is aware of basic concepts of selenium and maven.</p>
<p>As a first step we created a maven project for the test suite and added the required dependencies to the POM file. We prepared a remote windows virtual machine with all the required browsers and downloaded the selenium-server-standalone-{VERSION}.jar on it.</p>
<p>In our framework, we added a few system properties in our BaseTest.java (A helper class used by all tests to instantiate a WebDriver/RemoteWebDriver instance).</p>
<p><code><span style="color: #993300;">String BrowserType = System.getProperty("BrowserType");</span><br />
<span style="color: #993300;"> String RemoteExecution = System.getProperty("RemoteExecution");</span><br />
<span style="color: #993300;"> String RemoteUrl = System.getProperty("RemoteUrl");</span><br />
</code></p>
<p>Next, we made the invocation of a browser type and remote execution capability dependent on these property values in our BaseTest.java.</p>
<p><span style="color: #000080;"><code>if(!<strong>RemoteExecution</strong>.equals("true")) <span style="color: #333333;">// remote execution is false</span></code></span><br />
<span style="color: #333333;"> <code>{</code></span><br />
<span style="color: #000080;"> <code>if(<strong>BrowserType</strong>.equals("firefox"))</code></span><br />
<span style="color: #000080;"> <code>{</code></span><br />
<span style="color: #000080;"> <code>WebDriver driver = new FirefoxDriver(); <span style="color: #333333;">// Create a new instance of firefox driver</span></code></span><br />
<code><span style="color: #000080;">}</span><br />
<span style="color: #000080;"> else if</span><br />
<span style="color: #000080;"> {</span><br />
<span style="color: #000080;"> code for ie and chrome goes here</span><br />
<span style="color: #000080;"> }</span><br />
<span style="color: #000080;"> else                              <span style="color: #333333;"> //remote execution is true</span></span><br />
<span style="color: #000080;"> <code> if(<strong>BrowserType</strong>.equals("firefox"))</code></span><br />
<span style="color: #000080;"> {</span><br />
<span style="color: #000080;"> WebDriver driver = new RemoteWebDriver(newURL(<strong>RemoteUrl</strong>+"/wd/hub"),DesiredCapabilities.firefox());</span><br />
<span style="color: #333333;"> //Create a new instance of RemoteWebDriver with the  remote server url</span><br />
<span style="color: #000080;"> }</span><br />
<span style="color: #000080;"> else if</span><br />
<span style="color: #000080;"> {</span><br />
<span style="color: #000080;"> code for ie and chrome goes here</span><br />
<span style="color: #000080;"> }</span><br />
</code></p>
<p>Finally, we configured the maven-surefire-plugin to run the tests in integration-test phase. In the plugin execution we added the parameter 'systemPropertyVariables' to pass values for the system properties defined above at build time.</p>
<p><span style="color: #000080;">&lt;plugin&gt;</span><br />
<span style="color: #000080;"> &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br />
<span style="color: #000080;"> &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br />
<span style="color: #000080;"> &lt;configuration&gt;</span><br />
<span style="color: #000080;"> &lt;skip&gt;true&lt;/skip&gt;</span><br />
<span style="color: #000080;"> &lt;/configuration&gt;</span><br />
<span style="color: #000080;"> &lt;executions&gt;</span><br />
<span style="color: #000080;"> &lt;execution&gt;</span><br />
<span style="color: #000080;"> &lt;phase&gt;integration-test&lt;/phase&gt;</span><br />
<span style="color: #000080;"> &lt;goals&gt;</span><br />
<span style="color: #000080;"> &lt;goal&gt;test&lt;/goal&gt;</span><br />
<span style="color: #000080;"> &lt;/goals&gt;</span><br />
<span style="color: #000080;"> &lt;configuration&gt;</span><br />
<span style="color: #000080;"> &lt;skip&gt;false&lt;/skip&gt;</span><br />
<span style="color: #000080;"> <strong> &lt;systemPropertyVariables&gt;</strong></span><br />
<span style="color: #000080;"> <strong> &lt;BrowserType&gt;firefox&lt;/BrowserType&gt;</strong></span><br />
<span style="color: #000080;"> <strong> &lt;RemoteExecution&gt;false&lt;/RemoteExecution&gt;</strong></span><br />
<span style="color: #000080;"> <strong> &lt;RemoteUrl&gt;http://127.0.0.1:4444&lt;/RemoteUrl&gt;</strong></span><br />
<span style="color: #000080;"> <strong> &lt;/systemPropertyVariables&gt;</strong></span><br />
<span style="color: #000080;"> &lt;suiteXmlFiles&gt;</span><br />
<span style="color: #000080;"> &lt;suiteXmlFile&gt;${project.build.directory}/test-classes/testng.xml&lt;/suiteXmlFile&gt;</span><br />
<span style="color: #000080;"> &lt;/suiteXmlFiles&gt;</span><br />
<span style="color: #000080;"> &lt;/configuration&gt;</span><br />
<span style="color: #000080;"> &lt;/execution&gt;</span><br />
<span style="color: #000080;"> &lt;/executions&gt;</span><br />
<span style="color: #000080;"> &lt;/plugin&gt;</span></p>
<p>Now once we had the server running on the remote VM (using java -jar selenium-server-standalone-{VERSION}.jar) we were able to build and execute our tests using the following maven command.<br />
<code><br />
<span style="color: #993300;">mvn integration-test -DBrowserType=firefox -DRemoteExecution=true -DRemoteUrl=http://xyz.com:4444</span><br />
</code><br />
Now we already achieved our objective 1,2 and 3 but not 4. We ran into issues while running the tests on chrome remotely. We encountered an exception with the message 'The path to the chrome driver executable must be set by the webdriver.chrome.driver system property'. The solution to this is already discussed on <a href="http://stackoverflow.com/questions/6921170/how-to-build-remote-webdriver-for-chrome">stackoverflow</a>. In nutshell, you need to have the chromedriver.exe on the remote machine (where the selenium server is hosted) and run the selenium server on the remote machine with the following argument<br />
<code><br />
<span style="color: #993300;"> java -Dwebdriver.chrome.driver="path-to-chromedriver.exe" -jar selenium-server-standalone.jar</span><br />
</code><br />
That's it. This enabled us to run our tests on any remote machine against a specific browser with ease in continuous integration environment. It would be great to hear what alternative approaches you have used to solve something similar.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/01/executing-seleniumwebdriver-tests-remotely-using-maven-and-jenkins/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>NFC in Android</title>
		<link>http://xebee.xebia.in/2012/03/01/nfc-in-android/</link>
		<comments>http://xebee.xebia.in/2012/03/01/nfc-in-android/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 12:51:22 +0000</pubDate>
		<dc:creator>Paramvir Singh</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[mCommerce]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[NFC]]></category>
		<category><![CDATA[android development]]></category>
		<category><![CDATA[android wallet]]></category>
		<category><![CDATA[Android4.0]]></category>
		<category><![CDATA[mobile apps]]></category>
		<category><![CDATA[Near Field Communication]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12262</guid>
		<description><![CDATA[Near Field Communication or NFC is one of the hottest and most talked about feature in present day smartphones. The reason it is being so popular with smartphone users is that it is intuitive and easy to use. Also, NFC is being considered as one of the most appealing future technology in Mobile domain. Invented [...]]]></description>
			<content:encoded><![CDATA[<p>Near Field Communication or NFC is one of the hottest and most talked about feature in present day smartphones. The reason it is being so popular with smartphone users is that it is intuitive and easy to use. Also, NFC is being considered as one of the most appealing future technology in Mobile domain. Invented by NXP and Sony jointly in 2002, NFC was first adopted by Nokia for their smartphones to make mobile payments easy for their users. Now it is being supported and encouraged by <a target="_blank" title="NFC forum" href="http://www.nfc-forum.org/home/">NFC -Forum</a>, which has nearly 160 members including mobile manufaturers and developers. The member list of this forum boasts of major players like Samsung, Motorola, Google, Sony Ericsson and Microsoft among others.</p>
<p><span id="more-12262"></span>Google is particularly ambitious about this feature in its latest range of Android devices. Here is a summary of recent efforts by Google to make NFC popular among users and developers:</p>
<ul>
<li><strong>NFC API's for developers: </strong>In OS version 2.3 (Gingerbread) of Android, Google introduced NFC support and also exposed API's for developers to create applications for NFC enabled Android devices. Using this API's, "Developers can create new applications that offer proximity-based information and services to users, organizations, merchants, and advertisers".</li>
<li><strong>Google Wallet: </strong>Google's ambitious project in the area of mCommerce. This application for smart-phones empowers the devices to act as a virtual wallet which store user's credit card and other payment information safely. Users can use their mobile devices at stores to pay and benefit from offers provided by Google directly. The transaction will happen by tapping the mobile device at NFC readers installed at point of sales.</li>
<li><strong>Android Beam: </strong>In Android 4.0(Ice-cream Sandwich), a new application called "Beam" is introduced. This application makes it more easy and intuitive for users to share contacts, apps, songs and videos between two Android devices using NFC. Beam uses NFC Android API's which are fully exposed to developers.</li>
</ul>
<p>Let's dig into the important API’s and technical details we can use to make our application NFC enabled. Two terms frequently used for NFC are:</p>
<ul>
<li><strong>NFC Tag: </strong>The important characteristic of NFC is that an NFC powered mobile device can read and write passive targets. These passive targets are usually NFC tags which may be very small and simple and can be in the form of small stickers, movie poster or visting cards.</li>
<li><strong>NFC device:</strong> NFC device is the powered device which can read or write another NFC device or tag. In our case, it is NFC enabled Android phone.</li>
</ul>
<p><b>Detecting an NFC tag:</b></p>
<p>NFC device detects a NFC tag or other device when they come in close proximity(distance &lt; 4cm). On detecting the target, the device opens up the desired Activity to handle the required job. For instance, when a video is to be shared, Youtube application opens up and when user wants to share an app, Android market gets opened. If the device detects a tag with a link, it redirects to that link on browser.</p>
<p>This astute process of detecting a target, extracting information from that target and then pinpointing the Activity to accomplish the intended task without user intervention is called "<strong>Tag dispatching</strong>". Tags contain small amount of data in a special format called NDEF (NFC Data Exchange Format) standardized by NFC forum. This data and its MIME type is exchanged from the target to the device. On device, this data is further attached to an Intent which is sent to the interested applications. The applications which intend to handle this type of data will have to register appropriate Intent-filter.</p>
<p>We deal with following classes:</p>
<ol>
<li><strong>NdefMessage: </strong>Container class for storing the NDEF data. It contains a group of records which  contain the actual payload data, the type of data and other information about it.</li>
<li><strong>NdefRecord: </strong>Represents the records in NdefMessage. These records contain different fields to identify the required information about the data like format, type, ID and the actual payload. One of the field is <strong>Type Name Format (TNF)</strong> which is used to detect the MIME type or URI of the NdefMessage. When the data is transferred from target to receiver,the first NdefRecord is looked up for getting information about the whole NdefMessage. After that an Intent is created with action <strong>ACTION_NDEF_DISCOVERED </strong>and the MIME type and URI is attached to it.</li>
</ol>
<p>The appropriate application is chosen to do the job on the bases of intent and the data attached to it. The applications willing to handle the NFC tag detection declare intent filter in their manifest file:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;intent-filter&gt;

&lt;action android:name=&quot;android.nfc.action.NDEF_DISCOVERED&quot;/&gt;

&lt;category android:name=&quot;android.intent.category.DEFAULT&quot;/&gt;

&lt;data android:scheme=&quot;http&quot;

android:host=&quot;xebia.in&quot;

android:pathPrefix=&quot;/company.html&quot; /&gt;

&lt;/intent-filter&gt;
</pre>
<p>This Intent filter will filter intent generated on detecting a tag having a URI as data and will result in opening www.xebia.in/company.html in browser.</p>
<p style="text-align: center;"><img height="500" width="620" src="http://xebee.xebia.in/wp-content/uploads/2012/02/Tag_dispatching.png" title="Tag_dispatching" class="aligncenter size-full wp-image-12284" /></p>
<p><strong>Extracting required data from the NFC intent:</strong></p>
<p>When the selected activity opens up after tag dispatch, required data is extracted from the incoming intent to proceed further. This data is contained in "extras" of the intent:</p>
<p>1<strong>.  EXTRA_TAG: </strong>The extra for containing payload data and tag technology information bound into a  Tag object.</p>
<pre class="brush: java; title: ; notranslate">
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
</pre>
<p>2. <strong>EXTRA_NDEF_MESSAGES: </strong>The extra for containing all the NDEF messages in Tag object. These messages are obtained in an Array of Parcelable objects.</p>
<pre class="brush: java; title: ; notranslate">

public void onResume() {
	super.onResume();
	Intent parentIntent = getIntent();
	if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(parentIntent.getAction())){
		Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
		if (rawMsgs != null) {
			msgs = new NdefMessage[rawMsgs.length];
			for (int i = 0; i &lt; rawMsgs.length; i++){
				msgs[i] = (NdefMessage) rawMsgs[i];
			}
		}
	}
}
</pre>
<p><strong>Using Beam to push data:</strong></p>
<p>Beam can be used to push data from an application while it is running in foreground. Beam gets activated when the "beaming" device is put in physical contact with another device for a moment. At this instance, user is prompted for confirmation in special Beam UI and style. Any third party application can integrate Beam by using <strong>setNdefPushMessage() </strong>on <strong>NfcAdapter</strong>. This method will handle the beaming of data when devices come in required distance.</p>
<p><strong>CreateNdefMessageCallback </strong>interface is implemented to add Ndef push functionality in the Activity. This implementation requires following method to be defined:</p>
<pre class="brush: java; title: ; notranslate">
public NdefMessage createNdefMessage(NfcEvent event) {
String message = &quot;This is NFC message&quot;;
NdefRecord mimeRecord = createMimeRecord(&quot;application/param.android.sample.beam&quot;,
message.getBytes());
NdefRecord appRecord = NdefRecord.createApplicationRecord(&quot;param.android.sample.beam&quot;);
NdefRecord[] ndefRecords = new NdefRecord[] {
mimeRecord,
appRecord
};
NdefMessage ndefMessage = new NdefMessage(ndefRecords);
return ndefMessage;
}

public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
byte[] mimeBytes = mimeType.getBytes(Charset.forName(&quot;US-ASCII&quot;));
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
return mimeRecord;
}
</pre>
<p>Here two NdefRecords are being transferred. One record represents a text message and other is <strong>Android Application Record. </strong>This may be included to get guarantee that only this application will be opened up on detecting NFC device with this intent.</p>
<p>In onCreate method a reference to to an NFC adapter is created and a callback is set to it:</p>
<pre class="brush: java; title: ; notranslate">
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Check for available NFC Adapter
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, &quot;NFC is not available&quot;, Toast.LENGTH_LONG).show();
finish();
return;
}
// Register callback
nfcAdapter.setNdefPushMessageCallback(this, this);
}
</pre>
<p>The developers can use basic NFC API's to support any kind of tags and NFC data or they can simply leverage the benefits of in built Beam application to use NFC power. Interesting thing is that these API's are really simple to use and working with NFC is nothing less than fun.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/03/01/nfc-in-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Distributed Pomodoro</title>
		<link>http://xebee.xebia.in/2012/02/29/distributed-pomodoro/</link>
		<comments>http://xebee.xebia.in/2012/02/29/distributed-pomodoro/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 18:20:08 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Human Behaviour]]></category>
		<category><![CDATA[thought]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12418</guid>
		<description><![CDATA[Pomodoro is a simple technique for time management. Here is a link if you would like to know more about Pomodoro.http://www.pomodorotechnique.com/ . Here at Xebia we have a Open work area.This blog talk about one of the problems that we faced while working in Open work area and how we solved it.Our team was following Scrum [...]]]></description>
			<content:encoded><![CDATA[<p>Pomodoro is a simple technique for time management. Here is a link if you would like to know more about Pomodoro.<a target="_blank" href="http://www.pomodorotechnique.com/">http://www.<wbr></wbr>pomodorotechnique.com/</a> . Here at Xebia we have a Open work area.This blog talk about one of the problems that we faced while working in Open work area and how we solved it.Our team was following Scrum with a two weeks sprints.This was an ongoing project for last 6 months which had a team of 2.Project was recently just scaled up to 8 team members. Which means there were 6 team members who had joined new.<br />
<span id="more-12418"></span></p>
<div>
<div>
<div>Following are the challenges that we (new guys on team) faced</div>
<div>
<ul>
<li>No domain knowledge</li>
<li>Less idea about the latest frameworks used in project.</li>
<li>No idea about the architecture of the current project.</li>
</ul>
</div>
</div>
<div></div>
<div>
<div>With the above challenges one of the common point of Retrospective was we were disturbing</div>
</div>
<div>the 2 guys who have been in the project for the longest time. This is one of the disadvantages of this open work enviornment. You can be disturbed every easily. "Get the image for open work area". If someone has a questions he can just interrupt you when you are actually in the zone. This further affected the productivity of the 2 guys.</div>
<p>&nbsp;</p>
<div>To solve this problem Distributed Pomodoro was the solution that we came up with. Like pomodoro is a time management technique for one to be more productive and focused on work.The idea was simple We all have our clocks synched. We formed a protocol that we all work for 40 minutes and take a break for 10 minutes.Use this 10 minutes to discuss questions if we have , take a break , etc. Basically you can make all the noise you want to in a room in this 10 min.</div>
<div></div>
<div>This all looked good but there were a lot of challenges in executing this</div>
<div>
<ul>
<li>Someone has to keep time.</li>
<li>Not everyone starts the day together.</li>
</ul>
</div>
<p>&nbsp;</p>
<div>To solve the above challenge I have made a simple application based on P2P Solution. The application creates a virtual group</div>
<div>on LAN. Everyone can join the group in the start of the day.Anyone can start the clock. Once the clock is started it will start a clock on everyone's laptop. Once 40 mins is over there will be a loud alarm.If someone joins in the middle he will have the current clock timings synchronized on his laptop.</div>
<p>&nbsp;</p>
<div>This is a simple application that works on P2P based network.Having P2P message for communicating and synchronizing everyone connected.Also because of this application not only one person but the whole team follows Pomodoro.With some practicing this will help increase the teams productivity to good extend.Here is the <a href="http://code.google.com/p/team-pomodoro/source/checkout">Source Code</a></div>
<p>of the application. Enjoy!!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/29/distributed-pomodoro/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>To Err is a Developer</title>
		<link>http://xebee.xebia.in/2012/02/28/to-err-is-a-developer/</link>
		<comments>http://xebee.xebia.in/2012/02/28/to-err-is-a-developer/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 08:05:13 +0000</pubDate>
		<dc:creator>Shruti Khattar</dc:creator>
				<category><![CDATA[Designing]]></category>
		<category><![CDATA[Project Development Methodologies]]></category>
		<category><![CDATA[Quality]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Development practices]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12140</guid>
		<description><![CDATA[There is nothing like “flawless” in this world. Even the renowned or self proclaimed “Perfectionists” are not immaculate. Errors, mistakes, bugs are part of life of a developer. They can be equated to the quadrants of the 'Johari Window'.  In terms of design, code, testing, security measures, providing access and information, there can be both [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;" align="CENTER"><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2">There is nothing like “flawless” in this world. Even the renowned or self proclaimed “Perfectionists” are not immaculate. Errors, mistakes, bugs are part of life of a developer. They can be equated to the quadrants of the 'Johari Window'.  In terms of design, code, testing, security measures, providing access and information, there can be both technical as well as non technical mistakes. I would like to discuss some of the common mistakes and loopholes that the developers are prone to commit even if they score very high on the proficiency level.</span></span></span></p>
<p align="CENTER"><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2"><span id="more-12140"></span></span></span></span></p>
<ul>
<li><strong><span style="font-family: arial, helvetica, sans-serif; font-size: small;">In a design, individual elements do not matter, big picture does: </span></strong><span style="font-family: arial, helvetica, sans-serif; font-size: small;">It can be difficult to separate an eye for design with the ability to design. A captivating design is simple and attractive and not. Because of prejudice and bias, designers are not able to distinguish what should be included in the existing design and what should not be. They should not be tempted to use anything that does not integrate well with the existing design. It is absolutely not worth over committing the details and wasting time on it</span></li>
</ul>
<ul>
<li><strong><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2">Demanding Perfection in first attempt: </span></span></span></strong><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Too many people want everything perfect before they go live. While the coder makes all the efforts to get everything perfect, the Internet changes, someone presents  the same idea. “Getting there first” is often more important than “Getting there perfect” Apply the 80-20 rule to projects instead. It is better to wait to spend 80% of your resources polishing that last 20% once you've proven the stability of your site.</span></li>
</ul>
<ul>
<li><strong><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2">Not enough Unit Testing : </span></span></span></strong><span style="font-family: arial, helvetica, sans-serif; font-size: small;">It is the confidence biased towards the self written code that refrains the developer. It becomes hard to think of the scenarios and inputs that can break their code. Thus, the developer is not able to enhance his code to make it more rich and robust. Also, they get complacent when their code has to be reviewed by someone else and then is functionally checked by the QA.  A developer has to get into a different mindset keeping in consideration that all checks cannot be and ideally should not be incorporated into the code.  The method(s) has to be as generic as possible to allow extensibility  and it should be tested with respect to all the specifications. Ideally, even for a minor bug fix, a unit test case should be written.</span></li>
</ul>
<ul>
<li>
<p align="LEFT"><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2"><b>Exceptions</b></span></span></span></p>
<p align="LEFT"><em style="font-family: arial, helvetica, sans-serif; font-size: small;"><span color="#000000"><span face="Arial, sans-serif"><span size="2">Surpassing 	and suppressing exceptional conditions</span></span></span></em></p>
<p align="LEFT"><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Sometimes, the programmer is not specific enough in the type of exception they catch. Catching too general an exception type means that they may be inadvertently dealing with particular exceptions that would be best left to other code, higher up the call chain. Tune your exception catch blocks to be as specific as possible. The second mistake is more detrimental-the programmer doesn't want any exceptions leaving their code and so catches them all and ignores them. This is known as the empty catch block. Also,don't absorb exceptions with no logging and operation. Ignoring exceptions will save that moment but will create a chaos for maintainability later</span></p>
<p align="LEFT"><em style="font-family: arial, helvetica, sans-serif; font-size: small;"><span color="#000000"><span face="Arial, sans-serif"><span size="2"><span face="'times new roman', times" size="3">Inter wining Exception Handling and Business Logic</span></span></span></span></em></p>
<p align="LEFT"><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Don't manage business logic with exceptions. Use conditional statements instead. If a control can be done with if-else statement clearly, don't use exceptions because it reduces readability and performance  (e.g. null control, divide by zero control).eg. Null control with conditionals is not an alternative to catching NullPointerException. If a method may return null, control it with if-else statement. If a return may throw NullPointerException, it should be caught.</span></p>
</li>
</ul>
<ul>
<li><span style="font-family: arial, helvetica, sans-serif; font-size: small;"><strong><span style="color: #000000;" color="#000000"><span face="Arial, sans-serif"><span size="2"><b>Closing 	the source: </b></span></span></span></strong></span><span style="font-family: arial, helvetica, sans-serif; font-size: small;">One of the trickiest challenges for any company is determining how much to share with the people who use the software. Often the code itself grows more modular and better structured as others recompile the program and move it to other platforms. Just opening up the code forces you to make the info more accessible, understandable, and thus better. As they make the small tweaks to share the code, they feed the results back into the code base. Due to the trade off, developers are mostly indecisive of it.</span></li>
</ul>
<ul>
<li><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2"><b>Playing 	it fast and loose: </b></span></span></span><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Even though the developers are well aware of the possible security breaches, still not much is done to prevent them. Some of them are:</span></li>
</ul>
<p><span color="#000000" style="font-family: arial, helvetica, sans-serif; font-size: small;"><span face="Arial, sans-serif"><span size="2">1. <i>SQL 	injection or OS injection</i></span></span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif; font-size: small;"><span color="#000000"><span face="Arial, sans-serif"><span size="2">2. <i style="font-family: 'times new roman', times; font-size: medium;">Cross-site 	scripting</i></span></span></span><span color="#000000" style="color: #000000;"><span face="Arial, sans-serif"><span size="2"> : By not validating the input that is given dynamically, the 	developer might invite these problems like compromising on data 	integrity, cookies can be set and read, user input can be 	intercepted. Malicious scripts can be executed by the client in 	the context of the trusted source.</span></span></span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif; font-size: small;"><span style="color: #a2427c;" color="#a2427c"><span face="Arial, sans-serif"><span size="2"><i>3. I</i></span></span></span><span color="#000000"><span face="Arial, sans-serif"><span size="2"><i>mproper 	release of resources</i></span></span></span><span color="#000000"><span face="Arial, sans-serif"><span size="2">:</span></span></span><span style="color: #a2427c;" color="#a2427c"><span face="Arial, sans-serif"><span size="2"> </span></span></span><span style="color: #333333;" color="#333333"><span face="Arial, sans-serif"><span size="2">When</span></span></span><span style="color: #333333;" color="#333333"><span face="Arial, sans-serif"><span size="2"> the system resources such as memory, files, cookies, data 	structures, sessions, communication pipes, and so on have reached 	their end-of-life, they are disposed off. Attackers can exploit 	improper shutdown to maintain control over those resources well 	after you thought you got rid of them. They  may sift through the disposed off  items, looking for sensitive data. They can potentially be 	useful to them.</span></span></span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif; font-size: small;"><span color="#000000" style="color: #000000;"><span face="Arial, sans-serif"><span size="2"><i>4. Use 	of insufficiently random values:</i></span></span></span><span color="#333333" style="color: #333333;"><span face="Arial, sans-serif"><span size="2">The developer  may depend on randomness without even knowing it, such as when 	generating session IDs or temporary file names. Pseudo-Random Number 	Generators (PRNG) are commonly used, but a variety of things can go 	wrong. Once an attacker can determine which algorithm is being used,  they can guess the next random number often enough to launch a 	successful attack after a relatively small number of tries.</span></span></span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif; font-size: small;"><span color="#000000" style="color: #000000;"><span face="Arial, sans-serif"><span size="2"><i>5. Client 	side security: </i></span></span></span><span color="#000000" style="color: #000000;"><span face="Arial, sans-serif"><span size="2">The 	developer should not</span></span></span><span color="#000000" style="color: #000000;"><span face="Arial, sans-serif"><span size="2"><i> </i></span></span></span><span color="#333333" style="color: #333333;"><span face="Arial, sans-serif"><span size="2">trust 	the client to perform security checks on behalf of your server. 	Attackers can reverse engineer your client and write their own 	custom clients. The consequences will vary depending on what the security checks are protecting, but some of the more common targets 	are authentication, authorization, and input validation.</span></span></span></span></p>
<p><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2">Developers make such errors for two main reasons. First, they may be operating under the mistaken assumption that a given function is too obscure to be vulnerable, they fail to grasp the extent to which attackers may be willing to analyze their application flows to find weaknesses. More often, however, they simply haven't considered how important a given function might be to the overall security of their application. As applications grow more complicated and their functions are distributed across multiple systems and resources, it's particularly easy to lose track of the big security picture.</span></span></span></p>
<ul>
<li><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2"><b>Delegating 	too much to frameworks : </b></span></span></span><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Sometimes the magic tools lead only to confusion. By abstracting functionality and assuming what we want, frameworks can all too often leave developers at a loss for what's gone wrong in their code. This is where the developer gets bounded within the limitations of framework. Framework should be chosen only if it has a utility, and is inevitable in the project, keeping in mind that it should not tie you down and restrict you to extend or customize your code.</span></li>
</ul>
<ul>
<li><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2"><b>Reinventing 	the wheel : </b></span></span></span><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Writing your own libraries just because you think you know a better way to code can come back to haunt you. So being obsessed with writing your own logic without the help of an inbuilt function is like wasting time and efforts. Accepting and using libraries that are ready made, freely available and easy to use which solve your purpose is a stitch in time saves nine.</span></li>
</ul>
<p><span style="color: #000000; font-family: arial, helvetica, sans-serif; font-size: small;" color="#000000"><span face="Arial, sans-serif"><span size="2">This is not an exhaustive list of the mistakes. But the ones which are the major ones. The other side of mistakes is that they are developer friendly. They act as a driver to push them get better and better and also lead to useful findings and discoveries. There would be no errors or exceptions if nobody ever had an encounter with them <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  The important thing is to accept them with an open mindset, deal and resolve if it is not possible to eliminate it.</span></span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Arial, sans-serif"><span size="2"><br />
</span></span></p>
<p align="CENTER">&nbsp;</p>
<div dir="ltr" id=":xh"></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/28/to-err-is-a-developer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using Spring 3.1 Profiles To Achieve PaaS Portability</title>
		<link>http://xebee.xebia.in/2012/02/27/using-spring-3-1-profiles-to-achieve-paas-portability/</link>
		<comments>http://xebee.xebia.in/2012/02/27/using-spring-3-1-profiles-to-achieve-paas-portability/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 17:21:04 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Cloud Foundry]]></category>
		<category><![CDATA[openshift]]></category>
		<category><![CDATA[cloudfoundry]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Roo]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12349</guid>
		<description><![CDATA[Spring 3.1 release introduced a much awaited feature called Profiles which allows you to register different beans in different environments. In this blog we will take a look at how we can use profiles feature to run the same application without any code change in both OpenShift Express and Cloud Foundry. Creating a sample Spring [...]]]></description>
			<content:encoded><![CDATA[<p>Spring 3.1 release introduced a much awaited feature called Profiles which allows you to register different beans in different environments. In this blog we will take a look at how we can use profiles feature to run the same application without any code change in both OpenShift Express and Cloud Foundry.<span id="more-12349"></span></p>
<p><strong>Creating a sample Spring MongoDB Application</strong></p>
<p>I will use Spring Roo to create a simple bookshop application. Fire up the Roo shell and execute the following commands.</p>
<pre class="brush: plain; title: ; notranslate">
project --topLevelPackage com.xebia.bookshop --projectName bookshop
mongo setup --databaseName bookshop --host localhost --port 27017
entity mongo --class ~.domain.Book --testAutomatically --identifierType org.bson.types.ObjectId
field string --fieldName title --notNull
field string --fieldName author --notNull
field number --type double --fieldName price --notNull
repository mongo --interface ~.repository.BookRepository --entity ~.domain.Book
service --interface ~.service.BookService
web mvc setup
web mvc all --package ~.web
</pre>
<p>This will create a simple bookshop application. You can deploy this application on local tomcat using mvn tomcat:run. Please make sure you have MongoDB running on your local system.</p>
<p><strong>Deploying on OpenShift Express</strong></p>
<p>OpenShift Express supports two forms of deployment one is source code deployment which I showed in my last two blogs and other is war/binary deployment. In this blog I will show you how to deploy war to the Express cloud. Before we can deploy the application to OpenShift Express we first need to create bookshop application. To create the application execute the following command. You need rhc ruby gem to execute the command.</p>
<pre class="brush: plain; title: ; notranslate">
rhc-create-app -l &lt;rhlogin&gt; -a bookshop -t jbossas-7.0
</pre>
<p>It will prompt for the password. Now that you have created the application you should embed MongoDB cartridge in your application.</p>
<pre class="brush: plain; title: ; notranslate">
rhc-ctl-app -l &lt;rhlogin&gt; -a bookshop -e add-mongodb-2.0
</pre>
<p>Now that we have created the application and added the MongoDB cartridge we need to make change in our Spring application. We need to change applicationContext-mongo.xml file to have correct values for MongoDB factory. The values which exist are for application running on your local system. To change these values to OpenShift ones add a profile as shown below.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;beans profile=&quot;openshift&quot;&gt;
 &lt;mongo:db-factory dbname=&quot;${mongo.name}&quot; host=&quot;${OPENSHIFT_NOSQL_DB_HOST}&quot;
 port=&quot;${OPENSHIFT_NOSQL_DB_PORT}&quot; username=&quot;${OPENSHIFT_NOSQL_DB_USERNAME}&quot;
 password=&quot;${OPENSHIFT_NOSQL_DB_PASSWORD}&quot; /&gt;
 &lt;/beans&gt;
</pre>
<p>You also need to mention one context-param in web.xml to tell which profile is active. To do it add the following context-param.</p>
<pre class="brush: xml; title: ; notranslate">
   &lt;context-param&gt;
		&lt;param-name&gt;spring.profiles.active&lt;/param-name&gt;
		&lt;param-value&gt;openshift&lt;/param-value&gt;
	&lt;/context-param&gt;
</pre>
<p>Now build the project using mvn clean install -Dtest=maven.test.skip=true and copy to war file to deployments folder in OpenShift bookshop application. Also change the name of war to ROOT.war otherwise you application will be available at url_of_application/bookshop.<br />
Now to deploy do the following in deployments folder.</p>
<pre class="brush: plain; title: ; notranslate">
git add .
git commit -a -m &quot;adding bookshop application&quot;
git push
</pre>
<p>Wait for application to get deployed and see your application running at <a href="http://bookshop-random.rhcloud.com/">http://bookshop-random.rhcloud.com/</a></p>
<p><strong>Deploying to Cloud Foundry</strong></p>
<p>To deploy the bookshop application to Cloud Foundry we just need to add one more profile as shown below.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;beans profile=&quot;cloud&quot;&gt;
	&lt;cloud:mongo-db-factory id=&quot;mongoDbFactory&quot;/&gt;
&lt;/beans&gt;
</pre>
<p>In web.xml change the value of spring.profiles.active to cloud and create a war. To deploy to Cloud Foundry follow the following steps</p>
<ol>
<li>Download the Cloud Foundry <a href="http://rubygems.org/gems/vmc">VMC Ruby gem</a></li>
<li>Build the project using Maven. Do mvn clean install -Dmaven.test.skip=true</li>
<li>Once you have installed the vmc gem go to target folder and do vmc push.  This command will prompt you for creating a MongoDB service say yes to  that and you application will be deployed to Cloud Foundry cloud.</li>
<li>You can check the running application at <a href="http://bookshop.cloudfoundry.com/">http://bookshop.cloudfoundry.com/</a></li>
</ol>
<p>That's it for this blog. I think you will agree that Spring Profiles feature is very useful and powerful.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/27/using-spring-3-1-profiles-to-achieve-paas-portability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript client for web service using CXF</title>
		<link>http://xebee.xebia.in/2012/02/24/javascript-client-for-web-service-using-cxf/</link>
		<comments>http://xebee.xebia.in/2012/02/24/javascript-client-for-web-service-using-cxf/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 08:35:07 +0000</pubDate>
		<dc:creator>Mukesh Shah</dc:creator>
				<category><![CDATA[Apache CXF]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12100</guid>
		<description><![CDATA[Recently, I was looking for a Java Script client to test my Web Services. After my recent findings on CXF, I found out that it can also create JavaScript clients using tools. Since existing tools had ANT support for generating JavaScript client and my current requirements was to use Maven. After not finding any such [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I was looking for a Java Script client to test my Web Services. After my recent <a href="http://xebee.xebia.in/2012/01/25/what-made-me-to-choose-cxf-over-axis2/">findings on CXF</a>, I found out that it can also create JavaScript clients using tools. Since existing tools had ANT support for generating JavaScript client and my current requirements was to use Maven. After not finding any such configuration, I dug thoroughly the cxf-codegen-plugin, I came up with below configuration for maven to generate JavaScript artifacts.<br />
<span id="more-12100"></span><br />
Below are the guidelines to generate JavaScript artifacts and integrate it with existing JavaScript client.</p>
<p><strong>Create a maven based web project (or use your existing web project) and modify pom.xml as below</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;plugin&gt;
	&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
	&lt;artifactId&gt;cxf-codegen-plugin&lt;/artifactId&gt;
	&lt;version&gt;2.5.2&lt;/version&gt;
	&lt;executions&gt;
		&lt;execution&gt;
			&lt;configuration&gt;
				&lt;sourceRoot&gt;${project.build.directory}&lt;/sourceRoot&gt;
				&lt;wsdlOptions&gt;
					&lt;wsdlOption&gt;
						&lt;wsdl&gt;http://cxf_ws.cloudfoundry.com/sampleService?wsdl&lt;/wsdl&gt;
					&lt;/wsdlOption&gt;
				&lt;/wsdlOptions&gt;
			&lt;/configuration&gt;
			&lt;goals&gt;
				&lt;goal&gt;wsdl2js&lt;/goal&gt;
			&lt;/goals&gt;
		&lt;/execution&gt;
	&lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>In the pom mentioned above, sourceRoot tag in the configuration has been used to indicate directory to generate artifacts and wsdlOption has been used to mention the wsdl file location.</p>
<p><strong>Execute below maven command to generate JavaScript artifacts.</strong></p>
<p>mvn generate-sources</p>
<p>Once you run above command, a new JavaScript file gets generated at the mentioned destination directory, with the same name as wsdl definition name.</p>
<p><strong>Digging deeper into generated artifact.</strong></p>
<p>In brief about generated JavaScript artifact, There will be an operation function for every exposed web service operation and there will be a serialization and a deserialization functions for every operation function. The serialize function is used to convert the JavaScript object to an XML request format and the deserialize function converts the XML response to the corresponding JavaScript object.<br />
There will be a separate function which is used to map all these operation functions with their equivalent serialization/deserialization functions. This function is know as service function and gets generated by reading the service definition from the mentioned wsdl file in pom. The generated service function code starts with a comment given below.</p>
<pre class="brush: plain; title: ; notranslate">
// Definitions for service: {http://test.com/}SampleCXFServiceService
// Javascript for {http://test.com/}SampleCXFService
</pre>
<p><strong>Integrating generated artifact with JavaScript client code.</strong></p>
<p>Modify your client side JavaScript to incorporate generated artifact changes. For example if wsdl definition name is SampleCXFService then a  SampleCXFService.js file will get generated as an artifact. You need to include this SampleCXFService.js artifact in your client js. Other than that you also need to <a href="http://www.apache.org/dyn/closer.cgi?path=/cxf/2.5.2/apache-cxf-2.5.2.zip">download</a> CXF JavaScript utility file (cxf-utils.js) and include it in client JavaScript. This is a part of CXF distribution and can be found from apache-cxf-2.5.2-src\rt\javascript\javascript-rt\src\main\resources\org\apache\cxf\javascript location.</p>
<p>Add a JavaScript function (i.e. invokeService() ) to invoke the web service and store the result in a variable or use it directly(like in the snippet given below).</p>
<p><strong>Code snippet for client JavaScript:</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;cxf-utils.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;SampleCXFService.js&quot;&gt;&lt;/script&gt;

&lt;script language=&quot;JavaScript&quot; type=&quot;text/javascript&quot;&gt;
	var SampleService = new test_com__SampleCXFService();
	SampleService.url = &quot;http://cxf_ws.cloudfoundry.com/sampleService&quot;;

	function invokeService()
	{
	  var name = $('#inputTextId').val();
	  &lt;!-- Operation function invocation by passing name as input parameter --&gt;
	  SampleService.getMessage(successResponse, errorResponse, name);
	}

	&lt;!-- Function gets called for a successResponse. --&gt;
	function sucessResponse(response)
	{
		&lt;!-- Using response text to populate result on UI on success--&gt;
		$('#result').text(response.getReturn());
	}

	&lt;!-- Function gets called for an error. --&gt;
	function errorResponse(error)
	{
  	    alert(&quot;Error message is &quot; + error);
	}
&lt;/script&gt;
</pre>
<p>The first 2 lines are used to get the reference of web service using service function. The  invokeService() function simply delegating call to operation functions. There are two callback functions also in client js.</p>
<ul>
<li>successResponse(response) : This function retrieves the response object in callback process and gets called after a successful response.</li>
<li>errorResponse(error): In case of web service invocation failure, this function retrieves the error message in the callback process and display that message in an alert.</li>
</ul>
<p><strong>References:</strong></p>
<p><a href="http://cxf.apache.org/docs/overview.html">http://cxf.apache.org/docs/overview.html</a><br />
<a href="http://cxf.apache.org/docs/wsdl-to-javascript.html">http://cxf.apache.org/docs/wsdl-to-javascript.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/24/javascript-client-for-web-service-using-cxf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Social API&#8217;s and Updates in Ice Cream Sandwich</title>
		<link>http://xebee.xebia.in/2012/02/23/android-social-apis/</link>
		<comments>http://xebee.xebia.in/2012/02/23/android-social-apis/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 09:10:50 +0000</pubDate>
		<dc:creator>Paramvir Singh</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Social API]]></category>
		<category><![CDATA[android development]]></category>
		<category><![CDATA[Android4.0]]></category>
		<category><![CDATA[ContactsContract]]></category>
		<category><![CDATA[Ice Cream Sandwich]]></category>
		<category><![CDATA[ICS]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=12204</guid>
		<description><![CDATA[Giving users “power to share ” seamlessly  is a feature we will find in all popular and frequently used Mobile applications. Being social is crucial for applications. Users love to share and Android knows that. Acting prudently, Android has provided API's as well as inherent support using Intents for social integration. Here, I will explicate the [...]]]></description>
			<content:encoded><![CDATA[<p>Giving users “power to share ” seamlessly  is a feature we will find in all popular and frequently used Mobile applications. Being social is crucial for applications. Users love to share and Android knows that. Acting prudently, Android has provided API's as well as inherent support using <a href="http://developer.android.com/reference/android/content/Intent.html" target="_blank">Intents</a><b> </b>for social integration. Here, I will explicate the API's developers can use to integrate social features with their applications.<span id="more-12204"></span></p>
<p><b> </b></p>
<p><b> </b><b>ContactsContract</b>:</p>
<p>We (developers) usually use this API to get user's contacts list. The important thing about this API is that one Contact row has different information(phone number, email id, name, photo etc.) for the same person aggregated from different sources like local contacts book, Facebook account, Skype, Gmail account etc. The whole contacts database is <b>extensible </b>and is managed in a <b>three tier data model </b>using following three classes under ContactsContract package:</p>
<ul>
<li>RawContacts</li>
<li>Data</li>
<li>Contacts<img src="http://xebee.xebia.in/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" title="More..." /></li>
</ul>
<div>
<div id="attachment_12251" class="wp-caption aligncenter" style="width: 660px"><a rel="attachment wp-att-12251" href="http://xebee.xebia.in/2012/02/23/android-social-apis/contactscontract-3/"><img class="size-large wp-image-12251   " height="400" width="650" title="ContactsContract" src="http://xebee.xebia.in/wp-content/uploads/2012/02/ContactsContract2-1024x621.jpg" /></a><p class="wp-caption-text">ContactsContract</p></div>
</div>
<div>
<div>
<dl id="attachment_12184"> </dl>
</div>
</div>
<p>We can do basic operations like insert, update, delete as well as query the contacts database. For example, to insert a contact :</p>
<pre class="brush: java; title: ; notranslate">
ContentValues values = new ContentValues();
values.put(RawContacts.ACCOUNT_TYPE, accountType);
values.put(RawContacts.ACCOUNT_NAME, accountName);
Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
</pre>
<p><b>What Android4.0 (ICS) added to it:</b></p>
<ul>
<li><b>Easy access with high resolution photos</b>: In this version, the people to which users are most connected will be arranged into a magazine like UI. According to Android developer team “This is to support emotional connections between humans and the devices they carry”.<br />
For this purpose higher resolution pictures will be used ( 256x256 instead of 98x98).</li>
</ul>
<ul>
<li><b>Social Stream for Sync Adapters: </b>Through this “biggest new edition”, social applications can display recent online activities of all the contacts in the device user’s contact list. The activities would be visible in the contact list itself. This is achieved by <b>Sync Adapters. </b>Sync adapters can synchronize the raw contacts data  available locally on the device with the contact data available in the cloud resources like Facebook, Skype and other social  apps. In current update, the Sync Adapters now can also fetch update status, photos and other user posts via social stream. Following two classes are important:</li>
</ul>
<ol>
<li><a href="http://developer.android.com/reference/android/provider/ContactsContract.Contacts.StreamItems.html" target="_blank">StreamItems</a>: Stream items contain the recent social updates of a particular user under its Raw Contact data. Also contain the comments, photos and other useful information related to that social update.</li>
<li><a href="http://developer.android.com/reference/android/provider/ContactsContract.StreamItems.StreamItemPhotos.html" target="_blank">StreamItemPhotos</a>: Contains the photos related to a single social update by the user.</li>
</ol>
<ul>
<li><b>The “ME” Contact: </b>This will contain device user’s personal contact  information and profile data. Applications can access the “ME” profile information for display and verification purpose.</li>
</ul>
<ul>
<li><b>Adding a new connection is easy: </b>This is another important update in ICS. Now user can connect to a person on any social website (Facebook, Google plus) by clicking an option in the contact detail page of that person in the device's people app.</li>
</ul>
<div><b><br />
</b></div>
<p><b>NFC Reloaded with Beam:</b></p>
<p>NFC or Near Field Communication is one of the latest buzzwords in mobile sphere. Besides its acclaimed uses in e-commerce, mobile payments and enterprises it is becoming a new media of sharing. This "<a href="http://www.slideshare.net/ParamvirSingh1/near-field-communication-10509831" title="Slides: NFC, the &quot;tap&quot; technology" target="_blank">tap</a>" technology can be used for exchanging any type of data between two mobile devices.</p>
<p>Good thing is, NFC APIs are exposed to the developers and are available under <a href="http://developer.android.com/reference/android/nfc/package-summary.html" title="android.nfc packager summary" target="_blank">android.nfc</a> package.</p>
<p>In 4.0, a new application "Beam" is introduced to make tap-and-share feature  more intuitive. Using Beam, users can share apps, contacts, music, videos and other media contents and files instantly by single tap or touch of two NFC enabled devices.</p>
<p>Beam uses "NDEF push" to transfer data between devices when two devices come in close proximity. NDEF is a special format for NFC data and stands for "NFC Data Exchange Format". Two important classes used for NFC communication are:</p>
<ul>
<li>NDEFMessage: Container for NDEFRecords.</li>
<li>NDEFRecord: Contains the payload data, id and the type of data. if payload data is large, it is divided into   more than one NDEFRecords.</li>
</ul>
<p><b><br />
</b><strong>Intents To Share:</strong></p>
<p>Intents are the mainstay of Android system. Apart from regular usage of intents to start another activities, passing data across activities and applications, receiving broadcasts and triggering a service, intents can perform an interesting job for us: to give apps the power to "share" and that without a much extra effort. The simplest case is to create "Activity chooser " dialog to chose a social app capable of sharing:</p>
<pre class="brush: java; title: ; notranslate">
Intent intent=new Intent(android.content.Intent.ACTION_SEND);
intent.setType(&quot;text/plain&quot;);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
// Add data to the intent, the receiving app will decide what to do with it.
intent.putExtra(Intent.EXTRA_SUBJECT, “Here goes the subject...”);
intent.putExtra(Intent.EXTRA_TEXT, “Here goes the message body...”);
&lt;pre&gt;</pre>
<p><strong>Updates in 4.0: </strong>In this version, a new tool is introduced : <a href="http://developer.android.com/reference/android/widget/ShareActionProvider.html" title="ShareActionProvider" target="_blank">ShareActionProvider</a> . This will create a "share" button in the Action Bar. It is a sub-class of ActionProvider. ActionProviders are responsible for creating views to do the required action that will accomplish a given task. ShareActionProvider will create view for "share" task.</p>
<p>For using ShareActionProvider, modify the onCreateOptionsMenu() method in the Activity:</p>
<pre class="brush: java; title: ; notranslate">

public boolean onCreateOptionsMenu(Menu menu) {

MenuItem menuItem1 = menu.findItem(R.id.menu_item);

mShareActionProvider = (ShareActionProvider) menuItem1.getActionProvider();

mShareActionProvider.setShareHistoryFileName(&quot;custom_share_history.xml&quot;);

}
</pre>
<p>This will create a list of share targets the user can chose from to perform the sharing. The order of the share targets will depend on the past usage of the user which is saved in a history file. We can either use the default history file or we can maintain a custom history file and use that file throughout the application.</p>
<p>The ICS release has brought exciting goodies for developers and updates in social API's are most appealing.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/23/android-social-apis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Event Driven Architecture &#8211; EDA</title>
		<link>http://xebee.xebia.in/2012/02/20/event-driven-architecture-eda/</link>
		<comments>http://xebee.xebia.in/2012/02/20/event-driven-architecture-eda/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 07:22:14 +0000</pubDate>
		<dc:creator>Anant</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11515</guid>
		<description><![CDATA[We live in an event driven world. Companies, employees and even animals survive and thrive in this world on their ability to respond to any given opportunities and threats. These opportunities and threats occur in more unpredictable manner then any economic theory or sixth sense can map or forecast them. So to handle them we [...]]]></description>
			<content:encoded><![CDATA[<p>We live in an event driven world. Companies, employees and even animals survive and thrive in this world on their ability to respond to any given opportunities and threats.</p>
<p>These opportunities and threats occur in more unpredictable manner then any economic theory or sixth sense can map or forecast them. So to handle them we need event based handlers that are externally determined. <span id="more-11515"></span></p>
<p>Have a look at the below picture:</p>

<a href='http://xebee.xebia.in/2012/02/20/event-driven-architecture-eda/eda-2/' title='EDA'><img src="http://xebee.xebia.in/wp-content/uploads/2012/02/EDA1.bmp" class="attachment-thumbnail" alt="EDA" title="EDA" /></a>

<p>To give more sense to above picture:</p>
<p><strong>Event :</strong> It can be any thing which happens in this world or even universe like in this picture a striking light/ football match/finding water on moon etc. etc.</p>
<p><strong>Event listener &amp; generator :</strong>This element will listen an event (as a listener) and thereafter creates and send a signal to the Event Engine (as a generator).</p>
<p><strong>Event Engine :</strong> Upon receiving a signal this element will process the details and then send it to clients.</p>
<p><strong>Client :</strong> They all will catch the event and interrupt in the manner they want.</p>
<p>Gear up your imagination with the example below:</p>
<p>Imagine your air flight is running late (Event for us, although not the pleasant one). Now what could be the action plan in perfect world:</p>
<p>Your booked cab can be notified for the same so that they can adjust their bookings by assigning a new cab to you and may be book your cab for someone else.</p>
<p>In the same manner hotel reservation can also be handled when notified about your air flight delay.</p>
<p>Even your travel agent can look for other alternative routes or any other flights which can be taken if you have tight schedule. He can even notify the people at seminar you suppose to attend for your delayed plan.</p>
<p>The most important thing to catch here is  <em>"when an air flight gets delayed, the airline doesn't know any of these above cases."</em></p>
<p>Airline will just announce the delay or cancellation of a flight (which is a Event). The event will be announced to everything which says it's interested in that flight, which may be no one, a passenger or may be several agents for each passenger on the flight. The event listener &amp; generator (cab, hotel and travel agent) decides how to react to the notification. Thus processing the notification by re assigning in case of cab or re booking in case of hotel (Event Engine). After that they will send the confirmation notification to clients.</p>
<p><strong>Magento</strong> (CMS in PHP) uses EDA as its core of existence. Let's look how can we define an event and its affect in Magento.</p>
<p>Within Magento you can dispatch an event as simple as by calling a method like :</p>
<p><em>BaseController</em>::dispatchEvent('custom_event', array('data1'=&gt;$data));</p>
<p>This method accepts two parameters - event unique identifier and associative array of data passed to listener.</p>
<p>In Listener custom class, all the data dispatched by event will be captured and a listener would be added :</p>
<p>class Listener<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;* function to take out the 'object' key from $data passed to Listener<br />
&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static function addtoCart($data)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$object = $data-&gt;getEvent()-&gt;getObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$object-&gt;callPayPalEvent();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>In some cases, we need to process the request as per the event received.</p>
<p>public static function cashPaymentEvent($object)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;foreach($object-&gt;getEvent() as $event)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateCart($event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>The above Airline example is a simple case of Event Driven Architecture (EDA), it has more complex parts named as <strong>Complex event processing (CEP)</strong></p>
<p>Complex event processing (CEP) in above cases could be like delay in flight can affect the airport management, crew allocation, opening of gates, passengers intimation, subsequent delay in on going journey of that flight.</p>
<p>If you notice that event (Air flight delay) which is fired resulted in some services. Thus a service is triggered by incoming events. Hence, making its way to <strong>Service oriented architecture</strong> (SOA).</p>
<p>So in today's IT world where we talk more about events and services, we can easily state that  <strong>SOA 2.0</strong> evolves with the implications of both SOA and EDA architectures.</p>
<p>Hopefully, in next blog we will discuss more about SOA and EDA as winning combination.</p>
<p>Reference : https://www.ibm.com/developerworks/wikis/display/woolf/Event-Driven+Architecture+Examples</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/20/event-driven-architecture-eda/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Liferay Service Builder</title>
		<link>http://xebee.xebia.in/2012/02/16/liferay-service-builder/</link>
		<comments>http://xebee.xebia.in/2012/02/16/liferay-service-builder/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 17:52:51 +0000</pubDate>
		<dc:creator>Robin Nagpal</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[Portal]]></category>
		<category><![CDATA[Service Builder]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11999</guid>
		<description><![CDATA[Why another blog on Service builder ? Since you have landed on this post, we know that you are looking for a good reference for Liferay Service Builder, and by now you might be frustrated by the minimal documentation from Liferay, or are enervated by scrolling down the liferay forums, or you have been hopping [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Why another blog on Service builder ?</strong><br />
Since you have landed on this post, we know that you are looking for a good reference for Liferay Service Builder, and by now you might be frustrated by the minimal documentation from Liferay, or are enervated by scrolling down the liferay forums, or you have been hopping from one  blog to other since long. There is not even a single sufficient article/blog  which explains service builder in detail. I and my colleague <a href="http://xebee.xebia.in/author/pgarg/">Pratik</a>, faced the same problem some time ago, and we then decided to write a series of blogs which will help you in getting a good understanding of Service Builder.</p>
<p><span id="more-11999"></span><br />
We are using Liferay 5.2.3 for developing a web based collaboration portal with a very huge user base. Portal requires development of many custom portlets, which means handling CRUDs around old and new entities. We then started searching for some tools which could increase our pace of development of portlets and we came across Liferay Service Builder. This tool has great power but its effective usage requires good level of understanding. So here is the series of upcoming blogs which will introduce the liferay service builder concepts. We will start with "Service Builder Basics" and then dive deeper into advanced topics.  Here is a snapshot of different spaces.</p>
<ol>
<li>Service Builder Basics</li>
<li>Service Builder Finders</li>
<li>Advantages , Disadvantages , Tips and Tricks</li>
<li>Remote Services</li>
<li>Caching</li>
<li>Transactions</li>
<li>Testing</li>
</ol>
<p><strong>What is service builder ?</strong><br />
Liferay provides a code generation utility called Service Builder, created with an intention to get rid of most boilerplate work during portlet development. Liferay internally uses Spring and Hibernate, which basically means if you are not using service builder, you will end up writing the service layers, pojo’s , dao’s , sql scripts and configuration files if not using annotations. Service Builder does all this with little instructions. To get a good hang of service builder lets walk through an example and run though the various stages starting with concept of an entity and ending with the deployment of that entity inside a portlet with suitable views.</p>
<p><span style="font-size: large;"><strong>Email Example </strong></span><br />
Lets say we need an entity of “Email” which has attributes such as  from , to , cc, body, date and text.</p>
<p><span style="font-size: large;"><strong>Configuration</strong></span><br />
Create a service.xml file in your portlet as location - "portlet/docroot/WEB-INF/service.xml".  service.xml should stick to <a href="http://www.liferay.com/dtd/liferay-service-builder_5_2_0.dtd%20">this</a> schema definitions. Add entry for Email entity in service.xml.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;entity name=&quot;Email&quot; local-service=&quot;true&quot; remote-service=&quot;false&quot; table=&quot;Email&quot;&gt;
   	 &lt;column name=&quot;id&quot; type=&quot;long&quot; primary=&quot;true&quot;&gt;
   	 &lt;column name=&quot;to&quot; type=&quot;String&quot;&gt;
   	 &lt;column name=&quot;from&quot; type=&quot;String&quot;&gt;
   	 &lt;column name=&quot;subject&quot; type=&quot;String&quot;&gt;
   	 &lt;column name=&quot;content&quot; type=&quot;String&quot;&gt;
   	 &lt;column name=&quot;date&quot; type=&quot;Date&quot;&gt;

   	 &lt;!--  Finders --&gt;
   	 &lt;finder name=&quot;To&quot; return-type=&quot;Collection&quot;&gt;
   		 &lt;finder-column name=&quot;to&quot;&gt;&lt;/finder-column&gt;
          &lt;/finder&gt;
   	 &lt;finder name=&quot;From&quot; return-type=&quot;Collection&quot;&gt;
   		 &lt;finder-column name=&quot;from&quot;&gt;&lt;/finder-column&gt;
         &lt;/finder&gt;
   	 &lt;finder name=&quot;Subject&quot; return-type=&quot;Collection&quot;&gt;
   		 &lt;finder-column name=&quot;subject&quot;&gt;&lt;/finder-column&gt;
         &lt;/finder&gt;
   	&lt;finder name=&quot;Date&quot; return-type=&quot;Collection&quot;&gt;
   		 &lt;finder-column name=&quot;date&quot;&gt;&lt;/finder-column&gt;
         &lt;/finder&gt;
&lt;/entity&gt;
</pre>
<ul>
<li>entity refers to a new model which we want to create</li>
<li>name attribute refers to the name of the entity</li>
<li>column tag represents the different fields in entity or columns in table</li>
<li>type refers to the data-type . Please note you cannot establish one-to-many or many-to-many relationships using this.</li>
<li>finder tag is used to create find utility methods</li>
</ul>
<p><span style="font-size: large;"><strong>Code Generation</strong></span><br />
Run "ant build-service" from the command (will work only if liferay bin is included in your path). Below is the explanation of all the classes that will be generated. Liferay strictly follows program to interface design so every impl will have its corresponding interface.</p>
<p><span style="font-size: large;"><strong>Generated classes.</strong></span><br />
Service Builder generates three types of classes i.e. Model, Service and Persistence</p>
<p><span style="font-size: medium;"><strong> </strong></span></p>
<p><span style="font-size: medium;"><strong>Model Objects</strong></span></p>
<p>These objects are nothing but the data/value objects.</p>
<p><a href="http://xebee.xebia.in/2012/02/16/liferay-service-builder/email_model_1/" rel="attachment wp-att-12036"><img src="http://xebee.xebia.in/wp-content/uploads/2012/02/email_model_1.png" title="email_model_1" class="aligncenter size-full wp-image-12036" width="650" height="400" /></a>Following is the list of model classes generated when you run service builder</p>
<ul>
<li><strong>BaseModel</strong> - This is the Base class provided by liferay which is extended by every model/entity object. This is analogous to object class in Java.<strong> </strong></li>
<li><strong>BaseModelImpl </strong>- Basic implementation provided by liferay for BaseModel.<strong> </strong></li>
<li><strong>EmailModel </strong>- Interface for the getters/setters of all the fields that are specified in the service.xml for this entity.<strong> </strong></li>
<li><strong>Email </strong>- This is interface for Email entity.<strong> </strong></li>
<li><strong>EmailModelImpl</strong> - Implementation for the EmailModel methods and couple of other utility methods like clone , toString etc.</li>
<li><strong>EmailImpl</strong> - By Default this class is empty. The purpose of this class is to provide a placeholder to have custom methods on the entity (which are not generated by default) . For instance, if you want to make this entity rich by having  methods like validate “to” field , you can add method something like this
<pre class="brush: java; title: ; notranslate"> …
&lt;pre&gt;public boolean validateToAddress(){
//Add code to validate this.to
}
…
</pre>
<p>Now once you add this method in the Impl , you need to have this inside a corresponding interface also which is Email. To add this method signature just run the "build-service" target again and method will be added to EmailInterface. Please note that the method cannot be added inside the EmailModelImpl because in case if we change the entity in future or just run the ant build-service, those custom written methods will get deleted.</li>
</ul>
<p><span style="font-size: medium;"><strong> </strong></span></p>
<p><span style="font-size: medium;"><strong>Service Objects</strong></span></p>
<p><span style="font-size: medium;"><strong> </strong></span> Once you have you model objects, you need services to operate on them, and service builders generates these as well</p>
<div width="100%"><a href="http://xebee.xebia.in/2012/02/16/liferay-service-builder/email_service/" rel="attachment wp-att-12018"><img src="http://xebee.xebia.in/wp-content/uploads/2012/02/email_service.png" title="email_service" class="aligncenter size-full wp-image-12018" width="650" height="283" /></a><br />
Following are the classes generated by service builder for service layer</div>
<ul>
<li><strong>EmailLocalService </strong>:  Interface containing all the crud operations that can be performed on the Email entity. for e.g add/delete/get/update/find<strong> </strong></li>
<li><strong>EmailLocalServiceBaseImpl</strong> : Implementation for the EmailLocalService .This class is injected will the serviceImpl’s and persistenceImpl’s of all entities present in the service.xml. One service may need to call other service to do business operations. Injection of these service and persistence impls fully equipts base impl to do such type of operations.<strong> </strong></li>
<li><strong>EmailLocalServiceImpl</strong> : This class has the same role as EmailImpl in the model layer. If you want to add custom methods in the service layer for this model, then you can add the implementation in this class and run the ant build-service, and the new method signature will be pushed into EmailLocalService as well.<strong> </strong></li>
<li><strong>EmailLocalServiceUtil</strong> : Since we are using spring, ideally we should be able to inject the EmailLocalServiceImpl instance into a java class of view layer (e.g ActionClasses in struts or PageClass in Wicked), but in liferay if you are using JSP Portlet , it will not be possible to inject this dependency . So this util contains the same method signatures as the EmailLocalService but with static qualifier, so that you can use them directly. Internally it will look up that impl from the spring context and then execute the methods on it.<strong> </strong></li>
<li><strong>EmailLocalServiceClp</strong> : Clp or ClassLoaderProxy objects are used to serialize the objects. In this case it will be used to serialize EmailLocalServiceImpl. These clps are used for remote services which will be discussed in detail later.</li>
</ul>
<p><span style="font-size: medium;"><strong>Persistence objects<br />
</strong></span></p>
<p>Persistence classes contain all the code for dealing with hibernate sessions and fetching the actual model objects</p>
<p><a href="http://xebee.xebia.in/2012/02/16/liferay-service-builder/email_persistence_1/" rel="attachment wp-att-12039"><img src="http://xebee.xebia.in/wp-content/uploads/2012/02/email_persistence_1.png" title="email_persistence_1" class="aligncenter size-full wp-image-12039" width="650" height="377" /></a></p>
<ul>
<li><strong> BasePersistence</strong> - BasePersistence class is provided by liferay which every persistence impl extends. Some of the methods are registerListener , unregisterListener which are used to associate listeners with events occurring on the Entity Table. for e.g addition of new entity.<strong> </strong></li>
<li><strong>SessionFactory</strong> - As the name suggests, this classes is used for the database sessions.We rarely have to deal directly with this class. This class is extended by the BasePersitenceImpl.<strong> </strong></li>
<li><strong>BasePersistenceImpl</strong> - Default implementation for the BasePersistence and SessionFactory.<strong> </strong></li>
<li><strong>EmailPersistence</strong> - Interface for the basic CRUD operation that can be done on the Email Model.</li>
<li><strong>EmailPersistenceImpl</strong> - Implementation for the EmailPersistence. Again this class is also injected with the persistence impl of all the entities specified in the service.xml. This persistence impl is <strong>not same</strong> as the ModelImpl or LocalServiceImpl, because you cannot write your custom methods in this class. If you have to create a custom persistence method then you need to create a finder. This will be discussed in our next blog.</li>
</ul>
<p><span style="font-size: medium;"><strong>Generated sql’s</strong></span></p>
<p><strong>tables.sql</strong> - This sql contains the basic template for table creation. This has to be tweaked as per the database used.</p>
<pre class="brush: sql; title: ; notranslate">
create table Email (
    id_ LONG not null primary key,
    to_ VARCHAR(75) null,
    from_ VARCHAR(75) null,
    subject VARCHAR(75) null,
    content VARCHAR(75) null,
    date_ DATE null
);
</pre>
<p><strong>indexes.sql</strong> : This sql lists the indexes on those fields which are specified as finders in the service.xml.</p>
<pre class="brush: sql; title: ; notranslate">
create index IX_936DE65F on Email (date_);
create index IX_19F9ECE3 on Email (from_);
create index IX_8DEFA35A on Email (subject);
create index IX_92C5C772 on Email (to_);
</pre>
<p><strong><br />
<span style="font-size: x-large;">Code Utilization</span></strong></p>
<p>Lets take the use case of displaying all the emails  that were created yesterday.  So, to fetch emails by date, our portlet will call service class, which will call persistence class, and this will return the list of emails created yesterday. Lets start in t the reverse order and see how to write custom methods in each layer.</p>
<p><strong>Persistence layer</strong></p>
<p>This finder entry shown below, which we added while creating our Email entity,  is responsible for creation of a finder method in EmailPersestenceImpl.java and  and also in EmailPersistence.java.</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;finder name=&quot;Date&quot; return-type=&quot;Collection&quot;&gt;
   		 &lt;finder-column name=&quot;date&quot;&gt;
   	 &lt;/finder-column&gt;&lt;/finder&gt;
</pre>
<p>The method which gets added has the following signature:</p>
<pre class="brush: java; title: ; notranslate">
	public java.util.List&lt;com.xebia.general.model.email&gt; findByDate(
   	 java.util.Date date) throws com.liferay.portal.SystemException;
</pre>
<p><strong>Service Layer</strong></p>
<p>Our service layer should have a custom method which will take a date and then call the persistence layer to get all the emails corresponding to that date.  Our custom method will go into EmailLocalServiceImpl.java and will look like</p>
<pre class="brush: java; title: ; notranslate">
public  List&lt;email&gt; getAllEmailsByDate(Date createdDate) throws SystemException{
   		 List&lt;email&gt; emailsByDate = emailPersistence.findByDate(createdDate);
   		 return emailsByDate;
    }
</pre>
<p>After adding this method run service builder. Service Builder then pushes this method in the corresponding service and util classes. The new method that is added in EmailLocalService.java will look like</p>
<pre class="brush: java; title: ; notranslate">
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public java.util.List&lt;com.xebia.general.model.email&gt; getAllEmailsByDate(
   	 java.util.Date createdDate) throws com.liferay.portal.SystemException;
</pre>
<p>and in EmaiLocalServiceUtil.java</p>
<pre class="brush: java; title: ; notranslate">
	public static java.util.List&lt;com.xebia.general.model.email&gt; getAllEmailsByDate(
   	 java.util.Date createdDate) throws com.liferay.portal.SystemException {
   	 return getService().getAllEmailsByDate(createdDate);
    }
</pre>
<p><strong>Portlet code</strong></p>
<p>We now have the method for fetching emails by date in both persistence and service layer. Lets call the LocalServiceUtil class to get yesterday's emails</p>
<pre class="brush: java; title: ; notranslate">
List&lt;email&gt; emailsByDate = EmailLocalServiceUtil.getAllEmailsByDate(yesterday);
</pre>
<p>We would now like to conclude the "Service Builder Basics". After reading this post you should know: the classes generated by liferay, using of the generated classes, and placeholders for adding your custom code. In the next post we will add some entities in Email, and will then see how to use one-to-many, many-to-many, or write custom sqls by using finders.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/16/liferay-service-builder/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Tune your postgresql server with index on Text column</title>
		<link>http://xebee.xebia.in/2012/02/16/tune-your-postgresql-server-with-index-on-text-column/</link>
		<comments>http://xebee.xebia.in/2012/02/16/tune-your-postgresql-server-with-index-on-text-column/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 11:21:28 +0000</pubDate>
		<dc:creator>Saurabh Gupta</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Postgresql]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[postgresql performance]]></category>
		<category><![CDATA[postgresql text index]]></category>
		<category><![CDATA[tune postgresql]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11841</guid>
		<description><![CDATA[I am working on postgresql from last couple of weeks. In this blog, I will share my experience with tuning of postgresql server. After working on streaming replication, I got a chance to find the optimal write performance of postgresql with index and without index. As application is financial so we need to stick with data [...]]]></description>
			<content:encoded><![CDATA[<p>I am working on postgresql from last couple of weeks. In this blog, I will share my experience with tuning of postgresql server. After working on streaming replication, I got a chance to find the optimal write performance of postgresql with index and without index.</p>
<p>As application is financial so we need to stick with data consistency and thats why postgresql is running in "synchronized" replication mode. In the application, we are required to insert 40 million records, which would come from multiple sources in the form of text or csv files, in postgresql database with index on or off.</p>
<p>Without index the performance was very good (4000 to 4200 writes per second) but when I created index on text column then the performance reduced to 1/8th (500 to 550 writes per second). The reason is as the data grows the size of index also grows which takes huge amount of RAM, which results in an increased number of hits to the database for read and write operations.</p>
<p>To increase the performance I tweaked configuration of postgresql server which is defined in postgresql.conf. After changing the configuration the performance almost reached to previous level (3800 to 4000 writes per second).</p>
<div></div>
<div><span id="more-11841"></span></div>
<div><b><br />
</b></div>
<div><span style="text-decoration: underline;"><b>Test Environment</b></span></div>
<div>Master and Standby postgresql servers were running on same system in synchronized streaming replication mode. System had 4 GB RAM and 8 core CPU with Centos 6 operating system. I inserted 40 million records in the database and each row size was approximately 2.5 KB.</div>
<div><b><br />
</b></div>
<div><b>Configuration parameters</b></div>
<div>Following are the parameters which I changed in configuration file:</div>
<ol>
<li><b>SHARED_BUFFERS</b><br />
The first parameter that I changed in the configuration file was shared_buffers. Shared buffers defines a block of memory that PostgreSQL will use to hold  requests that are awaiting attention from the kernel buffer and CPU. The default value is 32 MB which is very low for write-heavy applications. This buffer is allocated while initializing the database. The value can not be assigned greater than  the value defined in shmmax file . Shmmax is in /proc/sys/kernel directory. If the value of shared_buffers is greater than value defined in shmmax and you try to start the postgresql server then server will throw an exception on the screen. So first update the value in shmmax and then start the server again. Value is in bytes in shmmax file. It should be sufficient enough to handle load on database server. Otherwise PostgreSQL will start pushing data to file and it will hurt the performance overall. This value should be set based on the: Size of data in database server + available RAM. Recommended value is 25 percent of system RAM.</li>
<li><b>MAINTENANCE_WORK_MEM</b><br />
This  is the working memory for larger operations than just regular sorting  e.g. VACUUM, CREATE  INDEX, ALTER  TABLE ADD FOREIGN KEY. The  approximate value of this parameter should be 50 MB of maintainance_work_mem per GB of server RAM.</li>
<li><b>WAL_BUFFER</b><br />
The  default value of this parameter is 64 KB. This setting should be  large enough to hold the amount of WAL data for a transaction. Otherwise data is written to disk every time which reduce the  performance of server.  For write-heavy application the optimal value  is atleast 1 MB or more. If you set the value as -1 then server  automatically calculate and set the value.</li>
<li><b>CHECKPOINT_SEGMENT</b><br />
PostgreSQL  creates WAL segment in database files for each new transactions that  are 16MB in size. By default a checkpoint segment value is 3. This  value should be atleast 10 if you are not running very small  application. For  more write-heavy systems, values are used  between 32 (checkpoint  every 512MB) to 256 (every 4GB).  Very large value will increase the  disk size as well as time to recover the database. Normally the large  settings (&gt;64/1GB) are only used for bulk loading.</li>
<li><b>CHECKPOINT_COMPLETION_TARGET</b><br />
If  you have increased the value of checkpoint_segment atleast 10 then  this value should be increased from default value 0.5 to 0.9. This  provides the checkpoint spreading without overhead on I/O.</li>
<li><b>EFFECTIVE_CACHE_SIZE</b><br />
This  parameter generally used for query tuning. This cache is used by  planner before executing the query to create different plans. Setting  effective_cache_size to 1/2 of total memory would be a normal  conservative setting, and 3/4 of memory is a more aggressive but  still reasonable amount.</li>
</ol>
<div><b>Conclusion</b></div>
<div>Following  are the values that I used in postgresql.conf</div>
<ol>
<li>Shared_buffer: 500MB</li>
<li>Checkpoint_segment: 64</li>
<li>Checkpoint_completion_target: 0.9</li>
<li>Maintenance_work_mem: 50 MB</li>
<li>Wal_buffer: 16MB</li>
<li>Effective_cache_size: 500MB</li>
</ol>
<div></div>
<div>These  all parameters that I tweaked in configuration file to get the best  performance. This  was all about my experience. If you also had similar  issues/challenges or if you want to share your finding on the same,  then please share it as a comment.</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/16/tune-your-postgresql-server-with-index-on-text-column/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Importance Of Exploratory Testing</title>
		<link>http://xebee.xebia.in/2012/02/16/importance-of-exploratory-testing/</link>
		<comments>http://xebee.xebia.in/2012/02/16/importance-of-exploratory-testing/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 10:41:26 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Exploratory testing]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11452</guid>
		<description><![CDATA[Meaning of Exploratory Testing is self explanatory. In plainest form, we can define it as discovery of test cases while testing functionality and then simultaneous learning functionality and designing test cases and executing them. It is useful in testing any type of application either simple or complex but It is extremely useful in following scenarios:- [...]]]></description>
			<content:encoded><![CDATA[<p>Meaning of Exploratory Testing is self explanatory. In plainest form, we can define it as discovery of test cases while testing functionality and then simultaneous learning functionality and designing test cases and executing them. It is useful in testing any type of application either simple or complex but It is extremely useful in following scenarios:-</p>
<p>1.  When you have no/less requirements or specifications</p>
<p>2. When you have little or no knowledge domain</p>
<p>3. When you do not have time to specify, script and test</p>
<p><span id="more-11452"></span></p>
<p>After reading few articles or papers on exploratory testing, I came to one conclusion that every tester does blend of both scripted and exploratory testing because while scripting test cases we cannot think of every obvious scenario which according to my experience happens most of the times. We come across with many other different test cases other than those scripted ones while doing real time testing of application.We know that there is always difference between what is written on a piece of paper and what you see working in real time.</p>
<p>My intent behind writing this blog is to showcase some information which I collected while working as a tester in my last project that nearly 40-45% of bugs were found during exploratory testing which were different from my scripted test cases. I would not say that this is a fixed percentage .This can vary depending on one’s knowledge of domain or complexity of application and many other factors.</p>
<p>Below graph shows the aggregated result percentage of bugs found in functionality testing on project where I was working as test consultant . I noticed that about 40-45% of bugs were found during exploratory testing.﻿</p>
<p><img src="data:image/png;base64,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" height="240" width="361" /></p>
<p><strong>Conclusion:-</strong></p>
<p>Exploratory testing is fun to do and if it is done properly then tester  can find many great and hidden bugs. It is an approach to find out how  software works and quality of testing depends on tester's skills of inventing test cases and finding bugs. We can gain  knowledge and expertise on what to test and how to identify problems by  studying competitive products, researching history of product, studying  related products, etc. Inspite of its advantages, it has  disadvantage also like test cases  invented on the fly becomes  difficult to recreate as it can be difficult to show what all test cases  are run.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/16/importance-of-exploratory-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>History of programming languages.</title>
		<link>http://xebee.xebia.in/2012/02/16/early-history-of-programming-languages/</link>
		<comments>http://xebee.xebia.in/2012/02/16/early-history-of-programming-languages/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 09:21:47 +0000</pubDate>
		<dc:creator>Jyoti Puri</dc:creator>
				<category><![CDATA[Programming Languages]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11646</guid>
		<description><![CDATA[Software development has a very rich history we rarely actually look into it. It’s very interesting and I should say very important to know the history of what we are doing and how and why it all came into being. What we have today with us is actually not the best, but there were many [...]]]></description>
			<content:encoded><![CDATA[<p>Software development has a very rich history we rarely actually look into it. It’s very interesting and I should say very important to know the history of what we are doing and how and why it all came into being. What we have today with us is actually not the best, but there were many factors responsible for making it what it is. <span id="more-11646"></span></p>
<p>It all began with the realization that logic can be represented by numbers also and not necessarily needed language. Initially there were punch cards where in you punch the information that’s fed into the machine which interprets those punches. But as the usages started growing and hardware improving programming languages came into picture. And there will be a programmer who will program it in Assembly Language and then it will be fed to a punching machine that will create punch cards for it and a deck of punch cards is your program... ready to run!!! This essentially happened after the invention of editors and until then computers was only a processing machine. The programming languages have a factor of human readability in them, which was what made them stand apart from those holes in the punch cards.</p>
<p>Thus the very first programming language to come into picture was Assembly Language. A program written in assembly language consists of a series of processor instructions and meta-statements, comments and data. These programmes can be types and saved using editors and while executing them they directly translate into machine language of 0 and 1. Most of us have read it in our academics, but it was only after I got to know the context in which it evolved that I am really finding the language with those GOTOs, MOV interesting. I wonder if it’s still being used anywhere, may be some really smart programmers are still coding in it to get best out of a great high end multiprocessor machine <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><!--more--></p>
<p>For most other programmers it’s practically not feasible to write good code in Assembly Language and this was soon realized. It took years and then appeared on screen high level languages. These were basically designed to be a more human friendly abstraction over the Assembly Language. Programmers can code in something more easily understandable for them and then computer which translate it into Assembly Language for itself and take care of its business. Later came into picture mainly 2 new programming languages:</p>
<ol>
<li>FOTRAN</li>
<li>COBOL</li>
</ol>
<p>Both these languages were essentially imperative languages consisting of statements and GOTOs to control flow. FOTRAN was fast in processing and more suited for scientific purposes. COBOL was made more human readable basically designed for business purposes.</p>
<p>Another major breakthrough achieved in invention of ALGOL. This language brought the concept of structured programming and blocks scope and saved us from ugly GOTOs. It took about a decade or 2 to get rid of GOTOs, GOTOS pointing to various places in the program actually complicate it and programs really cannot scale with these GOTOs.</p>
<p>But the trouble with these languages was that they were too complicated and specialized. FOTRAN was specialized for scientific programs and COBOL for business programs and ALGOL specialized for algorithmic programming. Thus need was felt for a simplified language that can sufficiently fulfil all these needs and more. Many languages like CPL, BCPL, LISP, and Pascal came into picture but none was largely successful.</p>
<p>Then came the first greatly successful language that’s Dennis Ritchie's C. C is a structured, imperative programming language, it was basically developed for System Software but it was then largely used for all types of software requirements. C had much influence on all the programming languages that came afterwards.</p>
<p>During the same time deriving its roots from ALGOL Object Oriented Programming languages Simula and SmallTalk came into picture. SmallTalk a wonderful Object Oriented language was developed mainly for games programming. Though great language it was not very successful since programmers did not much liked its syntax. Although not very successful its Object Oriented concepts SmallTalk had significant influence on languages that appeared later.</p>
<p>After 1980s no new major programming language paradigm came into picture but what happened was essentially consolidation of what was already there. C and SmallTalk inspired development of many new languages like Objective C, C++, JAVA, C#, Ruby, Eiffel.</p>
<p>As internet age started JAVA and other scripting languages had widespread acceptance coz of its platform independence and use in browsers.</p>
<p>In the mean time also evolved the concepts of functional programming and actor model. Actor model was slight shift from Object Oriented Programming wherein everything is an actor which communicates by sending messages. It was realised that this actor model is really not new; the concept is already in used in event driven applications. These concepts ripe in development of language like Scheme. This later went to have great influence on many languages today.</p>
<p>Evolution of software paradigms all happened in stages. And each shift in the paradigm took years. Though we may call our software community as most fast moving one, but our history definitely not so good.</p>
<p>Platform is now set and new languages like Scala, Haskell and DSLs are appearing on screen. The programming community is also much more large, open and dynamic than ever before. Its era of internet and personal computers every new concept and idea get audience and community of people using it. It’s important that we know the language we are really coding in and keep exploring the newer ones.....Happy Programming!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/16/early-history-of-programming-languages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Groovy/Grails : Hibernate Session Gotchas in multi-threaded code</title>
		<link>http://xebee.xebia.in/2012/02/16/groovygrails-hibernate-session-gotchas-in-multi-threaded-code/</link>
		<comments>http://xebee.xebia.in/2012/02/16/groovygrails-hibernate-session-gotchas-in-multi-threaded-code/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 07:04:19 +0000</pubDate>
		<dc:creator>Gagan Agrawal</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Hibernate session]]></category>
		<category><![CDATA[Multithreading]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11635</guid>
		<description><![CDATA[Recently I came across a situation where I had to delegate some portion of work from main thread to a new thread. I did not want user to keep waiting and hence returned response as soon as the desired work was completed and triggered supplementary work in new thread. However while doing so, I faced [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I came across a situation where I had to delegate some portion of work from main thread to a new thread. I did not want user to keep waiting and hence returned response as soon as the desired work was completed and triggered supplementary work in new thread. However while doing so, I faced many challenges with respect to hibernate session in new thread. In this blog I will share my experiences with hibernate session in multi-threaded code and  possible ways of handling it. Since currently I am working on Groovy/Grails, my example is modeled around it. But same concepts can be used in any framework.</p>
<p><span id="more-11635"></span></p>
<p>Initially I used default implementation of Executor framework provided by Java to delegate supplementary work in separate thread. The advantage of using Executor framework is that we don't have to worry about Thread management. (You can read this <a href="http://insidethemachine.wordpress.com/2008/11/08/the-executor-framework/" target="_blank">blog</a> to get quick insight on Executor framework.). Following is the code snippet for initializing and submitting task in executorService.</p>
<pre class="brush: groovy; title: ; notranslate">
def executorService = Executors.newFixedThreadPool(10)
executorService.submit(closure)
</pre>
<p>The problem with above implementation is that, as soon as we submit closure(task) in the executorService, the hibernate session used in current thread is not available in closure submitted in thread pool. As a result when we start executing database related logic with in the closure, all sorts of hibernate sessions related problems start coming. Let me elaborate more on this.<br />
Suppose we have a web portal, in which when user registers himself, he will receive welcome email from Portal. So basically when user hits "Register" button after providing his information on form, behind the scene two actions are performed.</p>
<p>Action1 : Validate and persist user information in database</p>
<p>Action2 : Send welcome email to user</p>
<p>Action 1 must be performed in the main thread in which user's request is getting served. However once validations are done and related information is saved in database, it will not be a great idea to keep user waiting while email is getting sent out. It requires network communication with Email Server and might take some time to complete the process. Hence it makes more sense to trigger email sending code in separate thread. In the below mentioned example, "register" method of UserService will be called in main thread and "sendEmail" in separate thread.</p>
<pre class="brush: groovy; title: ; notranslate">
class UserService{

    def executorService = Executors.newFixedThreadPool(10)

    void register(User user){
        if(user.validate()){
            user.save()
            executorService.submit{
                sendEmail(user)
            }
        }else{
            //throw Exception to report errors
        }

    }

    void sendEmail(User user){
        EmailRequest emailRequest = new EmailRequest(user : user)
        try{
           //Email Code to send updated user information
           emailRequest.status = &quot;SUCCESS&quot;
        }catch(Exception e){
            emailRequest.status = &quot;FAILURE&quot;
        }
        emailRequest.save()
    }
}
</pre>
<p>Now here, we first validate the user object and if it is valid, we save it in db. After saving user information, we submit a closure to send email in executorService which assigns the required task to one of the threads in pool. So basically "sendEmail" method is executed in separate thread and user get's instant response without waiting for email to be sent. When "sendEmail" method is invoked in separate thread, it will create a EmailRequest and try to send email to user.  If it is successful, will save emailRequest with success status else with failure status for reporting purpose.  Now to perform db operations a hibernate session is required. For the "register" method of UserService, hibernate session is automatically attached to main thread by Grails. However for "sendEmail", there won't be any hibernate session attached since we have not injected executorService implementation and have rather created on our own. As a result there is all sort of possibility of getting error "No hibernate session found" in sendEmail thread. To avoid this error a hibernate session either needs to be manually created and attached with new thread or should be injected by Grails. No doubt second option is desirable and in order to achieve that one must make use of Grails executor <a href="http://grails.org/plugin/executor">plugin </a>which takes care of injecting required hibernate session in threads created by Executor Framework. So now executorService will get auto injected and I no longer need to initialize it as mentioned below. And task submitted to executorService will have hibernate session attached to it's thread.</p>
<pre class="brush: groovy; title: ; notranslate">

class UserService{

def executorService

...
}
</pre>
<p>Ok, so now we have hibernate session in "sendEmail" method for db operations. So has the problem got resolved? Well, not yet. One thing to be noticed is the hibernate session injected in new thread is a separate session than that was used in main thread and that brings up all sort of new problems. When "sendEmail" method actually get's invoked and receives a user instance, it expects the user instance must have already got saved in DB by main thread.  However there is possibility that emailRequest's save() method is invoked before user object has actually got persisted in DB. One might think that user.save() was invoked before submitting the request to "sendEmail" and it should have got persisted. But that's not the reality. User object will only be persisted in DB once main thread has committed it's transaction and there is a possibility that emailRequest.save() is invoked before main thread commits transaction. In such scenario one would get error "not-null property references a null or transient value" while persisting emailRequest object since it references user object which is not yet persisted. Even if main thread transaction would have got committed successfully before any operation related to user object is performed in new thread, there is still possibility of getting lazy loading exceptions. The reason being, once user object is submitted to new thread, it is no longer associated with hibernate session from where it was created or fetched. Hence it is in detached state. It needs to be reattached to new hibernate session in order to work correctly.</p>
<p>One might think, isn't there a way I can pass my main thread's hibernate session to this new thread. Well, that's not possible. Hibernate session object is not thread safe and is desired to be used by single thread. The reason it is not thread safe is that databases do not allow multiple statements to be executed against same connection. So what's the solution? There could be many ways of handling this problem. Let's discuss some of the possible ways.</p>
<p>Here what we actually want is that new thread should be executed after main thread has committed it's hibernate session so that DB changes done by main thread are visible to new thread. Also the objects created/fetched in main thread should not be directly shared with other threads. Rather only identifiers can be shared so that these objects can be fetched again in other threads. In order to do that we will have to make certain changes in our design. We need to trigger new thread only after main thread has got committed. For that let's remove executorService from UserService and let's create a background job which polls user table and checks if new entry has been created. We can identify a new entry by a flag say "new". And once the desired action has been taken, flag can be updated to "false". The new entry created by main thread will be visible only after main thread has committed it's session. Grails has Quartz <a href="http://grails.org/plugin/quartz">plugin</a> for scheduling background jobs.</p>
<pre class="brush: groovy; title: ; notranslate">
class UserService{

    void register(User user){
        if(user.validate()){
            user.new = true
            user.save()
        }else{
            //throw Exception to report errors
        }

    }
}
/*Background Job to send new user registration mail*/
class NewRegistrationMailSenderJob{
    void execute(){
        def users = Users.findAllByNew(true)
        users.each{user -&gt;
             sendEmail(user)
             user.new = false
             user.save()
        }
    }
    void sendEmail(User user){
        EmailRequest emailRequest = new EmailRequest(user : user)
        try{
           //Email Code to send updated user information
           emailRequest.status = &quot;SUCCESS&quot;
        }catch(Exception e){
            emailRequest.status = &quot;FAILURE&quot;
        }
        emailRequest.save()
    }
}
</pre>
<p>The job can be scheduled to run at predefined frequency say 15 mins and check for all newly created user objects. If found any, send email to the user and update the new flag to false. Since Quartz job has it's own hibernate session, there won't be any need to handle it manually. This way there won't be any problem with respect to hibernate session and tasks can be executed asynchronously.<br />
Above way of handling asynchronous tasks was based upon "POLL" mechanism. Alternative solution could be to use "PUSH" mechanism vai JMS Queues since they support transactions. So once user has been created in UserService, a message with user id can be placed in JMS Queue for email sending. Message will be successfully placed in Queue only when overall transaction get's committed. A Message Listener can be created to listen for such messages and send email in turn. Grails has no native support for XA datasources or 2-phase commit process. However it can be achieved via  Atomikos <a href="http://grails.org/plugin/atomikos">plugin</a>.</p>
<p>These are few solutions that I could think of, but there could be many other. The idea behind this blog is to bring awareness about Hibernate session's behaviour in multi-threaded code and possible solutions to handle the problems.</p>
<p>So here are few lines to conclude.</p>
<p><strong>Conclusion</strong></p>
<p>1.  Use Grails executorService plugin when there is no dependency of hibernate session between main and child threads.</p>
<p>2.  Use background job when child thread can only be invoked when main thread has committed hibernate session.</p>
<p>3.  Alternatively JMS Queue can also be used instead of background job.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/16/groovygrails-hibernate-session-gotchas-in-multi-threaded-code/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JAVA 6 and JAVA 7 new features &#8211; How much do we use them and do we really need them ? Part 1</title>
		<link>http://xebee.xebia.in/2012/02/15/java-6-and-java-7-new-features-how-much-do-we-use-them-and-do-we-really-them-part-1/</link>
		<comments>http://xebee.xebia.in/2012/02/15/java-6-and-java-7-new-features-how-much-do-we-use-them-and-do-we-really-them-part-1/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 15:11:30 +0000</pubDate>
		<dc:creator>Anupriya Chhabra</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11648</guid>
		<description><![CDATA[My first introduction to JAVA was that it is a "pure" object oriented language, that it is a strong building block for any software application and the biggest thing -it is platform independent giving it the "write once run anywhere" capability. There have been many upgrades and new version launches but  sometimes I feel that [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: small; font-family: arial,helvetica,sans-serif;">My first introduction to JAVA was that it is a <em>"pure"</em> object oriented language</span>, <span style="font-family: arial,helvetica,sans-serif; font-size: small;">that it is a strong building block for any software application and the biggest thing -it is platform independent giving it the <em>"write once run anywhere"</em> capability. There have been many upgrades and new version launches but  sometimes I feel that all that has been done in these new versions is it really worth it, are we actually using the new features or are the new versions simply bundling everything possible into the JDK and making it heavy.Lets have a look at the last 2 versions of JAVA 6 &amp; 7 and discuss the new features that these versions boast of.<span id="more-11648"></span></span></p>
<p class="wp-caption-dd"><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery">JAVA 6</span></span></strong></p>
<ol>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery">Support for Web Services:Before addition of web services to JDK 1.6 they were being shipped with JAVA Enterprise Edition. I dont think there was any need to bundle it into JDK. They should have left the JDK to do the basics, after all every JAVA  based application does not require Web Services support and those that required could have used JAVA EE.Keeping different  functionality in different components is a basic object oriented and software design concept - how can the makers of the first pure object oriented language forget this.<br />
</span></span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery">Bundled JAVA DB:JDK 6 comes bundled with JAVA DB which is loosely based on Derby.Now many of us must have been using JDK 6 since past 2-3 years but there must be a very few percentage using JAVA DB. Huge data heavy enterprise applications have already adopted the best solutions for their needs and they will not migrate their old database to JAVA DB just because it comes bundled with JDK 6. It may however be helpful to students learning JAVA and Databases.But at the end of the day it is just reinvention of the wheel , a feature which we hardly use and is of no value addition.Instead of this they could have provided ,more powerful connectors.<br />
</span></span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery">Monitoring and Management Tools:JDK 6 has tools like jmap and jhat for analyzing memory, heap and threads/objects count. A good utility to have but most of us who needed these tools are already using other tools like JMeter for this.</span></span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery">Security API: With JDK 6 we get a bundled security API. Now most of this is available in JAVA Cryptography Edition and should have been kept that way. Bundling everything in one makes no sense, different users have different needs and its better to keep them in separate components. JAVA is not a framework in itself it is a framework builder and we should try to keep it this way.</span></span></li>
</ol>
<p><span style="font-size: small; font-family: arial,helvetica,sans-serif;">Well all is not bad with JAVA 6 but if some good features which make it more robust  and an even stronger building block are added to it it, it would truly enhance the power of JAVA and make it the star it truly deserves to be.My wish-list includes addition of more design patterns related classes the way Observer Pattern classes are included in JAVA.<br />
</span></p>
<p class="wp-caption-dd"><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><span class="wpGallery"> </span><br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/15/java-6-and-java-7-new-features-how-much-do-we-use-them-and-do-we-really-them-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scrollable Photo Gallery with add, remove image abilities for iOS</title>
		<link>http://xebee.xebia.in/2012/02/15/scrollable-photo-gallery-with-add-remove-image-abilities-for-ios/</link>
		<comments>http://xebee.xebia.in/2012/02/15/scrollable-photo-gallery-with-add-remove-image-abilities-for-ios/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 11:01:19 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[gestures]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iOS5]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[UIImageView]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11562</guid>
		<description><![CDATA[Mobile apps are effectively distinguished by the way they present content to the user. Content that can act as a catalyst in inference of the information that is being supplied to the user. Understandingly photos are one of the most powerful tool to serve this purpose. But almost always we encounter the roadblock of creating [...]]]></description>
			<content:encoded><![CDATA[<p>Mobile apps are effectively distinguished by the way they present content to the user. Content that can act as a catalyst in inference of the information that is being supplied to the user. <strong>Understandingly photos are one of the most powerful tool to serve this purpose.</strong> But almost always we encounter the roadblock of creating our own personalized photo gallery as iOS does not provide any such component. Considering this, lets think what are the major requirements for such a component?<br />
Well, I find following possibilities<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<ul>
<li style="text-align: left;">It can be fed n number of pre stored images to be displayed</li>
<li style="text-align: left;">Users can dynamically add, remove images</li>
<li style="text-align: left;">Developers can control number of images which are visible to the user</li>
<li style="text-align: left;">Developers can control padding between images</li>
</ul>
<p><span id="more-11562"></span>I have tried to create a component catering to the points mentioned above. You can get your hands dirty on it <a href="https://github.com/rajdeepmann/Photo-Gallery">here</a>. After integrating it looks like this</p>
<p><a href="http://xebee.xebia.in/wp-content/uploads/2012/02/Screen-Shot-2012-02-15-at-2.21.26-PM.png"><img src="http://xebee.xebia.in/wp-content/uploads/2012/02/Screen-Shot-2012-02-15-at-2.21.26-PM.png" alt="XePhotoGallery with add/remove image feature " title="XePhotoGallery with add/remove image feature " width="671" height="160" class="aligncenter size-full wp-image-11569" /></a><br />
&nbsp;<br />
&nbsp;<br />
&nbsp;</p>
<p>The foundation stone of the component is a UIScrollView that is used to add multiple UIImageViews as subviews. The following code is used to display pre stored images.</p>
<pre class="javascript">-<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>placeImages:<span style="color: #66cc66;">&#40;</span>NSArray *<span style="color: #66cc66;">&#41;</span>aImageList<span style="color: #66cc66;">&#123;</span>
    scrollView_.<span style="color: #006600;">contentSize</span> =CGSizeZero;
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>int imageNumber =<span style="color: #CC0000;">0</span> ; imageNumber &amp;lt; <span style="color: #66cc66;">&#91;</span>aImageList count<span style="color: #66cc66;">&#93;</span>; imageNumber ++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
              UIImageView * imageView = <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>UIImageView alloc<span style="color: #66cc66;">&#93;</span> initWithImage:
                                     <span style="color: #66cc66;">&#91;</span>aImageList objectAtIndex:imageNumber<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>;
              imageView.<span style="color: #006600;">frame</span> = CGRectMake<span style="color: #66cc66;">&#40;</span>imageNumber * <span style="color: #66cc66;">&#40;</span>imageWidth_ + self.<span style="color: #006600;">widhtPaddingInImages</span><span style="color: #66cc66;">&#41;</span>,
                                     self.<span style="color: #006600;">heightPaddingInImages</span>, imageWidth_, imageHeight_<span style="color: #66cc66;">&#41;</span>;
              <span style="color: #66cc66;">&#91;</span>scrollView_ addSubview:imageView<span style="color: #66cc66;">&#93;</span>;
              <span style="color: #66cc66;">&#91;</span>imageView setUserInteractionEnabled:YES<span style="color: #66cc66;">&#93;</span>;
              CGSize size = scrollView_.<span style="color: #006600;">contentSize</span>;
              size.<span style="color: #006600;">width</span> = size.<span style="color: #006600;">width</span> + imageWidth_ + self.<span style="color: #006600;">widhtPaddingInImages</span>;
              scrollView_.<span style="color: #006600;">contentSize</span> = size;
       <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p>It is a simple code whereby an UIImageView is created in every iteration, but the tricky part here is to increment the content size width with right amount to make scrolling possible. That's why for every image being added <strong>we increment the content size width by image width and padding between images</strong>.</p>
<p>Now to remove the image we use iOS gestures, every UIImageView is registered for <strong>UILongPressGestureRecognizer</strong>. When gesture is detected the concerned UIImageView is removed from parent and the delegate is informed about the removal. The removal process is animated to give a soothing experience. Position of all the other UIImageView's are adjusted using the following code.</p>
<pre class="javascript">-<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>reconfigureImagesAfterRemoving:<span style="color: #66cc66;">&#40;</span>UIImageView *<span style="color: #66cc66;">&#41;</span>aImageView<span style="color: #66cc66;">&#123;</span>
    NSArray * imageViews = <span style="color: #66cc66;">&#91;</span>scrollView_ subviews<span style="color: #66cc66;">&#93;</span>;
    int indexOfRemovedImageView = <span style="color: #66cc66;">&#91;</span>imageViews indexOfObject:aImageView<span style="color: #66cc66;">&#93;</span>;
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>int viewNumber = <span style="color: #CC0000;">0</span>; viewNumber &amp;lt; <span style="color: #66cc66;">&#91;</span>imageViews count<span style="color: #66cc66;">&#93;</span>; viewNumber ++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
          <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>viewNumber == indexOfRemovedImageView <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
              UIImageView * imageViewToBeRemoved= <span style="color: #66cc66;">&#91;</span>imageViews objectAtIndex:viewNumber<span style="color: #66cc66;">&#93;</span> ;
              <span style="color: #66cc66;">&#91;</span>imageViewToBeRemoved setFrame:
              CGRectMake<span style="color: #66cc66;">&#40;</span>imageViewToBeRemoved.<span style="color: #006600;">frame</span>.<span style="color: #006600;">size</span>.<span style="color: #006600;">width</span>/<span style="color: #CC0000;">2</span>+imageViewToBeRemoved.<span style="color: #006600;">frame</span>.<span style="color: #006600;">origin</span>.<span style="color: #006600;">x</span>,
              scrollView_.<span style="color: #006600;">frame</span>.<span style="color: #006600;">size</span>.<span style="color: #006600;">height</span>/<span style="color: #CC0000;">2</span>, <span style="color: #CC0000;">0</span>, <span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>;
           <span style="color: #66cc66;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>viewNumber &amp;gt;= indexOfRemovedImageView <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
              CGPoint origin = <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>UIImageView *<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#91;</span>imageViews objectAtIndex:viewNumber<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">frame</span>.<span style="color: #006600;">origin</span>;
              origin.<span style="color: #006600;">x</span> = origin.<span style="color: #006600;">x</span> - self.<span style="color: #006600;">widhtPaddingInImages</span> - imageWidth_;
              origin.<span style="color: #006600;">y</span> = self.<span style="color: #006600;">heightPaddingInImages</span>;
              <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>UIImageView *<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#91;</span>imageViews objectAtIndex:viewNumber<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">frame</span> =
              CGRectMake<span style="color: #66cc66;">&#40;</span>origin.<span style="color: #006600;">x</span>, origin.<span style="color: #006600;">y</span>, imageWidth_, imageHeight_<span style="color: #66cc66;">&#41;</span>;
              scrollView_.<span style="color: #006600;">showsVerticalScrollIndicator</span> = NO;
              scrollView_.<span style="color: #006600;">showsHorizontalScrollIndicator</span> = NO;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
    CGSize size = scrollView_.<span style="color: #006600;">contentSize</span>;
    size.<span style="color: #006600;">width</span> = size.<span style="color: #006600;">width</span> - imageWidth_ -self.<span style="color: #006600;">widhtPaddingInImages</span>;
    scrollView_.<span style="color: #006600;">contentSize</span> = size;
<span style="color: #66cc66;">&#125;</span></pre>
<p>We extract the index of the image and shift all other UIImageView's using there frames. Also we decrement the content size width. </p>
<p>Currently the photo gallery can only show images in a single row. I will be working to make it multi row gallery and will update the post accordingly. You can also give it a try and add more features as you may find useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/15/scrollable-photo-gallery-with-add-remove-image-abilities-for-ios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Infinispan – The Path Covered</title>
		<link>http://xebee.xebia.in/2012/02/15/infinispan-%e2%80%93-the-path-covered/</link>
		<comments>http://xebee.xebia.in/2012/02/15/infinispan-%e2%80%93-the-path-covered/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 10:48:01 +0000</pubDate>
		<dc:creator>Jagmeet Singh</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Clustering]]></category>
		<category><![CDATA[Data grid]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[clustering toolkit]]></category>
		<category><![CDATA[infinispan]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11582</guid>
		<description><![CDATA[Last month I attended JUDCon – 2012 (JBoss Users and Developers Conference). One thing that attracted me most were sessions about Infinispan especially by Manik Surtani. I have tried to compile the information gained in a concise form. What is Infinispan? Infinispan is an opensource (LGPL) data grid platform written in Java and Scala. It [...]]]></description>
			<content:encoded><![CDATA[<p>Last month I attended JUDCon – 2012 (JBoss Users and Developers  Conference). One thing that attracted me most were sessions about  Infinispan especially by Manik Surtani. I have tried to compile the  information gained in a concise form.</p>
<p><span style="font-size: medium;"><b>What is Infinispan?</b></span></p>
<p><a href="http://www.infinispan.org" target="_blank">Infinispan</a> is an opensource (LGPL) data grid platform written in Java and Scala. It is a distributed key/value store which is transactional, in-memory (optionally persisted to disk) and feature rich.</p>
<p>It supports 2 modes: Embedded and Client – Server</p>
<p>Let's feature some of the key points for Infinispan:</p>
<ul>
<li>API – It is <i>java.util.Map </i>like  key/value store with an 	additional asynchronous API which can be  utilized for asynchronous 	operations. It also features a CDI (Contexts and Dependency Injection) API. There  is also an upcoming 	JPA layer using <a href="http://www.hibernate.org/subprojects/ogm.html" target="_blank">Hibernate OGM</a>.</li>
<p><span id="more-11582"></span></p>
<li>Transactions  – 	Infinispan supports JTA and XA compliant transactions. It supports 	 different levels of XA integrations namely; simple synchronization, 	 full XA and full XA with recovery. It also supports optimistic and 	 pessimistic transactions.</li>
<li>Persistent 	Storage –  Inifinispan is not just an in-memory data store  with 	support for write  through and write behind. It also supports 	Passivation (spillover to  disk) and warm starts (preloading from 	disk). It is shipped with  implementations for file system based 	BTree (BerkelyDB, JDB), JDBC,  Cloud Storage (via JClouds)</li>
<li>Replication – 	It uses two clustered modes, namely: Replication (Full replication) 	and Distribution (Partial replication).
<ul>
<li>Full 		replication – It attracts fast reads at the cost of expensive 		writes, however it has scalability limitations.</li>
<li>Distribution 		– It is linear and far more scalable with access to very large 		heaps.<br />
Remote  Gets can be 	expensive, hence need for L1 cache (near cache in general)  with 	attributes such as limited lifespan for entries and smart 	 invalidating algorithms for invalidating entries in cache.</li>
</ul>
</li>
<li>Code Execution 	– Infinispan also features concept of moving logic to data instead 	of vice - versa.<br />
This  is implemented using java concurrency 	enhancements: executors and  callable interfaces and APIs. It also 	has support for Map/Reduce for  compressing calculation results.</li>
</ul>
<p>An open,  language independent wired protocol, Hot Rod is also developed for  client – server communication with attributes like smart routing and  build-in failover and load balancing capabilities.</p>
<p>Apart from Hot Rod, memcached and REST protocols can be used for communicating for client – server.</p>
<p><span style="font-size: medium;"><b>Why use Infinispan?</b></span></p>
<p>Despite  of above features that Infinispan posses, do we really need it? What  could be use cases for using cache or more specifically distributed  caches?</p>
<p>There could be many use cases such as:</p>
<ul>
<li>To  cache data 	that is expensive to retrieve or calculate. For example,  database 	calls can be expensive. There could be some data which is an  outcome 	of complex time taking calculations used multiple times.</li>
<li>The  	need for fast, low – low latency data access for performance and 	time  sensitive applications. Distributes caches are mostly used in 	 industries like Financial industry, Telcos or Highly scalable 	 e-commerce industries.</li>
<li>Data grids as 	clustering  toolkits – Data grids can also act as toolkits for 	introducing high  availability and failover to opensource, commercial 	or in-house  frameworks or reusable architectures. It may also aide 	in delegating  all state management to data grid which in turns helps 	frameworks to be  stateless and hence elastic which could be very 	important for cloud.</li>
<li>Data  grids 	used as cloud storage (NoSQL key/value store) – Traditional 	 databases are hard to deal with short lived clouds. As all cloud 	 components are expected to be elastic and highly available, 	Infinispan  fits in appropriately.</li>
</ul>
<p>To summarize, Infinispan is an opensource, in-memory, highly available and elastic data grid platform which can be used as:</p>
<ul>
<li>A fast, 	powerful local cache to boost performance.</li>
<li>A fast, 	available, distributed and elastic data grid.</li>
<li>A combination 	of Infinispan caches and data grids can be used to create high 	performance and scalable near caches.</li>
</ul>
<p>Watch out this space for some hands-on Infinispan.</p>
<p>For more information, visit <a href="http://www.infinispan.org/" target="_blank">http://www.infinispan.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/15/infinispan-%e2%80%93-the-path-covered/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blackberry: Support For Multiple Screens (Fonts)</title>
		<link>http://xebee.xebia.in/2012/02/15/blackberry-support-for-multiple-screens-fonts/</link>
		<comments>http://xebee.xebia.in/2012/02/15/blackberry-support-for-multiple-screens-fonts/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 05:18:56 +0000</pubDate>
		<dc:creator>sraheja</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11522</guid>
		<description><![CDATA[One of the major challenge with Blackberry Application development is adding support for multiple screens with varying sizes and pixel density. Your application must scale up or down as per the screen resolution (width, height and pixel density). In order to do it right, you must ensure scaling up and down is handled correctly for [...]]]></description>
			<content:encoded><![CDATA[<p>One of the major challenge with Blackberry Application development is adding support for multiple screens with varying sizes and pixel density. Your application must scale up or down as per the screen resolution (width, height and pixel density). In order to do it right, you must ensure scaling up and down is handled correctly for all</p>
<table align="left" border="0">
<tbody>
<tr>
<td></td>
<td></td>
<td>
<ul>
<li><span style="font-size: small;">Texts, </span></li>
<li><span style="font-size: small;">Images and</span></li>
<li><span style="font-size: small;">Layouts</span></li>
</ul>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>in your application. In this article, we will focus primarily on Texts. So the problem statement for now is "<strong>How one can ensure all texts are scaled up correctly on multiple Blackberry devices?</strong>". I will share more information on Images and Layouts in future blogs.</p>
<p><strong><span id="more-11522"></span> </strong></p>
<p><strong>Base Resolution</strong><br />
Well to start with, pick a base screen resolution and develop your application for that. Generally it is easier to scale up, so one should chose base resolution as 320x240_162 where width = 320, height = 240 and pixel density = 162.</p>
<p><strong>Ui.UNITS_pt</strong><br />
Blackberry automatically scales fonts which are specified in points. So make sure, in your application, fonts for all texts are specified in points rather than pixels. Fonts specified in pixels may look smaller or larger depending on the pixel density of the device. However, those specified in points will appear almost similar on all devices.</p>
<p>For example you can set default font for your application by:</p>
<pre class="brush: java; title: ; notranslate">
Font font = FontFamily.forName(&quot;BBGlobal Sans&quot;).getFont(Styles.APPLICATION_FONT_STYLE,
        Styles.APPLICATION_FONT_SIZE, Ui.UNITS_pt);
FontManager.getInstance().setApplicationFont(font);
</pre>
<p>where Styles is a custom class to consolidate all styles at one place. Similarily, you can change font of a RichTextField by:</p>
<pre class="brush: java; title: ; notranslate">
titleRTF.setFont(Font.getDefault().derive(Styles.TITLE_FONT_STYLE,
        Styles.TITLE_FONT_SIZE, Ui.UNITS_pt));
</pre>
<p><strong>Run-time Validation</strong><br />
Automatic scaling of fonts (specified in points) is good and will resolve most of the issues related to text scaling. However, still there might be some areas where scaling has not happened as desired. For example, on a specific device, there can be a button whose label is now getting truncated or at other place text has become larger then its specified container and does not fit in any more etc etc.</p>
<p>For such boundry cases, you can make a runtime check and adjust the font size accordingly, ofcourse, in agreement with UI Designer and the Product Owner. You can do that by:</p>
<pre class="brush: java; title: ; notranslate">
ButtonField customButton = new ButtonField(&quot;Continue&quot;) {
        public int getPreferredWidth() {
                return Display.getWidth() / 4;
        }
};

Font customFont = Font.getDefault().derive(Styles.BUTTON_FONT_STYLE,
        Styles.BUTTON_FONT_SIZE, Ui.UNITS_pt);

LabelField validatorLF = new LabelField(customButton.getLabel());
validatorLF.setFont(customFont);

int contentWidth = validatorLF.getPreferredWidth();
int i = 1;
while(contentWidth &gt; (customButton.getPreferredWidth() - Styles.CONTENT_PADDING_LEFT -
        Styles.CONTENT_PADDING_RIGHT)) {
                customFont = Font.getDefault().derive(Styles.BUTTON_FONT_STYLE,
                                Math.max((Styles.BUTTON_FONT_STYLE - i), 3), Ui.UNITS_pt);
                validatorLF.setFont(customFont);
                contentWidth = validatorLF.getPreferredWidth();
                i++;
}

customButton.setFont(customFont);
</pre>
<p>In the above example, we have a "Continue" button whose width is one-fourth of the screen width. For most of the devices "Continue" label scales correctly. However, on few devices, the label gets truncated.</p>
<p>So, what we are doing here is we are reducing the font size incrementally by 1 point until it fits perfectly well in the specified button size. We have also set the minimum font size to make sure it is readable. Kindly note, we have reduced the font size since we have fix container (Button) width (one-fourth of the screen size).</p>
<p>This trick comes quite handy when we have to adjust font by one or two points for few devices. In the follow-up blog, I will share my thoughts how we should handle challenges with images and layout scaling for multiple screens.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/15/blackberry-support-for-multiple-screens-fonts/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Liferay 5.2x &#124; Mobile Cookbook</title>
		<link>http://xebee.xebia.in/2012/02/09/liferay-5-2x-mobile-cookbook/</link>
		<comments>http://xebee.xebia.in/2012/02/09/liferay-5-2x-mobile-cookbook/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 11:52:00 +0000</pubDate>
		<dc:creator>Megha</dc:creator>
				<category><![CDATA[Liferay]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11371</guid>
		<description><![CDATA[Recently, I was researching upon how to support mobile versions of the websites on Liferay 5.2x. This post would mainly talk about the changes need to be done in Liferay 5.2x to accomplish the same. Liferay 5.2x has  in-built support for providing different themes and layouts for the WAP enabled devices. Primary mark-up language in [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I was researching upon how to support mobile versions of the websites on Liferay 5.2x. This post would mainly talk about the changes need to be done in Liferay 5.2x to accomplish the same.</p>
<p>Liferay 5.2x has  in-built support for providing different themes and layouts for the WAP enabled devices. Primary mark-up language in WAP enabled devices is XHTML Mobile Profile whereas current smart phones browsers are HTML recommended. WAP has become an old school and thus it calls for extending Liferay 5.2x to support Smart phones.</p>
<p>To support mobileVersion of the website we need to find answer to following 3 questions.</p>
<ol>
<li>How to detect it is a mobile device ?</li>
<li>How to get the theme for the mobile device and ask it to use that theme ?</li>
<li>How to get the page layout for the mobile device and ask it to use that layout ?</li>
</ol>
<div>
<p><span id="more-11371"></span></p>
<div><strong>Mobile Device Detection</strong></div>
<div>Before picking up any strategy, we need to ramp up the device detection capabilities of  Liferay 5.2x, so that it can detect our new smartPhones. This can be done by overriding <em>isMobile() </em>in <em>BrowserSnifferUtil.java</em>. <em>isMobile() </em>method would read user-agent from request and with the help of <a href="http://wurfl.sourceforge.net/">WURFL </a>device repository, it can determine if it is mobile.</div>
<div><strong>Themes and Layouts</strong></div>
</div>
<div>Path to Question 2 and 3 can be found through the following strategies:</div>
<div>Strategy 1 -  <strong>Single Site Strategy </strong>: This mainly is used when  content across the devices is almost same with a variations in the look and feel.  It can be implemented in 2 ways:</div>
<div>
<ol>
<li><b>Responsive Web design:</b> It states managing look and feel (CSS) based on screen size of the device. It can be implemented using CSS media queries and/or JavaScript. Liferay 6, provides same support through AUI().use('aui-viewport').</li>
<li><b>Seperate Themes: </b>It involves defining seperate themes for different devices. A mechanism would detect (to be coded) the device from which the request is coming and based on that it will apply the  theme defined for the device.</li>
</ol>
</div>
<div>Strategy 2 -  <strong>Multiple Site Strategy</strong>: Mutli-site involves developing mobile specific sites and it finds it place when the content across the devices differ. For instance: Facebook mobile version is m.facebook.com. This can be implemented on liferay as separate communities .It can also easily provide support of different sites for different devices (android/ iphone) by having device specific community.</div>
<div></div>
<div></div>
<div>In multiple site strategy, after the device is been detected as mobile it will be redirected to mobile specific site. Since it is a separate community  in itself, it will have its own theme and its own page layout which would be specific to mobile.</div>
<div></div>
<p><br/></p>
<div>Now lets see, how the questions 2 and 3 can be resolved for the <strong>single site strategy</strong>. It can be done with the following 2 approaches:</div>
<div><strong>Approach 1 : </strong>It is based upon leveraging the existing WAP support on Liferay 5.2x.</div>
<div>
<ul>
<li>It uses WAP theme as a mobile theme which we can specify for a page through <em>mobile devices</em> in<em> look and feel </em>tab of a page.  To make a HTML theme as a wap theme, enable property &lt;wap-theme&gt; for the theme in liferay-look-and-feel.xml</li>
<li>It uses the WAP version of the layout applied on each page.</li>
<li>It supports single theme and layout for all mobile devices, CSS can be made device dimension specific by CSS media queries.</li>
</ul>
<div>How Liferay5.2x supports WAP ?:</div>
<div>
<ul>
<li> it picks up WAP theme/HTML theme in <em>ServicePreAction.java</em> depending upon <em>isWap()</em>.</li>
<li>it picks up WAP/HTML path from <em>includeLayoutContent() </em>in <em>LayoutAction</em> depending upon <em>isWap()</em>. If <em>isWap()</em> then it calls <em>LayoutLocalServiceUtil.getWapContent() </em>in wap/../<em>layout/view/portlet.jsp </em>else  it calls<em> <em>LayoutLocalServiceUtil.getContent()</em></em> in html<em>/../<em>layout/view/portlet.jsp. </em></em></li>
<li>it picks up jsps from WAP/HTML path depending upon <em>isWap()</em>.<em><em><br />
</em></em></li>
<li>Response type is set to ContentTypes.XHTML_MP if <em>isWap()</em>.</li>
</ul>
</div>
<div></div>
<div>Now the question arises how to make it mobile specific.  It can be done in 2 ways.</div>
<div>Solution1 :</div>
<div>
<ul>
<li>Override  <em>ServicePre() </em> in<em> ServicePreAction.java</em> to incorporate check for the <em>isMobile() </em>and if found true use Wap theme.</li>
<li>Override html<em>/../<em>layout/view/portlet.jsp </em></em>to include check for <em>isMobile() and if found true use <em>LayoutLocalServiceUtil.getWapContent(). </em></em></li>
</ul>
<div>Solution 2:</div>
<div>
<ul>
<li>Override <i>isWap() </i>to return true if <em>isMobile()</em> is true.</li>
<li>Change contentTypes in pages/classes used by wap implemention from ContentTypes.XHTML_MP to ContentTypes.TEXT_HTML.</li>
</ul>
<div><strong>Approach 2: </strong>Build a separate path for mobile on the same lines as HTML and WAP works. It would involve overriding theme/ layout to have support for mobile same as it has for WAP. UI support in manage pages through which theme can be defined for mobile. Besides that<em>ServicePre() </em> in<em> ServicePreAction.java </em> to use mobile theme when isMobile. It would involve a lot of more work and can be made all together a seperate feature as we have in suppport in Liferay 6.1 provided by <a href="http://milen.commsen.com/2011/03/liferay-multidevice-extension.html">Milen Dyankov</a>.</div>
<div></div>
</div>
<div></div>
<p><br/></p>
<div>I hope the blog helps you in providing direction for mobile support for sites in Liferay 5.2x. Please refer to the following links for further reference:</div>
<div><a href="http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/8907527">http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/8907527</a></div>
<div><a href="http://milen.commsen.com/2011/03/liferay-multidevice-extension.html">http://milen.commsen.com/2011/03/liferay-multidevice-extension.html</a></div>
<div><a href="http://www.liferay.com/community/forums/-/message_boards/message/7864566">http://www.liferay.com/community/forums/-/message_boards/message/7864566</a></div>
<div></div>
</div>
<div></div>
<div></div>
<div></div>
</div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/09/liferay-5-2x-mobile-cookbook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Semantic based web search engines- Changing the world of Search</title>
		<link>http://xebee.xebia.in/2012/02/08/semantic-based-web-search-engines-changing-the-world-of-search/</link>
		<comments>http://xebee.xebia.in/2012/02/08/semantic-based-web-search-engines-changing-the-world-of-search/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 10:25:13 +0000</pubDate>
		<dc:creator>Prachi Nagpal</dc:creator>
				<category><![CDATA[Semantic Web]]></category>
		<category><![CDATA[Web 3.0]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[web 3.0]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11237</guid>
		<description><![CDATA[An important quality that the majority of search engines functional today lack is the ability to take into account the intention of the user behind the overall query. Basing the matching of web pages on keyword frequency and a ranking metric such as Pagerank return various results that may be of high ranking but still [...]]]></description>
			<content:encoded><![CDATA[<p>An important quality that the majority of search engines functional today lack is the ability to take into account the intention of the user behind the overall query. Basing the matching of web pages on keyword frequency and a ranking metric such as <a target="_blank" href="http://en.wikipedia.org/wiki/PageRank">Pagerank </a>return various results that may be of high ranking but still irrelevant to the users intended context. Therefore I explored with my friend Sumedha and realized that there  is a need to add <a target="_blank" href="http://en.wikipedia.org/wiki/Semantic_search">semantics</a> to the web search.</p>
<p>There are some semantic search engines that have already come up in the markets eg. Hakia, Swoogle, Kosmix, etc. that takes a semantic based approach which is different from the traditional search engines. I really liked their idea of  implementing and adding semantics to the web search. This provoked me to do more research in this field and tried to think of different ways to add semantics. <span id="more-11237"></span></p>
<p>Following is an <i>Algorithm </i>that can be used in <i>Semantic Based Web Search Engines</i> :-</p>
<p>So, to find web pages on the internet that match a user’s query based not only on the important keywords in a user query, but also based on the intention of the user, behind that query, first the user’s entered query is expanded using <a target="_blank" href="http://en.wikipedia.org/wiki/WordNet">WordNet</a> ontology.</p>
<p>This Algorithm focuses on work that uses the <i>Hypernym</i>/<i>Hyponymy </i>and<i> Synset </i>relations in WordNet for query expansion algorithm. A set of words that are highly related to the words in the user query, determined by the frequency of their occurrence in the <i>Synset</i> and <i>Hyponym</i> tree for each of the user query terms is created.  This set is now refined using the same relations to get a more precise and accurate expanded query.</p>
<h1><span style="font-size: small"><b>Query Expansion Using Semantics</b></span></h1>
<p>Let the user input query consisting of a set of query terms Q<sub>i </sub>be:</p>
<p>Q = {q<span style="font-size: xx-small">1</span>, q<span style="font-size: xx-small">2</span>,...................q<span style="font-size: xx-small">t</span>}                                          (1)</p>
<p>The next step is to find the set <i>EQ</i> consisting of the semantically expanded user Query <i>Q</i>.</p>
<p>EQ = {eq<span style="font-size: xx-small">1</span>, eq<span style="font-size: xx-small">2</span>, .........eq<span style="font-size: xx-small">m</span>}                                         (2)</p>
<p>The set <i>EQ</i> can then be used to return a list of web pages that match the expanded query and are ranked according to highest relevance first.</p>
<h2><span style="font-size: small"><b><i>Query Preprocessing</i></b></span></h2>
<p>When the search engine is initially begun, a HashSet of commonly used English words is created globally, to be used for stop word removal each time a user query is inputted. This helps in elimination of noise data and reducing redundancy during context creation.</p>
<p>On the search engine, a user is asked to enter a String Query, <i>Q</i>. This query is now tokenized into separate <i>‘t’</i> Query terms by removing white spaces to get (1). We now perform stop word removal using the hashset of common English words defined during the backend processing to get a refined set of <i>‘n’</i> query terms,</p>
<p>Q' = {q'<span style="font-size: xx-small">1</span>, q'<span style="font-size: xx-small">2</span>, ............... q'<span style="font-size: xx-small">n</span>}                                     (3)</p>
<p>This set <i>Q </i>is now used for semantic query expansion.</p>
<h2><span style="font-size: small"><b><i>Algorithm </i></b></span></h2>
<p>The complete algorithm used for Query Expansion is:</p>
<p><i> </i></p>
<p><i>Algorithm</i> : QueryExpansion</p>
<p><b><i>Input</i></b>: User Query</p>
<p><b><i>Output</i></b>: Refined Expanded Query</p>
<p>1.     Input<i> Q = {q<sub>1</sub>, q<sub>2</sub>, …, q<sub>t</sub>}</i> from user.</p>
<p>2.     Perform tokenization and stop word removal to get refined query <i>Q’ = {q’<sub>1</sub>, q’<sub>2</sub>, … q’<sub>n</sub>}</i></p>
<p>3.     Use synset <i>S(EQ)</i> and hyponymy relationships to get expanded query <i>EQ</i>.</p>
<p>4.     Create a hierarchical structure of terms <i>eq<sub>i</sub></i> in expanded query to get context string <i>C</i>.</p>
<h1><span style="font-size: small"><b>Finding Content for user Context</b></span></h1>
<p>To find web pages that are relevant to the users’ intention, a directory of the web that categorizes web pages according to their content is needed. For this purpose, the <a target="_blank" href="http://www.dmoz.org/%20">Open Directory Project</a>, which is a human-edited directory of the web can be used. Similarly, to find text content that is related to the users’ intention, content can be extracted from the DBpedia.org Project (<a target="_blank" href="http://dbpedia.org/About">DBpedia</a>). It allows extraction of structured information from <a target="_blank" href="http://www.wikipedia.org/%20">Wikipedia</a>.</p>
<h2><span style="font-size: small"><b><i>Retrieval of Relevant URLs</i></b></span></h2>
<p>The <a target="_blank" href="http://www.dmoz.org/rdf.html">RDF dump</a> of the ODP provides a list of all the possible categories found within it . The Context String found after the QueryExpansion algorithm is matched to all the categories within the ODP to retrieve the top ten category matches. These top ten matches are then displayed to the user using our user-interface and he/she is asked to select the category that according to them is the closest to their intention. This is called <i>CAT.</i></p>
<p>Once we have the correct category, we can create an online connection to the ODP to retrieve all the URLs that fall within that category. This can be done by tokenizing the CAT string and passing it as a query to the ODP search box.</p>
<h2><span style="font-size: small"><b><i>Retrieval of Relevant Content</i></b></span></h2>
<p>Now to display some relevant, concise text content to the user, along with the URLs, so that the user has immediate access to some information related to his user query. For this, the CAT string is tokenized into keywords and the ‘Keyword Search’ feature of DBpedia is used to retrieve a list of Uniform Resource Identifiers (URI) that matches this tokenized CAT string. These URIs are sorted according to maximum match the keywords by DBpedia. The first URL in the list returned by DBpedia is now used for content retrieval.</p>
<p>The requirement now is to extract some text content from this DBpedia resource that can be used to display to the user. For this, use of automated queries written in the <a target="_blank" href="http://www.w3.org/TR/rdf-sparql-query/">SPARQL</a> Query Language for RDF (SPARQL) is made. Using this automated query, extract a short abstract, written in English language that describes the resource in a brief manner is extracted and stored.</p>
<h2><span style="font-size: small"><b><i>Semantics Based Search Engine</i></b></span></h2>
<p>To display the above results to the user, a user interface called the Semantics Based Search Engine (SBSE) is created in the form of a website.</p>
<p>The home page of the website asks the user to enter his query. Once the user enters his query and presses the ‘Search’ button, he is redirected to a page that shows him a dropdown list of the top ten matching ODP categories that were found after comparison with the context string <i>C. </i>Once the user selects the most relevant category, he is directed to a page that uses frames to display the short abstract retrieved from DBpedia in the left frame and a list of relevant URLs in the right frame.</p>
<p><span style="font-size: small"><b>Conclusion</b></span></p>
<p>I observed that above <i>QueryExpansion </i>Algorithm gave expanded queries that were more concise and accurate with respect to the user intention as compared to previous work done in this field. As the size of the query increases, so did the accuracy of the QueryExpansion algorithm. Displaying a short text abstract, along with the relevant URLs, was found to be more efficient as the user could see information at the search engine website itself, thereby saving time.</p>
<p>For Reference, refer to this <a target="_blank" href="https://docs.google.com/open?id=0B4a0aKPbgkGpNzI3MDc4NWItZTY0Ni00YmZlLWE5MDEtZWFiNjQxZTc2YTdj">file </a>for the data set used and results obtained by executing the above algorithm on Java platform. A user interface was created using Java Server Pages(JSP) and Apache Tomcat.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/08/semantic-based-web-search-engines-changing-the-world-of-search/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Nodemap &#8211; First product of my Nodejs playground</title>
		<link>http://xebee.xebia.in/2012/02/07/nodemap-first-product-of-my-nodejs-playground/</link>
		<comments>http://xebee.xebia.in/2012/02/07/nodemap-first-product-of-my-nodejs-playground/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 09:31:19 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[Google Maps API]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[nowjs]]></category>
		<category><![CDATA[expressjs]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[joyent cloud]]></category>
		<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11297</guid>
		<description><![CDATA[I started learning Nodejs few weeks back and fell in love with the way it eases the development of real-time web applications. In general, when I start learning a new technology I try to make an app out of that learning. In that process, the most challenging task is "What to develop?" rather than How [...]]]></description>
			<content:encoded><![CDATA[<p>I started learning Nodejs few weeks back and fell in love with the way it eases the development of real-time web applications. In general, when I start learning a new technology I try to make an app out of that learning. In that process, the most challenging task is "What to develop?" rather than How to develop? Finally an interesting app idea came into my mind and I was able to turn that idea into an application. So here I am explaining the app and its code in detail.</p>
<p><a href="http://nodemap.no.de">NodeMap</a> : A realtime Nodejs application with Express, Nowjs, Ejs, Google Maps, Mongodb hosted on Joyent SmartMachines. What does this app do? It simply shows real-time messages on the world map from different users around the world in an awesome way.<br />
<a href="http://nodemap.no.de" style="color:blue; font-size:12px;"><strong>Click Here To See Working App</strong></a><br />
<span id="more-11297"></span><br />
First things first, the technology aspect :</p>
<ul>
<li><strong>Why Nodejs?</strong> Because its awesome and amazingly fast server side javascript.(For more info refer <a target="_blank" title="Nodejs Homepage" href="http://nodejs.org">Nodejs Homepage</a>).</li>
<li><strong>Why Express?</strong> Because I wanted a Web-MVC and this one is the best out there, with community support.(For more info refer <a target="_blank" title="Expressjs Web MVC" href="http://expressjs.com/">Expressjs Web MVC</a>)</li>
<li><strong>Why Nowjs?</strong> Because it allows me to "Call client functions from the server and server functions from client".(It internally uses socket.io, for more info refer <a target="_blank" title="Nowjs" href="http://nowjs.com/">Nowjs</a>)</li>
<li><strong>Why ejs?</strong> Because this template engine is very similar to html. So it was easy to grasp.(low learning curve For more info refer <a target="_blank" title="EJS" href="https://github.com/visionmedia/ejs">EJS</a>)</li>
<li><strong>Why Google Maps?</strong> Because I wanted to show some maps in my app. (For more info refer <a target="_blank" title="Google Maps API v3" href="http://code.google.com/apis/maps/documentation/javascript/">Google Maps API v3</a>)</li>
<li><strong>Why Mongodb?</strong> Because I wanted a light-weight NoSQL database which can easily run on Joyent SmartMachines.(For more info refer <a target="_blank" title="Mongodb" href="http://www.mongodb.org/">Mongodb</a>)</li>
</ul>
<p>Lets deep dive into the application code, here is the link to <a target="_blank" title="Nodemap" href="https://github.com/vijayrawatsan/nodemap">Github Repository</a>.</p>
<p>In a real-time web application both server side and client side code plays vital role in the proper functioning of the applicaiton. So I will switch between server-side code and client-side code while explaining the code.</p>
<p>Lets start with the server side snippet below :</p>
<pre class="brush: jscript; title: ; notranslate">
//Module dependencies.
var express = require('express'), nowjs = require('now'), mongojs = require('mongojs');
//starting server
var app = express.createServer().listen(80);
//Server configuration
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.static(__dirname + '/public'));
});
//Initialize mongojs to connect with mongodb
var db = mongojs.connect('nodemapdb', ['mycollection']);
//Initialize nowjs for real-time client-to-server and server-to-client calls
var everyone = nowjs.initialize(app, {socketio: {transports: ['xhr-polling', 'jsonp-polling']}});
</pre>
<p>Server side code starts with including the required dependencies( which are expressjs, nowjs and mongojs) and configuring them appropriately. Lets have a look at each one of them :<br />
<strong>Express</strong><br />
Line 4 creates a HttpServer to listen on port 80.<br />
Line 6 starts with configuration of the server.<br />
Line 7 sets the views directory path.<br />
Line 8 sets the view engine to ejs (if we don't set it the default jade view engine will be used).<br />
bodyParser() parses the request body and populates req.body<br />
methodOverride() checks req.body.method for the HTTP method override(i.e override to GET/POST/PUT etc.)<br />
Line 11 sets the static resource directory which will serve the static resources to the client.<br />
Thats all with express(for more info. please refer <a target="_blank" href="http://expressjs.com/guide.html">Express Guide</a>)</p>
<p>&nbsp;</p>
<p><strong>Mongojs</strong><br />
Line 14 initializes mongojs and configures it to connect with database 'nodemapdb' and collection 'mycollection'. For more configuration options refer : <a target="_blank" href="https://github.com/gett/mongojs/blob/master/README.md">Mongojs Read Me</a></p>
<p><strong>Nowjs</strong><br />
Line 16 initializes nowjs to work with the current HttpServer and explicitly set the socket.io transport to xhr or json polling. The second parameter is optional and by default uses websockets as first priority. I have explicitly set it because my application host does not support websockets on free accounts.</p>
<p>Now lets see how the request to home page is handled :</p>
<pre class="brush: jscript; title: ; notranslate">
app.get('/', function(req, res){
	var dataArray=[];
	db.mycollection.find({},{_id:0}).forEach(function(err, doc) {
		if (!doc) {
			// we visited all docs in the collection
			res.render('index', { title: 'NodeMap : Using Nodejs,Nowjs,Mongodb &amp; Google Maps ' , messages : JSON.stringify(dataArray)});
			return;
		}
		dataArray.push(doc);
	});
});
</pre>
<p>Whenever a person hits <a target="_blank" href="http://nodemap.no.de">http://nodemap.no.de</a> the above app.get("/",...) method will be called. What I am doing here is, simply getting all the documents stored in the database(without the "_id" field). And for each document found, it is pushed in "dataArray" and finally a call to <strong>res.render</strong> which will render the <strong>index.ejs</strong> in the views directory, and, since I haven't set <strong>"layout : false"</strong> while configuring the server, the contents of <a target="_blank" href="https://github.com/vijayrawatsan/nodemap/blob/master/views/index.ejs">index.ejs</a> will be rendered as "body" of <a target="_blank" href="https://github.com/vijayrawatsan/nodemap/blob/master/views/layout.ejs">layout.ejs</a>(the concept of layouts in express is similar to concept of master-pages).</p>
<p>&nbsp;</p>
<p>Now lets see how the initial markers are set on the map(client-side code):</p>
<pre class="brush: jscript; highlight: [15]; title: ; notranslate">
&lt;body onload=&quot;initialize();&quot;&gt;
&lt;div id=&quot;map_canvas&quot; &gt;&lt;/div&gt;
&lt;div id=&quot;form-wrapper&quot; style=&quot;z-index: 1000002; position: absolute; right: 0px; bottom: 0px; &quot;&gt;
	&lt;div id=&quot;form1&quot;&gt;
		Name : &lt;input id=&quot;owner&quot; type=&quot;text&quot; /&gt;&lt;br/&gt;
		Message : &lt;input id=&quot;message&quot; type=&quot;text&quot; /&gt;&lt;br/&gt;
		&lt;input id=&quot;locationCheck&quot; type=&quot;checkbox&quot; &gt;Use my location&lt;/input&gt;&lt;br/&gt;
		&lt;div id=&quot;cord&quot; style=&quot;display:none;&quot;&gt;
			Latitude : &lt;input id=&quot;latitude&quot; type=&quot;text&quot; /&gt;&lt;br/&gt;
			Longitude : &lt;input id=&quot;longitude&quot; type=&quot;text&quot; /&gt;
		&lt;/div&gt;
		&lt;input type=&quot;button&quot; value=&quot;Submit&quot; onclick=&quot;getGeoLocation();&quot;/&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;messages&quot; style=&quot;display:none;&quot;&gt;&lt;%=messages%&gt;&lt;/div&gt;
&lt;/body&gt;

&lt;script&gt;
function initialize() {
	var mapOptions = {
		maxZoom: 9,
		minZoom:2,
		zoom: 2,
		center: new google.maps.LatLng(27, 30),
		mapTypeControl: false,
		streetViewControl: false
	};
	var mapType = new google.maps.StyledMapType([
	    {
		featureType: &quot;all&quot;,
		elementType: &quot;all&quot;,
		stylers: [
		    { visibility: &quot;off&quot; },  // Hide everything
		    { lightness: 100 }  // Makes the land white
		]
	    }, {
		featureType: &quot;water&quot;,
		elementType: &quot;geometry&quot;,
		stylers: [
		    { visibility: &quot;on&quot; },  // Show water, but no labels
		    { lightness: -9 },  // Must be &lt; 0 to compensate for the &quot;all&quot; lightness
		    { saturation: -100 }
		]
	    }
	]);
	map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;), mapOptions);
	map.mapTypes.set('styledMapType', mapType);
	map.setMapTypeId('styledMapType');

	var messages = JSON.parse($(&quot;#messages&quot;).html());
	var size = messages.length;
	for(var i=0; i&lt;messages.length; i++){
		message = messages[i];
		if(size -i &lt; 50 ) {
			setTimeout((function(msg) {
				return function() {
				    addMarker(msg);
				}
		    	})(message), i*400 + Math.random()*500+500);
		}else{
			addMarkerDefault(message);
		}
	}
}
function addMarker(message){
	var marker = new google.maps.Marker({
		map: map,
		animation: google.maps.Animation.DROP,
		position: new google.maps.LatLng(message.latitude,message.longitude),
		icon: image
	});
	var infowindow = new google.maps.InfoWindow({
		content: message.owner+&quot; : &quot;+message.message
	});
	addNewListener(map,marker,infowindow);
}
&lt;/script&gt;
</pre>
<p>The above code does some important things :</p>
<p>&nbsp;</p>
<ul>
<li>The code at line 2, assigns the <strong>messages</strong> data passed in res.render(server side) call to the div with "<strong>id=messages</strong>".</li>
<li>Code in the script tag, initializes Google Maps with some styling applied to it,</li>
<li>And then parses the JSONified documents and places a marker on the Google Map corresponding to that document.</li>
</ul>
<p>This completes the initial rendering of the home page. Now lets see some interesting stuff, how I call server-side declared method from client side. For that, see the code below:</p>
<pre class="brush: jscript; title: ; notranslate">
//written server-side
everyone.now.addMarkerServer = function(msg){
	console.log(msg);
	db.mycollection.save({	owner : msg.owner,
			message : msg.message,
			latitude : msg.latitude,
			longitude: msg.longitude
		}, function (err, res) {
		// Handle response
		console.log(res);
	});
	everyone.now.addMarkerClient(msg);
};

//written client side
now.ready(function(){
	now.addMarkerClient = function(data) {
		addMarker(data);
	};
});
</pre>
<p>NowJS uses the excellent socket.io and node-proxy libraries. It creates a namespace "<strong>now</strong>", accessible by server and client. Functions and variables added to <strong>now</strong> are automatically synced, in real-time. Whenever user submits a message, <strong>now.addMarkerServer(msg)</strong> is called which actually calls the <strong>server-side declared</strong> addMarkerServer function.</p>
<p>&nbsp;</p>
<p>In addMarkerServer, the data passed is saved in the database and it calls everyone.now.addMarkerClient(msg); with the same data. Any method server calls to the <strong>everyone.now</strong> namespace gets called on every client's side(there can be thousands of client).</p>
<p>So in this blog post we learned how cool nodejs is and how easy it is to develop real time applications using nodejs. Although, I have used it very naively in my small application but nodejs has already entered the enterprise. LinkedIn's mobile website's serverside is completely built on nodejs(<a target="_blank" href="http://venturebeat.com/2011/08/16/linkedin-node/">link</a>). Even Wallmart is set to use nodejs(<a target="_blank" href="http://venturebeat.com/2012/01/24/why-walmart-is-using-node-js/">link</a>).</p>
<p>Happy Reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/07/nodemap-first-product-of-my-nodejs-playground/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Selenium Web-Driver OR RC decide yourself?</title>
		<link>http://xebee.xebia.in/2012/02/07/selenium-web-driver-or-rc-decide-yourself/</link>
		<comments>http://xebee.xebia.in/2012/02/07/selenium-web-driver-or-rc-decide-yourself/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 19:08:57 +0000</pubDate>
		<dc:creator>ngaur</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11303</guid>
		<description><![CDATA[I have dealt with automation of multiple types of applications at its core level whether its desktop app, Silverlight app,or windows application. When we talk about web application automation, the most widely used automation tool is Selenium. Selenium is open-source tool and this makes selenium more powerful than any other tool. Now as Selenium-Webdriver (Selenium [...]]]></description>
			<content:encoded><![CDATA[<p>I have dealt with automation of multiple types of applications at its core level whether its desktop app, Silverlight app,or windows application.</p>
<p>When we talk about web application automation, the most widely used automation tool is Selenium. Selenium is open-source tool and this makes selenium more powerful than any other tool.</p>
<p>Now as Selenium-Webdriver (Selenium 2) has been released, everybody ask one question whether to switch to Webdriver from Selenium-Remote Control. So I would be discussing here the core technical differences between the two, as basic differences are already available at various places.<br />
<span id="more-11303"></span><br />
<strong>Following are some technical differences between Selenium's two flavor ie.WebDriver and RC.</strong></p>
<ul>
<li>Web Driver is designed to accurately simulate the way that a user will interact with a web application.A common approach for simulating user input is to make use of JavaScript to synthesize and fire the series of events that an app would see if a real user were to perform the same interaction.This "synthesized events" approach is fraught with difficulties as each browser, and sometimes different versions of the same browser, fire slightly different events with slightly different values.To complicate matters, most browsers won't allow a user to interact in this way with form elements such as file input elements for security reasons.Where possible Web Driver uses the alternative approach of firing events at the OS level. As these "native events" aren't generated by the browser this approach circumvents the security restrictions placed on synthesized events and, because they are OS specific, once they are working for one browser on a particular platform reusing the code in another browser is relatively easy.</li>
</ul>
<div></div>
<ul>
<li>The WebDriver developers lean more towards finding and isolating the complexity in a few places rather than spreading it out. One reason for this is users. As an example, consider the following methods from the original Selenium API, each of which can be used to set the value of an input element : type, typeKeys, typeKeysNative, keydown,keypress,keyup,keydownNative,keypressNative,keyupNative,attachFile. Here's the equivalent in the WebDriver API: sendKeys</li>
</ul>
<div></div>
<ul>
<li> <strong>WebDriver Design</strong> : The Webdriver team refers to WebDriver's API as being "object-based". The interfaces are clearly defined and try to adhere to having only a single role or responsibility,but rather than modeling every single possible HTML tag as its own class webdriver developer only have a single WebElement interface.  The result is that coding sessions may look like this (in Java):</li>
</ul>
<blockquote>
<p style="text-align: left"><span style="color: #e34f1b"> WebDriver driver = new FirefoxDriver();</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> driver.&lt;user hits space&gt;</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> At this point, a relatively short list of 13 methods to pick from appears. The user selects one:</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> driver.findElement(&lt;user hits space&gt;)</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> While RC doesn't define a webelement rather it get the object at run time based on the locator given by user. This result in coding session like this</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> Selenium selenium = new defaultSelenium(&lt;host&gt;,&lt;port&gt;,&lt;browser&gt;,&lt;url&gt;);</span></p>
<p style="text-align: left"><span style="color: #e34f1b"> selenium.click(&lt;locator&gt;);</span></p>
<p>Apart from cleaner Api,this webdriver approach allow user to do lot of manipulations based on requirements with Object before performing actual operation on test  object.</p></blockquote>
<ul>
<li><span><span style="font-family: sans-serif">Selenium makes use of a layered set of libraries</span></span> as a mechanism to interrogate the DOM. <span style="font-family: sans-serif">The bottom layer is Google's Closure Library, which supplies primitives and a modularization mechanism allowing source files to be kept focused and as small as possible.. Within the project, these are viewed as offering the smallest units of browser automation, and so are called Browser Automation Atoms or atoms. Finally, there ar</span><span style="font-family: sans-serif">e adapter layers that compose atoms in order to meet the API contracts of both WebDriver and Core.</span></li>
<div><span style="color: #0000ee;font-family: sans-serif"><span style="text-decoration: underline"><br />
</span></span><span style="font-family: sans-serif"> ﻿<a rel="attachment wp-att-11324" href="http://xebee.xebia.in/2012/02/07/selenium-web-driver-or-rc-decide-yourself/untitled-2/"><img class="aligncenter size-full wp-image-11324" height="237" width="243" src="http://xebee.xebia.in/wp-content/uploads/2012/02/Untitled.png" /></a></span></div>
</ul>
<div><span style="font-family: sans-serif"><br />
</span></div>
<div><span style="font-family: sans-serif">Due to Atoms ,a layer emulating the existing RC implementation but backed by WebDriver is an important tool for teams looking to migrate in a controlled fashion to the newer WebDriver APIs.</span></div>
<p><strong>Looking future of Webdriver:</strong></p>
<p><span style="color: #000000"><span style="font-family: sans-serif">There will always be browsers that WebDriver can't integrate tightly to, so there will always be a need for Selenium Core. Migrating this from its current traditional design to a more modular design based on the same Closure Library that the atoms are using is underway. Webdriver developer also expect to embed the atoms more deeply within the existing WebDriver implementations</span></span> .</p>
<p>More details can be accessed from "<a href="http://www.aosabook.org/en/selenium.html">http://www.aosabook.org/en/selenium.html</a>".</p>
<p>In  next blog post, most probably I would be discussing on Webdriver's best usage to make automation reliable.</p>
<p><span style="color: #000000"><span style="font-family: sans-serif">Thanks <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/07/selenium-web-driver-or-rc-decide-yourself/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Opportunities and Challenges in Social Web Data Mining</title>
		<link>http://xebee.xebia.in/2012/02/02/opportunities-and-challenges-in-social-web-data-mining/</link>
		<comments>http://xebee.xebia.in/2012/02/02/opportunities-and-challenges-in-social-web-data-mining/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 09:34:46 +0000</pubDate>
		<dc:creator>Shruti Khattar</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[data mining]]></category>
		<category><![CDATA[Google Prediction API]]></category>
		<category><![CDATA[social web]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11222</guid>
		<description><![CDATA[Social Web Analysis focuses on the social, structural,and behavioral aspects of the social network. It is a media which produces up to one third of new Web content. Because the content always grows, is highly competitive and undergoes constant metamorphosis which is  studied by sociologists, physiologists and anthropologists to understand network evolution, belief formation, friendship [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: small;"> <span face="Times New Roman, serif">Social Web Analysis focuses on the social, structural,and behavioral aspects of the social network. It is a media which produces up to one third of new Web content. Because the content always grows, is highly competitive and undergoes constant metamorphosis which is  studied by sociologists, physiologists and anthropologists to understand network evolution, belief formation, friendship formation, etc. These relations and structural amalgamation influence the behavior and performance of almost all the real world entities. In this blog, I will be taking stock of mining the 'BIG DATA' <span id="more-11222"></span></span></span></p>
<p><strong><span style="font-size: small;" face="Times New Roman, serif"><span size="3"> </span></span></strong></p>
<p><strong><span style="font-size: small;" face="Times New Roman, serif"><span size="3">THE NEW BUZZWORDS FOR CONTENT GENERATION</span></span></strong></p>
<p><span style="font-size: small;"> <a href="http://xebee.xebia.in/2012/02/02/opportunities-and-challenges-in-social-web-data-mining/css-social-media-icons/" rel="attachment wp-att-11231"><img class="alignnone size-full wp-image-11231" title="css-social-media-icons" src="http://xebee.xebia.in/wp-content/uploads/2012/01/css-social-media-icons.png" width="600" height="200" /></a></span></p>
<p><strong><span style="font-size: small;"> </span></strong></p>
<p><strong><span style="font-size: small;"><span face="Times New Roman, serif"><span size="3"><i>Opportunities </i></span></span></span></strong></p>
<p><span style="font-size: small;" face="Times New Roman, serif">Managing the immeasurable data is not easy. But because of its affluence in features and patterns it gives rise to, and a way towards infinite scope of exploring, analyzing and channelizing the output in the desired direction. For example, users can then run Google MapReduce jobs to analyze this data for insight and factors such as new relationships. </span>We can use Google Prediction API is based on pattern matching and recognition approach to generate and filter data. <span style="font-size: small;" face="Times New Roman, serif">Given a set of data examples to train against, you can create applications that can perform the following tasks:</span></p>
<ul>
<li><span style="font-size: small;" face="Times New Roman, serif">Given a user's past viewing habits, predict what other movies or products a user might like.</span></li>
<li><span style="font-size: small;" face="Times New Roman, serif">Categorize emails or blogs as spam or non-spam.</span></li>
<li><span style="font-size: small;" face="Times New Roman, serif">Analyze posted comments about your product to determine whether they have a positive or negative tone.</span></li>
<li><span style="font-size: small;" face="Times New Roman, serif">Guess how much a user might spend on a given day, given his spending history.</span></li>
<li><span style="font-size: small;" face="Times New Roman, serif">Give recommendations on purchases based on his previous transactions</span></li>
</ul>
<p>Step 1 :  <strong>Upload training data </strong> to your Google Cloud Storage account in the bucket space.  This should ideally be in a .txt file or as JSON/GSON. This can be updated as and when needed.</p>
<p>Step 2: <strong>Train the system </strong>TrainingModel's insert method will take the Training data as an input file and analyze it. This is an asynchronous process, so you'll have to query the server periodically to check the status of the training session. Training must be complete before you can start to send queries.</p>
<p>There are 3 ways to interact with Google API:</p>
<ul>
<li>Google API REST client libraries</li>
<li>Apps Script : A JavaScript cloud scripting language</li>
<li>APIs Explorer : An interactive tool that lets you easily try out Google APIs right from your browser</li>
</ul>
<p>Step 3:  Now query the model and it will return the results based on the best guess at the language of your phrase. Each result has a likelihood score associated with it.</p>
<p>Lets dig into the social networking sites. The example of Facebook would be something we all can relate to. The profile of an individual, can provide two types of data. The first one is profile data and the other one is transactional data which can probably be educed from the wall posts, status messages, the communication with friends, the articles they have gone through or read, the apps and the games they have been involved in, the content that they have shared/liked, the pages they have subscribed to, monitoring their activities in timeline and likewise can be used to give meaningful and concrete information to assess the individual s characteristics and traits that can be leveraged for both personal and business gains.</p>
<p><span style="font-size: small;" face="Times New Roman, serif">Blog mining can explore the networking element of blogs, such as the use of hyperlinks between blogs and to outside sources of information. The literary aspect of blogging probes into the personal traits of an individual like nationality, political affiliation, thinking orientation and likewise based on his style. In my opinion, blogs are an important source of sentiment extraction as one is free to give words to their thoughts without sticking to a particular syntactical or semantic boundaries. The nature of posts, the comments that follow, can help in identifying and classifying the like minded people and also in reasoning their interpretations. Ranking the blogs on basis of in-and-out links or number of likes can be used to help determine their significance in the 'BlogSphere'. </span></p>
<p><strong><span style="font-size: small;" face="Times New Roman, serif"><span size="3"><i>Challenges</i></span></span></strong></p>
<p><span style="font-size: small;" face="Times New Roman, serif">Listed below are the weaknesses or limitations for social web mining.</span></p>
<p><span style="font-size: small;" face="Times New Roman, serif"><i>Finding a needle from the haystack</i> : The social web data is heterogeneous and lacks structure. A Web page typically contains a mixture of many kinds of information. The Web is dynamic and the content changes constantly. The arena of social networking data is highly fragmented. </span></p>
<p><span style="font-size: small;" face="Times New Roman, serif"><i>No standards for information retrieval : </i>There are no predefined ways to fetch information or guaranteeing the authenticity of data. </span></p>
<p><span style="font-size: small;" face="Times New Roman, serif"><i>Privacy policies and settings</i>: Media scrutiny, and easy data access to social networking sites is pushing users to designate their profile as private. While this certainly improves privacy, but is a challenge to data mining. </span></p>
<p><span style="font-size: small;" face="Times New Roman, serif"><i>Spam</i> has become a serious problem in blogs and social media, users and to systems that harvest, index and analyze generated content. Two forms of spam are common in blogs. Spam Blogs, or splogs where the entire blog and hosted posts are machine generated, and spam comments where authentic posts feature machine generated comments. They bring a new set of challenges for blog analytics. Similarly, the information derived from social networking sites is not something which can be relied upon completely.<a></a></span></p>
<p><strong><span style="font-size: small;" face="Times New Roman, serif"><span size="3"><i>Conclusion</i></span></span></strong></p>
<p align="left"><span style="font-size: small;" face="Times New Roman, serif">The above mentioned, was the SWOT analysis of social web mining from my point of view. Its versatility will always intrigue researchers and give scope for innovations and algorithms for data mining. But the fact  remains that the Web is a virtual society. It is not only about data, information and services, but also about interactions among people, organizations and automatic systems. They cannot be mapped to actual human responses. However, how close or far it is from the reality will always be a subject of discussion.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/02/02/opportunities-and-challenges-in-social-web-data-mining/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>OpenShift Express &#8212; The Future Of RedHat PaaS</title>
		<link>http://xebee.xebia.in/2012/01/26/openshift-express-the-future-of-redhat-paas/</link>
		<comments>http://xebee.xebia.in/2012/01/26/openshift-express-the-future-of-redhat-paas/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 13:23:42 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[openshift]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11145</guid>
		<description><![CDATA[Last couple of days I was at JUDCon India conference held in Bangalore where I gave a session on OpenShift. The JUDCon India was the biggest JUDCon conference ever with more than 800 attendees. Sessions were mainly on topics -- Infinispan, JBoss AS7 , OpenShift, CDI, Rules Engine, and other JBoss tools. I was mainly interested in hearing [...]]]></description>
			<content:encoded><![CDATA[<p>Last couple of days I was at <a data-mce-href="http://www.jboss.org/events/JUDCon/2012/india" href="http://www.jboss.org/events/JUDCon/2012/india">JUDCon India</a> conference held in Bangalore where I gave a session on <a data-mce-href="http://www.slideshare.net/shekhargulati/a-happy-cloud-friendly-java-developer-with-openshift." href="http://www.slideshare.net/shekhargulati/a-happy-cloud-friendly-java-developer-with-openshift.">OpenShift</a>. The JUDCon India was the biggest JUDCon conference ever with more than 800 attendees. Sessions were mainly on topics -- Infinispan, JBoss AS7 , OpenShift, CDI, Rules Engine, and other JBoss tools. I was mainly interested in hearing the thoughts of RedHat guys on OpenShift -- its future, comparison with Cloud Foundry, and when it will be open sourced.<span id="more-11145"></span></p>
<p>The biggest announcement made at the conference was the unification of OpenShift Express and OpenShift Flex Platforms. At first I was disappointed to hear this as I wanted to showcase Flex in my presentation. It was not good to hear one day before the presentation that Flex will not be developed further and will be merged in express.  Someone asked why OpenShift Flex is being abandoned as it has some very good features like AutoScaling, Log Management, MongoDB Replica Sets, Tomcat support,  Cost Calculator and many more. Mark Atwood replied  to this by saying "It was getting difficult to manage two products and two teams which overlap a lot. ". <a href="https://www.redhat.com/openshift/community/author/jimmy-guerrero">Jimmy Guerrero</a> has <a href="http://xebee.xebia.in/2012/01/26/openshift-express-the-future-of-redhat-paas/#comment-7140">commented</a> and shed more light on it.</p>
<blockquote><p>Our motivation for unifying the Flex and Express platforms isn’t because it was difficult to manage two teams and two products, but instead we are being driven by the desire to bring the best features of both platforms into a single user experience called, OpenShift. For us it isn’t the end of Flex, but, rather, the beginning of a single converged solution that is easy to use and has the capabilities that you want.</p>
<p>This way, from the same IDE, GUI or client tools, a user can continue to get the free access to multiple instances and the broad middleware and framework support of Express, coupled with the rich functionality of Flex’s auto-scaling, performance monitoring and log management. And from, your post, it looks like you agree this is best way to go.</p>
<p>&nbsp;</p></blockquote>
<p>In my opinion also this is a right step forward for OpenShift. OpenShift Express has gained more popularity as compared to OpenShift Flex because it is free and easy to use . Express is lightweight, developer oriented, easy to get started with and better suited for creating new applications.  Another reason why I think it is good to have one platform is to avoid porting the applications from one flavor to another. I created a very simple Spring MongoDB application and to make the application run on both platforms I had to change database properties. Also as both the platforms support different cartridges (example RedHat messaging is supported in Flex but not in Express) it would be difficult to port applications across platforms.</p>
<p>Another big news about OpenShift is that it will be open source soon and you will be able to create a private PaaS on your own infrastructure behind company firewalls. I think it is very important for OpenShift if it wants to have the same momentum as Cloud Foundry. This also means that community can add support for cartridges which does not exist in OpenShift.</p>
<p>Overall I think OpenShift is heading in the right direction and it is a wise decision to spend time on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/26/openshift-express-the-future-of-redhat-paas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What made me to choose CXF over Axis2</title>
		<link>http://xebee.xebia.in/2012/01/25/what-made-me-to-choose-cxf-over-axis2/</link>
		<comments>http://xebee.xebia.in/2012/01/25/what-made-me-to-choose-cxf-over-axis2/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 12:11:40 +0000</pubDate>
		<dc:creator>Mukesh Shah</dc:creator>
				<category><![CDATA[Apache CXF]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11063</guid>
		<description><![CDATA[My last assignment required me to expose soap based web service. While exploring I came to know that there are many types of web services, for example JBossWS, GlassFish Metro, Apache CXF, Axis1, Axis2 and likewise. All of them are widely used and were also promising to fulfill most of my requirements. Since I had [...]]]></description>
			<content:encoded><![CDATA[<p>My last assignment required me to expose soap based web service. While exploring I came to know that there are many types of web services, for example  JBossWS, GlassFish Metro, Apache CXF, Axis1, Axis2 and likewise. All of them are widely used and were also promising to fulfill most of my requirements. Since I had to deploy my web service on tomcat web container, I shortlisted Axis2 and Apache CXF for comparison. While working on POC for their comparison, factors mentioned below helped me to choose the appropriate.</p>
<p><strong>Factors in favor of CXF</strong><br />
<span id="more-11063"></span></p>
<ol>
<li>I do not have to download any soap engine as we do when we use Axis2.</li>
<li>Deployment of axis2 is not as easy as CXF because there is no well known plugin available for axis2 which can directly deploy aar file on soap engine.</li>
<li>CXF provides nice and simple integration with service component architecture(SCA) container like Tuscany.</li>
<li>CXF also gives web service standards support, Frontend programming APIs support, Tools support(like xsd to wsdl, wsdl validator, wsdl to soap, wsdl to xml, wsdl to javascript, wsdl to java, java to web service  etc.) and RESTful services support in very simple fashion.</li>
<li>The last but not least is that CXF provides tools to generate java client as well as JavaScript client.</li>
</ol>
<p>Now lets have a glance on the steps which I followed during CXF and Axis2 POCs.</p>
<p><strong>Axis2 POC</strong><br />
Steps followed during POC that describes how to get started with Axis2:-</p>
<p><strong>Step-1:</strong> Download Axis2, which is required as soap engine to process soap based request.<br />
<strong>Step-2:</strong> Create a maven based web project with services. Service class and pom configurations are given below.</p>
<p><strong>service class:</strong></p>
<pre class="brush: plain; title: ; notranslate">
public class StringWebService {
	public String getMessage(String s) {
		return s;
	}
}
</pre>
<p><strong>pom.xml</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;dependencies&gt;
		&lt;!--Axis2 Jars --&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.axis2&lt;/groupId&gt;
			&lt;artifactId&gt;axis2&lt;/artifactId&gt;
			&lt;version&gt;1.4&lt;/version&gt;
		&lt;/dependency&gt;
	&lt;/dependencies&gt;
	&lt;build&gt;
		&lt;plugins&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.axis2&lt;/groupId&gt;
				&lt;artifactId&gt;axis2-aar-maven-plugin&lt;/artifactId&gt;
				&lt;version&gt;1.4.1&lt;/version&gt;
				&lt;configuration&gt;
					&lt;aarName&gt;ws_axis2&lt;/aarName&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/build&gt;
</pre>
<p>You can use other dependencies as per your requirement. I have used axis2-aar-maven-plugin to build Apache archive (aar) file, to be deployed on soap engine.</p>
<p><strong>Step-3:</strong> Create a services.xml file to expose service name and its operations in src/main/resources/META-INF directory. Also add web.xml in WEB-INF directory as we do in normal web project to define AxisServlet and its mapping.</p>
<p><strong>services.xml</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;service name=&quot;WebService&quot;&gt;
	&lt;parameter name=&quot;ServiceClass&quot; locked=&quot;false&quot;&gt;com.test.ws.StringWebService&lt;/parameter&gt;
	&lt;operation name=&quot;getMessage&quot;&gt;
		&lt;messageReceiver class=&quot;org.apache.axis2.rpc.receivers.RPCMessageReceiver&quot;/&gt;
	&lt;/operation&gt;
&lt;/service&gt;
</pre>
<p><strong>web.xml</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;web-app&gt;
    &lt;display-name&gt;Apache-Axis2&lt;/display-name&gt;
    &lt;servlet&gt;
        &lt;servlet-name&gt;AxisServlet&lt;/servlet-name&gt;
        &lt;display-name&gt;Apache-Axis Servlet&lt;/display-name&gt;
        &lt;servlet-class&gt;org.apache.axis2.transport.http.AxisServlet&lt;/servlet-class&gt;
        &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
    &lt;/servlet&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;AxisServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/servlet/AxisServlet&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;AxisServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
<p><strong>Step-4:</strong> Execute below maven command to build web service.<br />
<strong>mvn clean install axis2-aar:aar</strong><br />
(axis2-aar:aar basically generates the .aar file)</p>
<p><strong>Step-5:</strong> The final step is to deploy .aar file in $CATALINA_HOME/webapps/axis2/WEB-INF/services directory. Now our web service is ready to use.<br />
After deployment you can access wsdl by hitting this url:- http://localhost:8080/axis2/services/WebService?wsdl</p>
<p><strong>CXF POC</strong><br />
Steps followed during POC which describes how to get started with CXF:-</p>
<p><strong>Step-1:</strong> Create maven based web project with services</p>
<p><strong>service class:</strong></p>
<pre class="brush: plain; title: ; notranslate">
@WebService
public class SampleCXFService {
    public String getMessage(String s) {
        return s;
    }
}
</pre>
<p><strong>pom.xml</strong></p>
<p>&nbsp;</p>
<pre class="brush: plain; title: ; notranslate">
&lt;build&gt;
		&lt;plugins&gt;
			&lt;plugin&gt;
				&lt;!-- Plugin for compiling Java code --&gt;
				&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
				&lt;configuration&gt;
					&lt;source&gt;1.5&lt;/source&gt;
					&lt;target&gt;1.5&lt;/target&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
			&lt;plugin&gt;
				&lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
				&lt;version&gt;2.1.1&lt;/version&gt;
				&lt;configuration&gt;
					&lt;warName&gt;ws_cxf&lt;/warName&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
				&lt;artifactId&gt;tomcat-maven-plugin&lt;/artifactId&gt;
				&lt;configuration&gt;
					&lt;url&gt;http://127.0.0.1:8080/manager&lt;/url&gt;
					&lt;server&gt;TomcatServer&lt;/server&gt;
					&lt;path&gt;/ws_cxf&lt;/path&gt;
					&lt;warFile&gt;target/ws_cxf.war&lt;/warFile&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/build&gt;
	&lt;dependencies&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
			&lt;version&gt;2.2.3&lt;/version&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
			&lt;version&gt;2.2.3&lt;/version&gt;
		&lt;/dependency&gt;
	&lt;/dependencies&gt;
</pre>
<p>You can use other dependencies as per your requirement and to use tomcat-maven-plugin effectively you will have to add below configuration snippet in settings.xml of maven repository. Make sure that username and password exist in your $CATALINA_HOME/conf/tomcat-users.xml file.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;server&gt;
	&lt;id&gt;TomcatServer&lt;/id&gt;
	&lt;username&gt;admin&lt;/username&gt;
	&lt;password&gt;password&lt;/password&gt;
&lt;/server&gt;
</pre>
<p><strong>Step-2:</strong> Create beans.xml configuration file which is basically used to define service endpoint and few configuration file i.e. cxf.xml, cxf-extension-soap.xml and cxf-servlet.xml. Also add web.xml in WEB-INF directory as we do in normal web project to define CXFServlet and its mapping.</p>
<p><strong>beans.xml</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	xmlns:jaxws=&quot;http://cxf.apache.org/jaxws&quot;
	xsi:schemaLocation=&quot;
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd&quot;&gt;
	&lt;import resource=&quot;classpath:META-INF/cxf/cxf.xml&quot; /&gt;
	&lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-soap.xml&quot; /&gt;
	&lt;import resource=&quot;classpath:META-INF/cxf/cxf-servlet.xml&quot; /&gt;
	&lt;jaxws:endpoint id=&quot;sampleService&quot;
	  implementor=&quot;com.test.SampleCXFService&quot;
	  address=&quot;/sampleService&quot; /&gt;
&lt;/beans&gt;
</pre>
<p><strong><br />
web.xml</strong></p>
<p>&nbsp;</p>
<pre class="brush: plain; title: ; notranslate">
&lt;web-app&gt;
	&lt;context-param&gt;
		&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
		&lt;param-value&gt;WEB-INF/beans.xml&lt;/param-value&gt;
	&lt;/context-param&gt;
	&lt;listener&gt;
		&lt;listener-class&gt;
			org.springframework.web.context.ContextLoaderListener
		&lt;/listener-class&gt;
	&lt;/listener&gt;
	&lt;servlet&gt;
		&lt;servlet-name&gt;CXFServlet&lt;/servlet-name&gt;
		&lt;display-name&gt;CXF Servlet&lt;/display-name&gt;
		&lt;servlet-class&gt;
			org.apache.cxf.transport.servlet.CXFServlet
		&lt;/servlet-class&gt;
		&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
	&lt;/servlet&gt;
	&lt;servlet-mapping&gt;
		&lt;servlet-name&gt;CXFServlet&lt;/servlet-name&gt;
		&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
	&lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
<p><strong>Step-3:</strong> Now we are ready to deploy our CXF base web service.<br />
Execute below maven command and make sure that your tomcat instance is running.<br />
<strong>mvn clean tomcat:deploy</strong><br />
and for undeploying you can use <strong>mvn tomcat:undeploy</strong><br />
After deployment you can access wsdl by hitting this url:- http://localhost:8080/ws_cxf/sampleService?wsdl url.</p>
<p><strong>Conclusion:</strong><br />
So on the basis of above 2 POCs I concluded that implementing soap based web services is easy in CXF because it takes lesser steps than Axis2. You will not have to download separate soap engine to deploy your application when you choose CXF. It provides simple integration with service component architecture(SCA) container like Tuscany as I have mentioned above also. The last thing which attracted me most is that CXF provides tools to generate JavaScript client also which I didn't find in Axis2.</p>
<p>Please post your question(s) if any.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/25/what-made-me-to-choose-cxf-over-axis2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Persisting relationship entities in Neo4j</title>
		<link>http://xebee.xebia.in/2012/01/24/persisting-relationship-entities-in-neo4j/</link>
		<comments>http://xebee.xebia.in/2012/01/24/persisting-relationship-entities-in-neo4j/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 20:33:31 +0000</pubDate>
		<dc:creator>Sunil Prakash Inteti</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Neo4j]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Data]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10920</guid>
		<description><![CDATA[Neo4j is a high-performance, NOSQL graph database with all the features of a mature and robust database. In Neo4j data gets stored in nodes connected to each other by relationship entities that carry its own properties. These relationships are very important in graphs and helps to traverse the graph and make decisions. This blog discusses [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://neo4j.org/">Neo4j</a> is a high-performance, NOSQL graph database with all the features of a mature and robust database. In Neo4j data gets stored in nodes connected to each other by relationship entities that carry its own properties. These relationships are very important in graphs and helps to traverse the graph and make decisions. This blog discusses the two ways to persist a relationship between nodes and also the scenario's which suits their respective usage. <a href="http://neo4j.org/spring/">Spring-data-neo4j</a> by springsource gives us the flexibility of using the spring programming model when working with neo4j database. The code examples in this blog will be using spring-data-neo4j.<br />
<span id="more-10920"></span><br />
Let's consider a case where we have two NodeEntities Employee and Project. A Employee has a role in a project which is a relationship entity.<br />
Here is the code snippet for these entities and the relationship between them.</p>
<pre class="brush: java; title: ; notranslate">
@NodeEntity
public class Employee {
	@GraphId
	@Indexed
	private Long nodeId;

	@Indexed
	private String name;

	@RelatedToVia(elementClass = Role.class, type=&quot;WORKED_IN&quot;, direction=Direction.BOTH)
	private Set&lt;Role&gt; roles;

 }

@NodeEntity
public class Project {

	@GraphId
	@Indexed
	private Long nodeId;

	@Indexed
	private String name;

	@RelatedTo( elementClass=Employee.class, type=&quot;WORKED_IN&quot;, direction=Direction.BOTH)
	private Set&lt;Employee&gt; teamMembers;
}

@RelationshipEntity(type=&quot;WORKED_IN&quot;)
public class Role {

	@GraphId
	private Long nodeId;

	@Indexed
	private String name;

	@StartNode
	private Employee employee;

	@EndNode
	private Project project;
}
</pre>
<p>1) First way to persist relationship : Using the Neo4jTemplate class to create relationship. For example</p>
<pre class="brush: java; title: ; notranslate">
Role stint = template.createRelationshipBetween(sunil, beachbody, Role.class,
                                                                      &quot;WORKED_IN&quot;, false);
template.save(stint);
 </pre>
<p>createRelationship method takes the two node entities and the relationship class and relation type defined by the RelationshipEntity and a boolean value to allow/disallow duplicate relationships.</p>
<p>2) Second way is to instantiate the role and add it to a employee entity and persist the employee entity. Persisting the entity also persists the Role entity too, thus establishing the link between employee and project nodes.</p>
<pre class="brush: java; title: ; notranslate">
		Employee sunil = new Employee(&quot;Sunil&quot;);
		sunil = employeeRepo.save(sunil);
		Project beachbody = new Project(&quot;Beachbody&quot;);
		Project project = projectRepo.save(beachbody);

		Role stint = sunil.workedIn(beachbody, &quot;Java developer&quot;);
		template.save(sunil);
</pre>
<p>It's curious to know by a simple unit test that the second way is performing almost 30 times better than the first way in persisting just the relationship. I looked at the source code for both the ways, I noticed that the first way fetches the persistent state of both the start and the end nodes and then tries to establish a relation between the two. The second option just tries to create the relation directly on the employee which is already persisted. Clearly given a scenario that we have two persisted nodes and we need to create the relationship we must always go with the option2 in my opinion. This can greatly improve the performance. The only scenario that I can think of using the first option can be that we have to allow duplicate relationships between nodes which can generally happen when relationship entities are very rich ie have a lot of properties.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/24/persisting-relationship-entities-in-neo4j/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MongoDB Replica Set on OpenShift Flex</title>
		<link>http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/</link>
		<comments>http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 19:25:32 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[openshift]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=11020</guid>
		<description><![CDATA[As I am preparing for my JUDCon session on OpenShift one topic that I will be covering is setting up MongoDB Replica Set on OpenShift Flex. There are various reasons to setup MongoDB replication. The primary reason for replication is to ensure data survive single or multiple machine failures. The more replicas you have, the [...]]]></description>
			<content:encoded><![CDATA[<p>As I am preparing for my JUDCon session on OpenShift one topic that I will be covering is setting up MongoDB Replica Set on OpenShift Flex. There are various reasons to setup MongoDB replication. The primary reason for replication is to ensure data survive single or multiple machine failures. The more replicas you have, the more likely is your data to survive one or more hardware crashes. With three replicas, you can afford to loose two nodes and still serve the data.Replication also helps to scale reads as you can distribute your read load accross multiple machines. There are two ways to support replication in MongoDB -- Master Slave and Replica Set. Replica Set is the recommended way to do replication and OpenShift only supports replica set.  OpenShift Flex MongoDB replica set is yet not polished so you might face issues in setting up. This blog will show steps to configure a working MongoDB replica set on OpenShift Flex. If you are not aware of MongoDB Replica Set you should first refer to the <a href="http://www.mongodb.org/display/DOCS/Replica+Set+Tutorial">MongoDB documentation</a>. Also you can refer to my blog on<a href="http://whyjava.wordpress.com/2011/12/12/using-mongodb-replica-set-with-spring-mongodb-1-0-0-rc1/"> how to use MongoDB replica set with Spring</a>.<span id="more-11020"></span></p>
<ol>
<li>Login to <a href="https://openshift.redhat.com/flex/flex/index.html">OpenShift Flex console</a> and create a cluster. as shown below in a screenshot. As you can see below I have defined  cluster named replica with 1server and used EC2 medium instance.<a rel="attachment wp-att-11027" href="http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/define-server-cluster/"><img class="alignnone size-medium wp-image-11027" height="300" width="292" title="Define-Server-Cluster" src="http://xebee.xebia.in/wp-content/uploads/2012/01/Define-Server-Cluster-292x300.png" /></a></li>
<li>After cluster has been setup you will see one server running in server tab.  Go to the "Applications" tab and press Add Application. Please select a server cluster , give application name and application version and then press submit button. My settings are shown in screenshot below.<a href="http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/create-application/" rel="attachment wp-att-11030"><img src="http://xebee.xebia.in/wp-content/uploads/2012/01/Create-Application-222x300.png" title="Create-Application" width="222" height="300" class="alignnone size-medium wp-image-11030" /></a><a href="http://whyjava.files.wordpress.com/2012/01/create-application.png"><br />
</a></li>
<li>Next you will see a application named bookshop (or the name you gave to application) under the Applications tab. Name of the application is a hyperlink and on clicking that you will be able to configure the application. So click on the application name and you will see five sub-tabs -- Overview, Components,Files, Configure, and Deploy Changes.</li>
<li>Click on the Components tab to select the components required for running the application. The required components are Tomcat, Java6 and MongoDB 2. <a href="http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/application-components/" rel="attachment wp-att-11031"><img src="http://xebee.xebia.in/wp-content/uploads/2012/01/Application-Components-300x154.png" title="Application-Components" width="300" height="154" class="alignnone size-medium wp-image-11031" /></a><a href="http://whyjava.files.wordpress.com/2012/01/application-components.png"><br />
</a></li>
<li>Next go to the Configure tab to configure the components selected. This view gives us the power to configure the components according to our needs. We will only configure MongoDB components as we need to set up replica set. So click MongoDB-2.0.1 and enable replica sets. Right now you can only can have replica set of only 3 machines. But I think in future you will have the choice to select a replica set from 3-7 machines.<a href="http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/enable-mongodb-replicaset/" rel="attachment wp-att-11032"><img src="http://xebee.xebia.in/wp-content/uploads/2012/01/enable-mongodb-replicaset-300x245.png" title="enable-mongodb-replicaset" width="300" height="245" class="alignnone size-medium wp-image-11032" /></a><a href="http://whyjava.files.wordpress.com/2012/01/enable-mongodb-replicaset.png"><br />
</a></li>
<li>Then go to Deploy Changes tab and deploy the changes and start the application.</li>
<li>After you have started the application you will notice that two more instances are added to the cluster. Please keep patience it takes some minutes (2-5 minutes). After that you will have 3 instance cluster with MongoDB setup.<a href="http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/server-cluster/" rel="attachment wp-att-11033"><img src="http://xebee.xebia.in/wp-content/uploads/2012/01/Server-Cluster-300x128.png" title="Server-Cluster" width="300" height="128" class="alignnone size-medium wp-image-11033" /></a><a href="http://whyjava.files.wordpress.com/2012/01/server-cluster.png"><br />
</a></li>
<li>Please note until this point replica set is not set up and if you ssh into any of the machines you will notice that normal mongod instances are running. To enable replica set you need to deploy a application. I am deploying a simple Spring MongoDB application. You can download the application from my <a href="http://code.google.com/p/shekhar-playground/downloads/list">google code project</a>.</li>
<li>Go to the File tab and upload the bookshop.war and deploy the changes. This will restart the application.</li>
<li>In the Overview tab you will find the url of the application. Append bookshop to the url as bookshop is the context path. The application url will be like <a href="http://replica107550541-1150999735.us-east-1.elb.amazonaws.com/bookshop/">http://replica107550541-1150999735.us-east-1.elb.amazonaws.com/bookshop/</a>. You will be able to do CRUD operations on Book.</li>
<li>There is a bug in the flex code that sometimes it is not able to add a particular node to the replica set. To check that all of the three nodes are added to replica set lets ssh to first instance in our cluster. To do it type ssh admin@107.21.186.11. Replace ip address with your instance ip address.</li>
<li>Next connect to mongo on machine by typing command shown below.
<pre class="brush: plain; title: ; notranslate">
/opt/vostok/cartridges/mongodb-2.0.1/bundle/bin/mongo
</pre>
</li>
<li>If you see the output that you are logged into PRIMARY &gt;. It means replica set is configured.
<pre class="brush: plain; title: ; notranslate">
[admin@ip-10-194-195-117 ~]$ /opt/vostok/cartridges/mongodb-2.0.1/bundle/bin/mongo
MongoDB shell version: 2.0.1
connecting to: test
PRIMARY&gt;
</pre>
</li>
<li>Next we should check that all the three instances are added to replica set. To check do execute rs.status() command. The command and output are shown below.
<pre class="brush: plain; title: ; notranslate">
PRIMARY&gt; rs.status()
{
	&quot;set&quot; : &quot;SET1&quot;,
	&quot;date&quot; : ISODate(&quot;2012-01-22T18:46:02Z&quot;),
	&quot;myState&quot; : 1,
	&quot;members&quot; : [
		{
			&quot;_id&quot; : 0,
			&quot;name&quot; : &quot;10.194.195.117:27017&quot;,
			&quot;health&quot; : 1,
			&quot;state&quot; : 1,
			&quot;stateStr&quot; : &quot;PRIMARY&quot;,
			&quot;optime&quot; : {
				&quot;t&quot; : 1327256835000,
				&quot;i&quot; : 1
			},
			&quot;optimeDate&quot; : ISODate(&quot;2012-01-22T18:27:15Z&quot;),
			&quot;self&quot; : true
		},
		{
			&quot;_id&quot; : 1,
			&quot;name&quot; : &quot;10.212.138.54:27017&quot;,
			&quot;health&quot; : 1,
			&quot;state&quot; : 2,
			&quot;stateStr&quot; : &quot;SECONDARY&quot;,
			&quot;uptime&quot; : 1121,
			&quot;optime&quot; : {
				&quot;t&quot; : 1327256835000,
				&quot;i&quot; : 1
			},
			&quot;optimeDate&quot; : ISODate(&quot;2012-01-22T18:27:15Z&quot;),
			&quot;lastHeartbeat&quot; : ISODate(&quot;2012-01-22T18:46:02Z&quot;),
			&quot;pingMs&quot; : 0
		}
	],
	&quot;ok&quot; : 1
}
</pre>
</li>
<li>The output shows that replica set has two nodes one primary and other secondary. But we created a replica set  consisting of three nodes. This is the bug in OpenShift Flex code which will be fixed in future. For now we can add the third node by rs.add() command. The add() requires the internal ip of the third machine. This ip is not the same ip shown in clusters tab. You have to run ifconig command and get the ip of machine and then add the node to replica set.
<pre class="brush: plain; title: ; notranslate">
rs.add('10.190.206.11')
</pre>
</li>
</ol>
<p>After following all the steps you will have running MongoDB replica set on OpenShift Flex.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/23/mongodb-replica-set-on-openshift-flex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XML Parsers for iOS: libXML vs KissXML</title>
		<link>http://xebee.xebia.in/2012/01/22/ios-xml-parsers-libxml-vs-kissxml/</link>
		<comments>http://xebee.xebia.in/2012/01/22/ios-xml-parsers-libxml-vs-kissxml/#comments</comments>
		<pubDate>Sat, 21 Jan 2012 20:11:16 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[kissxml]]></category>
		<category><![CDATA[libxml]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10997</guid>
		<description><![CDATA[XML Parsing on iPhone/iPad - Is that something your current sprint revolves around? Well if it does, this blog might help you. While parsing XMLs on device, we need to look into factors like performance and memory consumption. While googling, i found couple of XML parsing APIs including Apple's native NSXMLParser. NSXMLParser looked like this is [...]]]></description>
			<content:encoded><![CDATA[<p>XML Parsing on iPhone/iPad - Is that something your current sprint revolves around? Well if it does, this blog might help you. While parsing XMLs on device, we need to look into factors like performance and memory consumption. While googling, i found couple of XML parsing APIs including Apple's native <a href="http://developer.apple.com/library/mac/#documentation/Coc&lt;/em&gt;oa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html">NSXMLParser</a>. NSXMLParser looked like this is all i need. But my requirement was also to 'write' xmls making sure that i do not compromise on performance and memory. On googling more i found couple of APIs which can provide me XML writing capabilities. I chose to explore <a href="http://xmlsoft.org/">libXML2</a> and <a href="https://github.com/robbiehanson/KissXML">KissXML</a>.</p>
<p><span id="more-10997"></span></p>
<p>You need to have some basic settings in order to use any of these APIs. Open your project build settings and search for following two parameters and enter the respective values:</p>
<ul>
<li><strong>Header Search Paths:</strong> <em>/usr/include/libxml2</em></li>
<li><strong>Other Linker Flags:</strong><em>-lxml2</em></li>
</ul>
<div>and you are good to go!</div>
<p>While the memory consumption by both the APIs are almost same but there is a big difference when it comes to development. libXML2 is written in C, so it's hard to call it as developer-friendly. On the other side, KissXML is written in Objective C, so it's pretty easy to understand and implement as compared to libXML2.</p>
<p>I will show and compare the basic parsing logic provided by both the APIs.</p>
<p><strong>libXML:</strong></p>
<pre class="brush: plain; title: ; notranslate">
	NSString *path = [[NSBundle mainBundle] pathForResource:@&quot;Employee&quot; ofType:@&quot;xml&quot;];
    NSData *xmlData = [NSData dataWithContentsOfFile:path];
    xmlTextReaderPtr reader = xmlReaderForMemory([xmlData bytes],
                                                 [xmlData length],
                                                 [path UTF8String], nil,
                                                 (XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING));

    if(!reader) {
        NSLog(@&quot;Error loading XML&quot;);
    }

    NSString *currentNode = nil;
    NSString *nodeValue = nil;

    employeeCollection = [NSMutableArray array];

    NSDictionary *employee = nil;

    char* temp;

    while (true) {
        if (!xmlTextReaderRead(reader)) break;
        switch (xmlTextReaderNodeType(reader)) {
            case XML_READER_TYPE_ELEMENT: {
                temp = (char *) xmlTextReaderConstName(reader);
                currentNode = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding];
                if([currentNode isEqualToString:@&quot;employee&quot;]) {
                    employee = [NSMutableDictionary dictionary];
                    [employeeCollection addObject:employee];
                }
                break;
            }
            case XML_READER_TYPE_TEXT: {
                temp = (char *) xmlTextReaderConstValue(reader);
                nodeValue = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding];
                [employee setValue:nodeValue forKey:currentNode];
                currentNode = nil;
                nodeValue = nil;
                break;
            }
            default:
                break;
        }
    }
</pre>
<p><strong>KissXML:</strong> (using XPath)</p>
<pre class="brush: plain; title: ; notranslate">
	NSString *source = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@&quot;employee&quot; ofType:@&quot;xml&quot;] encoding:NSUTF8StringEncoding error:&amp;error];
	DDXMLDocument *theDocument = [[DDXMLDocument alloc] initWithXMLString:source options:0 error:&amp;error];
    NSMutableArray *employeeList = [[NSMutableArray alloc] init];

	NSArray *employeeXmlResult = [theDocument nodesForXPath:@&quot;/xml/employees/employee&quot; error:&amp;error];

	for (DDXMLElement *employee in employeeXmlResult) {
        NSMutableArray *arr = [[NSMutableArray alloc] init];
        arr = (NSMutableArray *)[employee children];

        NSString *employeeName = [[employee attributeForName:@&quot;name&quot;] stringValue];
        [employeeList insertObject:employeeName atIndex:0];

    }
</pre>
<p>So was there something in both the code snippets that comes into mind at first? May be the developer-friendliness i was talking above? One of the reason i preferred KissXML was this.</p>
<p>One thing which is important to note here is the performance consideration. While i was testing my project with some extra data stubbed at the backend, i found some pause happening while using KissXML. The pause happened when my application received response for that heavy XML. When i replaced the parsing logic with libXML2, i noticed that the pause went unnoticeable. Though the actual data was not at all heavy, so i simply ignored this test. But this could be an important issue which you can look into before going for KissXML.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/22/ios-xml-parsers-libxml-vs-kissxml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why to choose JMeter for performance testing?</title>
		<link>http://xebee.xebia.in/2012/01/20/why-to-choose-jmeter-for-performance-testing/</link>
		<comments>http://xebee.xebia.in/2012/01/20/why-to-choose-jmeter-for-performance-testing/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 17:56:17 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[performance testing]]></category>
		<category><![CDATA[JMeter]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10906</guid>
		<description><![CDATA[During my last project, I was given a task to choose one of the best tools for performance testing among open source tools available in market.  After evaluation and little research I came up with JMeter. I have thought of writing a small blog for those who are new to performance testing and are confused [...]]]></description>
			<content:encoded><![CDATA[<p>During my last project, I was given a task to choose one of the best tools for performance testing<del cite="mailto:Anubhav%20" datetime="2012-01-05T04:12"> </del> among open source tools available in market.  After evaluation and little research I came up with JMeter. I have thought of writing a small blog for those who are new to performance testing and are confused of which tool to use. It’s pretty common that whenever we start looking out for any tool we keep few things in our mind that it should record and playback, allow easy parametrization, generate detailed reports, should be able to simulate a heavy load on a server, analyze overall performance, etc . JMeter would not disappoint you in that sense because it has more than above mentioned features. There are important features of JMeter which have been listed down in this blog. Let's start from first thing which is its installation. It is very easy to install which requires only Java set up on your machine since it is a Java based tool.</p>
<p><span id="more-10906"></span></p>
<p><strong>Installation<br />
</strong></p>
<p>1. Download JMeter  from  link provided below :-</p>
<p>http://jmeter.apache.org/download_jmeter.cgi</p>
<p>2. Unzip it anywhere in your system.</p>
<p>3. Then run jmeter.bat (for Windows) which is kept in its bin folder and start using it.</p>
<p><b>Record and Play<ins cite="mailto:Anubhav%20" datetime="2012-01-05T04:51"> </ins></b></p>
<p>JMeter lets you record your test plan by using its <b>proxy server.</b> Besides recording, you can also exclude non required sampler requests by giving  required regular expressions in its proxy server.</p>
<p><b>Parametrization</b></p>
<p>You can also easily parametrize your test cases by using user-parameter pre-processors or config-elements. <ins cite="mailto:Anubhav%20" datetime="2012-01-05T04:51"></ins></p>
<p><b>Passing data from one Request to other</b></p>
<p>Passing response data from one request to another can be easily done using its powerful post processors like XPath Extractors and Regular Expression<ins cite="mailto:Anubhav%20" datetime="2012-01-05T04:52"> </ins>Extractor.</p>
<p><b>Allow working with multiple types of Requests</b></p>
<p><b> </b></p>
<p>JMeter does not only work with simple HTTP<span style="text-decoration: underline;"> </span>requests but it also works with other requests which includes FTP Request, JDBC Request , LDAP Request , SOAP/XML-RPC Request, etc</p>
<p><b>Allow Customization of test case flow with its Logic Controllers</b></p>
<p>Logic Controllers can be consumed to customize logic to decide when to send requests to cover different scenarios we come across during performance testing. They can modify the requests themselves; cause JMeter to repeat requests, etc. JMeter provides different types of controllers like once-only-controller, interleave controller, etc which have their own functioning and you can decide test plan logic with the help of these controllers. For example, Loop controllers can be used to send request repeatedly many times to put stress on server.</p>
<p><b> </b></p>
<p><b>Remote Testing/Distributed Testing</b></p>
<p><b> </b></p>
<p>It is the most powerful feature of JMeter. JMeter client machine is not able to simulate enough users to stress your server so there is one option exists which is to control multiple remote JMeter engines from a single JMeter GUI client. By running JMeter remotely, you can replicate a test across many low-end computers and thus simulate a larger load on the server. One instance of the JMeter GUI client can control any number of remote JMeter instances, and collect all the data from them. This offers the following features:</p>
<ul>
<li>Saving      of test samples to the local machine</li>
<li>Management      of multiple JMeter Engines from a single machine</li>
<li>No      need to copy the test plan to each server - the client sends it to all the      servers</li>
</ul>
<p><b>Generate Reports</b></p>
<p>Unless you can show effectively, the tests and results you achieve is of little use to others. Tool should be able to collect information, organize it, and present it in form of reports. JMeter has capability to produce nice reports with help of its listeners is a component that shows the results of the samples.</p>
<p><b> </b></p>
<p><b>Allow addition of  Think Time </b></p>
<p>We know that Think time is a time taken by end user of an application between navigation of application pages/screens. It also includes the time taken by end user to fill in any application page. To make test cases realistic it is good practice to include think time in between transaction steps. We can add think time in test cases with the help of different types of timer options available in JMeter for example:- constant timer, random uniform timer which can be added in test cases as per requirement.</p>
<p><b>Contains important browser features like Cache Manager, etc</b></p>
<p>JMeter is not a browser but it simulates like a browser however it does not perform all the actions supported by browsers but it provides some of important browser features like HTTP cache manager, HTTP cookie manager, HTTP header manager. For example: by adding HTTP cookie manager, it ensures that all HTTP requests will share the same cookies.</p>
<p><b>Allow Assertions to be added in each Request</b></p>
<p>Assertions allow the ability to assert facts about responses received from the server being tested. Using an assertion, you can essentially "test" that your application is returning the results you expect it to. Assertions can be added to any controller in a test plan (simply right-click on the controller and add an assertion). As always, these assertions will be attached to any test samples that "pass through" that controller.</p>
<p><b>Provides access to Functions and Bean- shell scripting </b></p>
<p>JMeter has some useful build in functions<ins cite="mailto:Anubhav%20" datetime="2012-01-05T04:59">,</ins> which can compute new values at run-time based on previous response data and Bean Shell function evaluates the script passed to it, and returns the result.</p>
<p>Components used in JMeter seem like a lot of jargon initially but eventually you will get used to these elements and then testing will be a piece of cake .The image below gives the brief description of components used in JMeter.</p>
<p><img src="data:image/png;base64,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" /></p>
<p><strong><br />
</strong></p>
<p><em><strong>Conclusion:-</strong></em></p>
<p>JMeter is good to be used for testing of performance both on static and dynamic resources. It can easily be used to simulate a heavy load on a server to test its strength and to analyze overall performance under different load types. You can use it to make a graphical analysis of performance and get detailed reports under heavy concurrent load. At the conclusion of this blog, lets check below what does score-card of JMeter says:-</p>
<ul>
<li>Ease of use – <b>YES</b></li>
<li>Record and Playback - <b>YES</b></li>
<li>Manual scripting – <b>YES</b></li>
<li>Command Line – <b>YES</b></li>
<li>Analyzing performance- <b>YES</b></li>
<li>Detailed Reports-<strong>Yes</strong><b><br />
</b></li>
<li>Stress Testing- <b>Yes</b></li>
</ul>
<div></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/20/why-to-choose-jmeter-for-performance-testing/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>SOPA in US and Censorship in India: A cocktail to destroy Internet Freedom !</title>
		<link>http://xebee.xebia.in/2012/01/19/sopa-in-us-and-censorship-in-india-a-cocktail-to-destroy-internet-freedom/</link>
		<comments>http://xebee.xebia.in/2012/01/19/sopa-in-us-and-censorship-in-india-a-cocktail-to-destroy-internet-freedom/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 12:28:33 +0000</pubDate>
		<dc:creator>Jiten</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[e-Commerce]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[censorship]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[pipa]]></category>
		<category><![CDATA[sopa]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10948</guid>
		<description><![CDATA[As US senators mull over the SOPA(Stopping Online Piracy Act) and PIPA(Protecting Intellectual Property Act) bills, the world stands witness to a historic moment. Almost all big IT companies like Google, Wikipedia, Facebook, Mozilla, Godaddy, etc are speaking in one unanimous voice against SOPA and Internet Censorship. The draconian provisions of SOPA/PIPA are bound to [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">As US senators mull over the SOPA(Stopping Online Piracy Act) and PIPA(Protecting Intellectual Property Act) bills, the world stands witness to a historic moment. Almost all big IT companies like Google, Wikipedia, Facebook, Mozilla, Godaddy, etc are speaking in one unanimous voice against SOPA and Internet Censorship. The draconian provisions of SOPA/PIPA are bound to create the deathbed of internet freedom and free speech, and if a careful reading of the proposed legislation is done, one realizes that it is likely to have the same impact on India.<br />
In the disguise of protecting copyrights and stopping piracy its completely clear that the US government is trying to assert its control over the free flow of information on internet  which is some time uncomfortable to them. Giving power to Attorney General to direct search engines like Google to filter particular search results, or asking an ISP to manipulate their DNS  to filter specific IP addresses just at whims and fancies of government all the threatening to accessing information. <span id="more-10948"></span></p>
<p style="text-align: justify;">To make the matters worse on the name of stopping piracy the websites will be held directly responsible for content uploaded by a one of its millions user. And if infringement is proved  then apart from banning whole website its executives would be liable to mountainous fines and prison terms along with the user who uploaded content for upto 5 years. So imagine if a teenager ends up uploading a Michal Jackson video on YouTube he may get 5 year term in jail where as the doctor who killed Michal Jackson could get only 4 years. Or if you post a YouTube video link  of Rockstar movie song on your Facebook wall, entire Facebook website can be blocked for copyright infringement.</p>
<p style="text-align: justify;">To make the matters worse, one of the provisions says if a particular site is banned. Any websites which provides any information about blocked website or softwares it offered can also be blocked. So in a nutshell if a website like Napster is blocked, a website like Wikipedia can also be blocked incase they provided any information about Napster, even if it was merely a hyperlink to Napster’s website And if Wikipedia is banned. all the websites which ever quoted Wikipedia can also be blocked.</p>
<p style="text-align: justify;">Another draconian provisions say that the government through attorney general  can also direct all companies like 'payments gateway  providers', Banks or even the Digital certificate providers to not provide any service to  the blocked website. Now see how will this impact us in India</p>
<ol style="text-align: justify;">
<li>80% of Indian websites are hosted on US based servers with companies  like Godaddy, which are under US jurisdiction and will fall under SOPA.</li>
<li>Websites which are  using  payment gateways provided by US companies will also be affected.</li>
<li>Even if a Indian website is hosted on a Indian server and uses all  Indian payment gateways or banks for its business, If a injunction is  issued by US court against it, US government can ask all the American  websites to remove any information or links about that Indian website  and block its access through all US based ISP's by forcing DNS blockade  through ISP's</li>
<li>Even the Anti SOPA tools like DeSopa would not work because providing  them on any website or using them or providing any information about  them would also become illegal.</li>
<li>All the paid VPNs we use for our privacy or secure surfing would also be  forced to share our data with US government because most of them have their  head offices in US. This may spell disaster for people in countries  like China and Iran who use these methods or overcome illegitimate  government censorships.</li>
<li>Onion surfing (chain proxy) tools like Tor would become useless because at  the one shot US government will have power to ask all US ISP's,   hosting servers to filter any request coming from proxy sites in  disguise of stopping piracy.</li>
</ol>
<p style="text-align: justify;">Internet was born in US but it is not a personal property of US  government. Any type of laws which will be made in US are bound to be  replicated in other countries. And with many governments across the  world facing protest for various reason are already toying the idea of  censoring the information on internet by some or other means. sometimes   by arm twisting, some times by arbitrary court injunctions  or some  times by framing unconstitutional laws. Currently we are witnessing  companies like Facebook,Twitter and Google are landing up in lawsuits in  India on the issue of content filtering and government hardening its  position against companies. Its not a good sign of for the future of  internet, whose freedom we must uphold.</p>
<p style="text-align: justify;">Dissent is a integral part of any democracy. If countries like America  in the aftermath of Wikileaks incidents frame laws to acquire backdoor authority to censor internet in disguise of protecting intellectual property and stopping piracy. They would be doing a great insult to the very<br />
first amendment to their own constitution  guarantying free speech. In India where our fundamental right of freedom of expression is ushering like a diamond hope with every passing year. We must protest any idea or policy  which threatens our freedom to do things on innovation of millennium, Internet,  Which has no boundaries, no laws, no jurisdictions and  no censorships.</p>
<p style="text-align: justify;">So in my opinion we must oppose SOPA or any sort of censorship anywhere, before you are left with a internet with filtered search engines, Blocked websites, no free mp3 songs, No proxies, No free softwares and no Wikipedia and no free code snippets too <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  !</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/19/sopa-in-us-and-censorship-in-india-a-cocktail-to-destroy-internet-freedom/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Software Development Practices that helped me become better</title>
		<link>http://xebee.xebia.in/2012/01/19/software-development-practices-that-helped-me-become-better/</link>
		<comments>http://xebee.xebia.in/2012/01/19/software-development-practices-that-helped-me-become-better/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 20:07:27 +0000</pubDate>
		<dc:creator>Guneet Sahai</dc:creator>
				<category><![CDATA[Extreme Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10927</guid>
		<description><![CDATA[Xebia India takes great pride in paying high amount of attention to writing QUALITY code. “Doing it Right” is almost a religion here. For us the buck does not stop at showing a demo of working software to the client, but also ensuring the underlying code is written in the best possible manner using best [...]]]></description>
			<content:encoded><![CDATA[<p align="JUSTIFY"><span style="color: #000080;" color="#000080"><span style="text-decoration: underline;"><a href="http://xebiaindia.com/" target="_blank">Xebia India</a></span></span> takes great pride in paying high amount of attention to writing QUALITY code. “Doing it Right” is almost a religion here. For us the buck does not stop at showing a demo of working software to the client, but also ensuring the underlying code is written in the best possible manner using best known software development practices.</p>
<p align="JUSTIFY">To achieve this, it needs a different kind of a culture in the organization that encourages people to go after Quality. This is a lot more difficult than it sounds. Most developers at Xebia will agree that we have a slightly different approach to work (Some call it our culture). A lot of developers joining Xebia India experience these differences first hand &amp; in due course of time, unknowingly they end up picking up these practices themselves. In this article, I list below some changes &amp; practices that I have picked up in the last 2 odd years of my relatively short stay here that helped me be a better programmer.</p>
<p align="JUSTIFY"><span id="more-10927"></span></p>
<p align="JUSTIFY"><strong>Time Vs Quality - Quality should win</strong></p>
<p align="JUSTIFY">Here's what I heard from a programmer at a Beer Session once : “Every time I pickup a programming task, a clock starts ticking in my head. It stops (or resets) only after I declare completion of this task”. IMHO this clock is one of the biggest enemy of Quality. The trouble is that if this clock continues ticking for more time then you planned (working on the task), then it gives a very uncomfortable feeling to the programmer; which leads to pressure to complete the task quickly. This usually happens by cutting corners therefore compromising QUALITY.</p>
<p align="JUSTIFY">For me, I had this clock very loud in my head. I always wanted to declare (task) completion faster than anybody else can imagine (<i>I guess this is a result of my competitive schooling</i>).  Clearly for me, speed was more important than quality earlier. I have tried to change that in recent months. I wouldn't say I have reversed the situation, but now have a different meaning to the word completion – For me now DONE means DONE. If there is an obvious improvement that can be made, then the task is NOT DONE..</p>
<p align="JUSTIFY">&nbsp;</p>
<h3>Test the hell out of your code</h3>
<p align="JUSTIFY">When I was younger, I used to be more confident about new code that I write than I am now. I think the confidence came simply because I hadn't seen enough failures of my code. With Time (and with discovered bugs), I became more careful  &amp; started to write more tests around my code – giving me a better sense of security. While I do see people agree with the above, but a lot of developers treat Tests as second class citizens of development practices. Not enough thought on what exactly needs to be tested is given – without that it is highly likely that tests will not be fully beneficial.</p>
<p align="JUSTIFY"><span style="text-decoration: underline;">What works for me:</span> a) Every time, I discover a problem or a bug in my code – I almost always go back and think why didn't my tests detect this problem earlier. Improve the tests so that the leak does not go undetected again. b) I spend some time thinking about what exactly needs to tested in a class/module. This sounds easier than it is, but with time &amp; practice I think my tests are getting better at finding problems.</p>
<p align="JUSTIFY">&nbsp;</p>
<h3><span style="font-family: 'Liberation Sans', sans-serif;" face="Liberation Sans, sans-serif">Bug Fixing – Fix the root cause &amp; avoid applying a patch</span></h3>
<p align="JUSTIFY">I have been in many situations when the first apparent fix turns out to be a patch on the surface of a bigger problem. The root cause can go undetected easily if nobody questions the fix in totality.</p>
<p align="JUSTIFY"><span style="text-decoration: underline;">What works for me</span>: a) Questions like “If this was the problem, then why didn't it appear in situation X?” go a long way in improving the probability of discovering the root cause. b) Upon finding the possible cause, talking to the author of the code may shed more light about the nature of the problem and sometimes gives a different perspective of the problem. c) Good testers already know this – I try &amp; play more with the problem (reproduce it under different situations); not only the understanding of the problem improves, but sometimes the solution itself becomes really apparent.</p>
<p align="JUSTIFY">&nbsp;</p>
<h3 align="LEFT" lang="en-IN"><span style="color: #000000;" color="#000000">Mistakes are not bad </span></h3>
<p align="JUSTIFY">Mistakes are not bad; but hiding them clearly is. On being pointed out for a possible mistake, my head used to go in the defensive mode and it used to try to come up with either problems in the proposed alternate solution or defend the problem in my code. After having grown some white hair, I have now realized there is no need to do that. It becomes a lot easier if I accept that I goofed up and improve the situation from where it is. That way there is more sense of achievement for everybody involved &amp; the overall environment is geared towards problem solving rather than blaming.</p>
<p align="JUSTIFY"><span style="text-decoration: underline;">What works for me</span>: a) While there is no easy way to avoid mistakes, I think more collaboration within a team can  help. If I'm working on an important piece, I try and get opinion of my team mates on my approach before I start coding. b) If somebody presents an alternate way of solving a problem, I weigh pros &amp; cons of both approaches honestly – without being biased about the code that has already been written or about the author of the code. c) Avoid being emotionally attached to <b>your</b> code – there could be better ways to do what your code does.</p>
<p align="JUSTIFY">&nbsp;</p>
<p align="JUSTIFY">Some other practices that I have picked up &amp; I think are helping me but do not need much explanation are listed below.</p>
<h3 lang="en-IN" align="LEFT">Invest Time in upgrading yourself</h3>
<p align="JUSTIFY">There is always something new to learn - A programming language, a new framework, a new tool etc. Have some way of adding items to your “To learn/Study” list. For me knowledge sharing sessions at Xebia (XKE) do just that.</p>
<h3 align="LEFT" lang="en-IN"></h3>
<div>
<h3 align="LEFT" lang="en-IN">Seek company of better/Senior Programmers</h3>
</div>
<div>
<p align="JUSTIFY">Things like Pair Programming with somebody senior is a very enriching experience. It provides an opportunity to learn &amp; grow. I try &amp; grab opportunities like these whenever they come my way.</p>
<p align="JUSTIFY"><span style="font-size: 15px; font-weight: bold;">Keep company of young software developers</span></p>
</div>
<h5><span style="font-size: 13px; font-weight: normal;">Young software developers challenge practices &amp; don't easily accept them unless proven. This  forces me to think about practices that I have been following myself &amp; re-evaluate them again. They can keep me on my toes all the time - That drives the need to improve myself. Besides having young people in the team can reflect positively in the burn-down chart <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></h5>
<div><span style="font-size: 15px; font-weight: bold;">Hide Nothing &amp; Collaborate more</span></div>
<p align="JUSTIFY">Be Transparent &amp; Hide nothing. This sounds easier than it actually is. However if you are really concerned about quality of your work, then quick feedback (from tests &amp; peer coders) is the only way to find problems early. Seeking peer reviews for an important piece of code is a practice that has helped me a lot. I'm usually asking a lot of questions if there is some ambiguity. If there's anything that I don't know – saying that upfront (even to the client) and asking for help is much better than faking knowledge.</p>
<p align="JUSTIFY"><span style="font-size: 15px; font-weight: bold;">Respect to all</span></p>
<p align="JUSTIFY">In today's world nobody can know it all. There will always be somebody who knows more. Years of experience don't really matter. A Freshman out of college might know better about a particular technology than an experienced programmer &amp; there's no harm in acknowledging that fact. Be humble to all. Anybody can teach you a lesson or so in some field. Keep your eyes &amp; ears open.</p>
<p align="JUSTIFY"><strong>Share knowledge</strong></p>
<p align="JUSTIFY">For a developer; with Knowledge comes power (and money). Contrary to popular belief, the more you spread it the more you get. In other words do not ever hold back knowledge; spread it as much as possible. This IMO will encourage others to do the same and the overall environment becomes very learning friendly.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/19/software-development-practices-that-helped-me-become-better/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Using Hibernate SafeHtml Validator In Application Running On OpenShift Express</title>
		<link>http://xebee.xebia.in/2012/01/18/using-hibernate-safehtml-validator-in-application-running-on-openshift-express/</link>
		<comments>http://xebee.xebia.in/2012/01/18/using-hibernate-safehtml-validator-in-application-running-on-openshift-express/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 17:22:35 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[openshift]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Hibernate Validation]]></category>
		<category><![CDATA[Spring Roo]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10923</guid>
		<description><![CDATA[I use Spring Roo to create sample applications for me. Spring Roo uses JSR 303 (Bean Validation) to validate the entities for invalid values. Today I created a very simple application -- a simple PasteBin clone where you can anonymously create post or share text snippets. I wanted to validate that field post should not [...]]]></description>
			<content:encoded><![CDATA[<p>I use Spring Roo to create sample applications for me. Spring Roo uses JSR 303 (Bean Validation) to validate the entities for invalid values. Today I created a very simple application -- a simple PasteBin clone where you can anonymously create post or share text snippets. I wanted to validate that field post should not contain any Unsafe HTML content in it. So I decided to use Hibernate SafeHtml validator to validate the input field. This post will first show you how to use @SafeHtml validator in an Spring application and then we will deploy the application to OpenShift Express.<span id="more-10923"></span></p>
<p><strong>Create JBoss AS 7 OpenShift Express</strong></p>
<p>Create a jbossas-7.0 OpenShift Express application using rhc-create-app command as shown below.</p>
<pre class="brush: plain; title: ; notranslate">
rhc-create-app -l &lt;rhlogin email&gt; -a pastebin -t jbossas-7.0 -d
</pre>
<p>In case you are not aware of OpenShift Express please refer to the documentation at <a href="https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/index.html">https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/index.html</a></p>
<p><strong>Generate PasteBin clone source using Spring Roo</strong></p>
<p>I am using Spring Roo to create a pastebin clone application and will be using MongoDB as the datastore. In case you are not aware of Spring Roo you can refer to my <a href="http://www.ibm.com/developerworks/views/opensource/libraryview.jsp?search_by=introducing+spring+roo,">IBM DeveloperWorks series on Spring Ro</a>o. But before we create application remove the generated src and pom.xml files using commands shown below.</p>
<pre class="brush: plain; title: ; notranslate">
git rm -rf pom.xml src
git commit -m &quot;removed default files&quot;
</pre>
<p>Now fire the roo shell and execute the following commands to create the application.</p>
<pre class="brush: plain; title: ; notranslate">
project --topLevelPackage com.shekhar.pastebin --projectName pastebin
mongo setup
entity mongo --class ~.domain.Post
field string --fieldName body --notNull --sizeMax 4000
repository mongo --interface ~.repository.PostRepository
service --interface ~.service.PostService
web mvc setup
web mvc all --package ~.web
</pre>
<p><strong>Embed MongoDB Cartridge </strong></p>
<p>After the application has generated add MongoDB cartridge to the application using rhc-ctl-app command as shown below.</p>
<pre class="brush: plain; title: ; notranslate">
rhc-ctl-app -l &lt;rhlogin email&gt; -a pastebin -e add-mongodb-2.0
</pre>
<div></div>
<p><strong>Do Mongo Setup Again</strong></p>
<p>Now that we have embed MongoDB cartridge we should run the mongo setup command again to correctly configure the MongoDB. Fire the roo shell and execute the following line.</p>
<pre class="brush: plain; title: ; notranslate">
mongo setup --databaseName pastebin --username admin --password _cvF8XgIxIzv --host 127.1.27.1 --port 27017
</pre>
<p>Make sure your database.properties file has all the correct value.</p>
<p><strong>Adding HTMLSafe Validator</strong></p>
<p>It is very simple to add HTML validator just add SafeHtml annotation as shown below.</p>
<pre class="brush: java; title: ; notranslate">
package com.shekhar.pastebin.domain;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.layers.repository.mongo.RooMongoEntity;
import org.springframework.roo.addon.tostring.RooToString;
import org.hibernate.validator.constraints.SafeHtml;

@RooJavaBean
@RooToString
@RooMongoEntity
public class Post {

    @NotNull
    @Size(max = 4000)
    @SafeHtml
    private String body;
}
</pre>
<p>Once you have added this annotation if you try and run this on tomcat using mvn tomcat:run you will face <strong>java.lang.ClassNotFoundException : org.jsoup.safety.Whit</strong><strong>elist </strong>while creating a post.</p>
<p>To fix this add jsoup dependency to pom.xml</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
	    &lt;groupId&gt;org.jsoup&lt;/groupId&gt;
	    &lt;artifactId&gt;jsoup&lt;/artifactId&gt;
	    &lt;version&gt;1.6.1&lt;/version&gt;
	&lt;/dependency&gt;
</pre>
<p>Now if you try and run again on tomcat you will be able to successfully create a post.</p>
<p><strong>Running on OpenShift Express</strong></p>
<p>Before you commit the code and push to express you need to first define a maven  profile called openshift. OpenShift uses this profile when it run the build in cloud.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;profile&gt;
     &lt;!-- When built in OpenShift the 'openshift' profile will be used when invoking mvn. --&gt;
     &lt;!-- Use this profile for any OpenShift specific customization your app will need. --&gt;
     &lt;!-- By default that is to put the resulting archive into the 'deployments' folder. --&gt;
     &lt;!-- http://maven.apache.org/guides/mini/guide-building-for-different-environments.html --&gt;
     &lt;id&gt;openshift&lt;/id&gt;
     &lt;build&gt;
        &lt;finalName&gt;demo1&lt;/finalName&gt;
        &lt;plugins&gt;
          &lt;plugin&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.1.1&lt;/version&gt;
            &lt;configuration&gt;
              &lt;outputDirectory&gt;deployments&lt;/outputDirectory&gt;
              &lt;warName&gt;ROOT&lt;/warName&gt;
            &lt;/configuration&gt;
          &lt;/plugin&gt;
        &lt;/plugins&gt;
      &lt;/build&gt;
    &lt;/profile&gt;
</pre>
<p>To push the code on OpenShift Express cloud add the files and commit them as shown below.</p>
<pre class="brush: plain; title: ; notranslate">
git add src pom.xml
git commit -m &quot;adding pastebin application&quot;
</pre>
<p>finally push the code using git push command.</p>
<p>After build has run fine and code deployed to express. Hit the url and try creating a post and you will get "Internal Error". And if you tail the logs using rhc-tail-files command and you will see exception as shown below</p>
<pre class="brush: plain; title: ; notranslate">
org.jsoup.safety.Whitelist from [Module &quot;org.hibernate.validator:main&quot; from local module loader @16aa37a6 (roots: /var/lib/libra/521ca7af66d64093ae386ed99a49a790/linkbin/jbossas-7.0/standalone/configuration/modules,/var/lib/libra/521ca7af66d64093ae386ed99a49a790/linkbin/jbossas-7.0/modules)]
	at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:361)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:333)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:310)
	at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:103)
	at java.lang.Class.getDeclaredFields0(Native Method) [:1.6.0_22]
	at java.lang.Class.privateGetDeclaredFields(Class.java:2308) [:1.6.0_22]
	at java.lang.Class.getDeclaredFields(Class.java:1760) [:1.6.0_22]
</pre>
<p>You might thought why this error is coming as you have already added dependency in pom.xml. The reason is that this validation is carried by Hibernate Validator in JBoss AS7 and you need to add JSoup module.</p>
<p><strong>Adding JSoup and Hibernate </strong><strong>Validator Module </strong></p>
<div>To add module go to the directory where your application exists. There will be folder called .openshift inside which there will be folder called config and under which there will be folder called modules. Create the folder structure as shown below<a href="http://whyjava.files.wordpress.com/2012/01/modules.png"><img class="aligncenter size-full wp-image-1641" title="Modules" src="http://whyjava.files.wordpress.com/2012/01/modules.png" width="630" height="139" /></a></div>
<p>We are adding hibernate validator module also because we need to specify the dependency of jsoup in its module.xml.</p>
<p>The module.xml of hibernate validator is shown below</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;module xmlns=&quot;urn:jboss:module:1.0&quot; name=&quot;org.hibernate.validator&quot;&gt;
  &lt;resources&gt;
    &lt;resource-root path=&quot;hibernate-validator-4.2.0.Final.jar&quot;/&gt;
        &lt;!-- Insert resources here --&gt;
  &lt;/resources&gt;

  &lt;dependencies&gt;
    &lt;module name=&quot;javax.api&quot;/&gt;
    &lt;module name=&quot;javax.persistence.api&quot;/&gt;
    &lt;module name=&quot;javax.validation.api&quot;/&gt;
    &lt;module name=&quot;javax.persistence.api&quot;/&gt;
    &lt;module name=&quot;javax.xml.bind.api&quot;/&gt;
    &lt;module name=&quot;org.jboss.logging&quot;/&gt;
    &lt;module name=&quot;org.jboss.common-core&quot;/&gt;
    &lt;module name=&quot;org.joda.time&quot;/&gt;
    &lt;module name=&quot;org.slf4j&quot;/&gt;
    &lt;module name=&quot;org.jsoup&quot;/&gt;
    &lt;module name=&quot;org.apache.xerces&quot; services=&quot;import&quot;/&gt;
    &lt;module name=&quot;sun.jdk&quot; services=&quot;import&quot;/&gt;
  &lt;/dependencies&gt;
&lt;/module&gt;
</pre>
<p>The module.xml of jsoup is shown below.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;module xmlns=&quot;urn:jboss:module:1.0&quot; name=&quot;org.jsoup&quot;&gt;
  &lt;resources&gt;
    &lt;resource-root path=&quot;jsoup-1.6.1.jar&quot;/&gt;
  &lt;/resources&gt;
&lt;/module&gt;
</pre>
<p>Now add the files, commit to git and do git push. This time you will be able to create the post and validate the post. Try and create post with text shown below and you will get message <span style="color: #ff0000;">may have unsafe html content</span></p>
<pre class="brush: plain; title: ; notranslate">
form action=”http://www.hackablesite.com/submit.php” method=”post”&gt;
&lt;input name=”price” type=”text” value=”1000″ /&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/18/using-hibernate-safehtml-validator-in-application-running-on-openshift-express/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running Spring Java MongoDB Apps on OpenShift Express Using Spring Roo OpenShift Express Addon</title>
		<link>http://xebee.xebia.in/2012/01/09/running-spring-java-mongodb-apps-on-openshift-express-using-spring-roo-openshift-express-addon/</link>
		<comments>http://xebee.xebia.in/2012/01/09/running-spring-java-mongodb-apps-on-openshift-express-using-spring-roo-openshift-express-addon/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 20:54:08 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[openshift]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Spring Roo]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10890</guid>
		<description><![CDATA[Last couple of years Spring Roo has been one of my favorite tool to rapidly build Spring applications for demo, POC, and learning new technologies. With Spring Roo Cloud Foundry integration you can not only build applications rapidly but deploy to Cloud Foundry public cloud with a couple of commands. In case you are not [...]]]></description>
			<content:encoded><![CDATA[<p>Last couple of years Spring Roo has been one of my favorite tool to rapidly build Spring applications for demo, POC, and learning new technologies. With Spring Roo Cloud Foundry integration you can not only build applications rapidly but deploy to Cloud Foundry public cloud with a couple of commands. In case you are not aware of Spring Roo and Cloud Foundry you can refer to my <a href="http://www.ibm.com/developerworks/views/opensource/libraryview.jsp?search_by=introducing+spring+roo,">Spring Roo series on IBM DeveloperWorks</a>. From last 5-6 months I have been following OpenShift platform as a service and I am really in love with OpenShift Express because of its feature set and simplicity. In case you are not aware of OpenShift Express please refer to the <a href="https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/index.html">documentation</a>. There are two ways Java applications can be deployed to express --- using ruby <a href="https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/sect-User_Guide-Application_Development-Creating_Applications.html#sect-User_Guide-Creating_Applications-Using_the_Command_Line">command line tool called RHC</a> and using Eclipse plugin. Personally I like rhc command line more than eclipse plugin. The rhc command line tool is great but you should have ruby runtime installed on your machine. Being Spring Roo afficianado I decided to write Spring Roo OpenShift Express add-on to create, deploy, add cartridges from with Roo shell. This can be thought of as a third way to deploy applications to OpenShift Express. The project is hosted on Google Code at <a href="http://code.google.com/p/spring-roo-openshift-express-addon/">http://code.google.com/p/spring-roo-openshift-express-addon/</a>. In this blog I will show you how you can install the add-on, create a template OpenShift Express application, convert that application to a Spring MongoDB application using Spring Roo, and finally deploy application to OpenShift Express. All of this will be done from with in Roo shell.<span id="more-10890"></span></p>
<p><strong>Prerequisites</strong></p>
<ol>
<li>Sign up at <a href="https://openshift.redhat.com/app/express">https://openshift.redhat.com/app/express</a></li>
<li>Download Spring Roo 1.2 Release from <a href="http://s3.amazonaws.com/dist.springframework.org/release/ROO/spring-roo-1.2.0.RELEASE.zip">Spring Roo website</a>.</li>
<li>Git. OpenShift uses git to deploy applications to OpenShift Express cloud.</li>
<li>SSH keys. OpenShift uses ssh keys for authentication. Please refer to <a href="https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/sect-User_Guide-Authenticating_SSH_Keys.html#sect-User_Guide-Authenticating_SSH_Keys-Generating_new_SSH_keys">documentation for generating your ssh keys</a>.</li>
</ol>
<p><strong>Lets Get Started</strong></p>
<ol>
<li>After you have installed Spring Roo on your machine fire the roo command to load the roo shell.</li>
<li>Install the add-on by executing the following command.
<pre class="brush: plain; title: ; notranslate">
osgi start --url http://spring-roo-openshift-express-addon.googlecode.com/files/org.xebia.roo.addon.openshift-0.1.RELEASE.jar
</pre>
<p>This command will take couple of seconds to execute as it has to download the jar.</li>
<li>Verify that add-on is active by viewing all the osgi process using osgi ps command. You will see output like as shown below that openshift add-on is Active.
<pre class="brush: plain; title: ; notranslate">
[ 166] [Active     ] [    1] spring-roo-openshift-express-addon (0.1.0.RELEASE)
</pre>
</li>
<li>You can view all the available add-on command by typing help command as shown below.
<pre class="brush: plain; title: ; notranslate">
roo&gt; help --command rhc
* rhc app destroy - Destroys the application
* rhc app restart - Restarts the deployed application
* rhc app start - Starts the deployed application
* rhc app status - Gives status of the deployed application
* rhc app stop - stops the deployed application
* rhc cartridge add - Adds a cartridge to the application
* rhc cartridge list - Lists all the avaliable embeddable cartridges
* rhc create jbossas7 app - Creates a new JBoss AS7 OpenShift Express Application
* rhc create jenkins app - Creates a new Jenkins OpenShift Express Application
* rhc deploy - Deploys code to OpenShift Express
* rhc pom - Adds OpenShift Profile to pom.xml
* rhc user info - Displays information about user's OpenShift Express applications
</pre>
<p>You can also view commands by typing rhc and then pressing tab. As you can see from the commands you can do a lot of stuff with this add-on. You can create the application (both jboss and jenkins), do application management (start, stop, destroy, status), view user information, add cartridges (MySQL, MongoDB, Jenkins client, RockMongo client, PhpMyAdmin etc ) and adding OpenShift profile in pom.xml.</li>
<li>Now that add-on has been successfully installed we can create the application. But before you can create the application you have to make sure that you have created the domain. Currently the add-on does not support creating domain but I will be adding support for creating domain in next release. In case you have not created domain please refer to the <a href="https://docs.redhat.com/docs/en-US/OpenShift_Express/1.0/html/User_Guide/sect-User_Guide-Application_Development-Creating_a_Domain.html">documentation to create one</a>. The domain name should be unique. I have created domain name called xke which stands for Xebia Knowledge Exchange.</li>
<li>You can view the information of the user like all the applications created by user using rhc user info command. This is same as rhc-user-info command.</li>
<li>Lets create a simple application  called bookshop which will be simple CRUD application for creating books.  The application will be using MongoDB as datastore. The Java applications created in Express are deployed on JBoss AS 7 server. To create the application type the command shown below.
<pre class="brush: plain; title: ; notranslate">
rhc create jbossas7 app --applicationName bookshop --rhLogin &lt;rhlogin&gt; --password &lt;please&gt;
</pre>
<p>Please type the email and password with which you registered for express. You will see output like as shown below. This command first create the default application, clone the git repository, and deploy the application on express. You can view the application at</p>
<pre class="brush: plain; title: ; notranslate">
Loaded OpenShift configuration from /home/shekhar/.openshift/express.conf
Waiting for OpenShift to propagate DNS
Trying to contact https://bookshop-xke.rhcloud.com/ (attempt 1 of 500)
Git Clone Command : git clone ssh://b85866270d85472886c7f2611b7774ad@bookshop-xke.rhcloud.com/~/git/bookshop.git/ bookshop
Initialized empty Git repository in /home/shekhar/dev/playground/bookshop/.git/
Application Path ./bookshop
Cloned the git repository
Application created and deployed to https://bookshop-xke.rhcloud.com/
</pre>
</li>
<li>Quit the Roo shell and cd into bookshop directory and you will see that<br />
bookshop is a maven based project. Delete these files and commit using git as shown below.</p>
<pre class="brush: plain; title: ; notranslate">
git rm -rf src pom.xml
git commit -m &quot;deleting default files&quot;
</pre>
</li>
<li>Fire the roo command again. Make sure that you are in bookshop directory.</li>
<li>Add the MongoDB cartridge to your application using rhc cartridge add command as shown below.
<pre class="brush: plain; title: ; notranslate">
roo&gt; rhc cartridge add --applicationName bookshop --rhLogin &lt;email&gt; --password &lt;password&gt; --cartridge MONGODB
Loaded OpenShift configuration from /home/shekhar/.openshift/express.conf
Embedded cartridge: mongodb-2.0

MongoDB 2.0 database added.  Please make note of these credentials:

       Root User: admin
   Root Password: j7eCdNsjANyY
   Database Name: bookshop
  Connection URL: mongodb://127.1.13.1:27017/

You can manage your new MongoDB by also embedding rockmongo-1.1
</pre>
</li>
<li>Now that we have added the MongoDB cartridge to our application lets create a simple Spring MongoDB application using Spring Roo. Create the project using Spring Roo project command as shown below.
<pre class="brush: plain; title: ; notranslate">
project --topLevelPackage com.xebia.bookshop --projectName bookshop
</pre>
</li>
<li>After the project setup we need to add MongoDB support to our application using mongodb setup command as shown below.  The MongoDB credentials will be the one that we got back from rhc cartridge command as shown above.
<pre class="brush: plain; title: ; notranslate">
mongo setup --host 127.1.13.1 --username admin --password j7eCdNsjANyY --port 27017 --databaseName bookshop
</pre>
</li>
<li>As this is not a Spring Roo tutorial so I am not going to walk through all the commands. Please refer to Spring Roo documentation or my IBM DeveloperWorks series for more information. Execute the following commands and a simple CRUD bookshop application will be ready.
<pre class="brush: plain; title: ; notranslate">
entity mongo --class ~.domain.Book
field string --fieldName title --notNull
field string --fieldName author --notNull
field number --type double --notNull --fieldName price
repository mongo --interface ~.repository.BookRepository --entity ~.domain.Book
service --interface ~.service.BookService --entity ~.domain.Book
web mvc setup
web mvc all --package ~.web
</pre>
</li>
<li>There is a small bug in the generated code. The bug is that in applicationContext-mongo.xml dbname is referring to a property named mongo.database which does not exist. The correct name of the property is mongo.name. To fix this we can use database properties command as shown below.
<pre class="brush: plain; title: ; notranslate">
database properties remove --key mongo.name
database properties set --key mongo.database --value bookshop
</pre>
</li>
<li>There is just one last thing left before we can push our code to cloud which is that pom.xml file should have a profile called openshift. When we deploy the code to cloud openshift profile gets executed. To add openshift profile please execute rhc pom command.
<pre class="brush: plain; title: ; notranslate">
~.web roo&gt; rhc pom
Updated ROOT/pom.xml [added openshift profile]
</pre>
</li>
<li>Deploy the application using rhc deploy command. This command first add all the files to git , then commit all the files, and then finally do git push. This command will take some time(less than 30 secs) as it has to execute the Maven build which has to download all the jars and then restart the application with new war file.</li>
<li>You can view the status of the application to check if the war has been deployed or not using rhc app status command as shown below. If you don't see any error and see ROOT.war deployed.  This means deployment was successful.
<pre class="brush: plain; title: ; notranslate">
~.web roo&gt; rhc app status --applicationName bookshop --rhLogin &lt;email&gt; --password &lt;password&gt;
Loaded OpenShift configuration from /home/shekhar/.openshift/express.conf
Status ... tailing /var/lib/libra/b85866270d85472886c7f2611b7774ad/bookshop//jbossas-7.0/standalone/log/server.log
------ Tail of bookshop application server.log ------
14:31:58,042 INFO  [org.jboss.as.deployment] (MSC service thread 1-3) Started FileSystemDeploymentService for directory /var/lib/libra/b85866270d85472886c7f2611b7774ad/bookshop/jbossas-7.0/standalone/deployments
14:31:58,387 INFO  [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.2.Final &quot;Arc&quot; started in 6743ms - Started 81 of 106 services (22 services are passive or on-demand)
14:31:58,460 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment of &quot;ROOT.war&quot;
14:32:02,288 INFO  [org.jboss.as.jpa] (MSC service thread 1-4) added javax.persistence.api dependency to ROOT.war
14:32:06,290 INFO  [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (MSC service thread 1-2) No Spring WebApplicationInitializer types detected on classpath
14:32:06,357 INFO  [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (MSC service thread 1-2) Initializing Spring root WebApplicationContext
14:32:09,455 INFO  [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (MSC service thread 1-2) Initializing Spring FrameworkServlet 'bookshop'
14:32:10,698 INFO  [org.hibernate.validator.util.Version] (MSC service thread 1-2) Hibernate Validator 4.2.0.Final
14:32:13,907 INFO  [org.jboss.web] (MSC service thread 1-2) registering web context:
14:32:14,093 INFO  [org.jboss.as.server.controller] (DeploymentScanner-threads - 2) Deployed &quot;ROOT.war&quot;
</pre>
</li>
<li>Go to <a href="http://bookshop-xke.rhcloud.com/">http://bookshop-xke.rhcloud.com/</a></li>
</ol>
<p><strong>Conclusion</strong></p>
<p>In this blog I have not covered all the features of this add-on like Jenkins support, MySQL support etc. There are also couple of things which are still missing like creating domain and some sort of session management so that you don't have to provide username and password with every command. I will try and add them in next release. Please share your suggestions and give feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2012/01/09/running-spring-java-mongodb-apps-on-openshift-express-using-spring-roo-openshift-express-addon/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sakai SSO and multiple WorkSites</title>
		<link>http://xebee.xebia.in/2011/12/31/sakai-sso-and-multiple-worksites/</link>
		<comments>http://xebee.xebia.in/2011/12/31/sakai-sso-and-multiple-worksites/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 13:32:52 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[Sakai]]></category>
		<category><![CDATA[sakai]]></category>
		<category><![CDATA[sakai sso]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10839</guid>
		<description><![CDATA[Recently I was working on a project that modifies Sakai a LMS( Learning Management System) to meet some very specific requirements. One of the requirements that forced me to write this blog was that, we have to perform SSO( Single Sign On) in Sakai, and based on the some parameters land different users in different [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was working on a project that modifies <a href="http://www.google.co.in/url?sa=t&rct=j&q=sakai&source=web&cd=1&ved=0CDIQFjAA&url=http%3A%2F%2Fsakaiproject.org%2F&ei=Ww7_TpTtBNDprQf8zdDcDw&usg=AFQjCNHAJoMs21PrM4GCLIeaD0XE21_LIA&sig2=YEp40b6OyZZKLRq62mpFGQ">Sakai </a>a LMS( Learning Management System) to meet some very specific requirements. One of the requirements that forced me to write this blog was that, we have to perform SSO( Single Sign On) in Sakai, and based on the some parameters land different users in different WorkSites in Sakai. </p>
<p>For <strong>Single Sign On</strong>(SSO allows a user who has been authenticated in a trusted external system seamlessly log into Sakai) in Sakai, you need to invoke <strong>SakaiPortalLogin.jws</strong> Web service from the external system(with a HTTP Client). <span id="more-10839"></span>Here is a detailed explanation of SSO in Sakai : <a href="https://confluence.sakaiproject.org/display/DOC/Sakai+Admin+Guide+-+Advanced+Configuration+Topics"> Sakai Admin Guide:Sakai SSO</a>. In short you will call SakaiPortalLogin.jws web service with some specific parameters and a sakai.Session will be returned. Once you have your user created and logged into the Sakai, you need to associate this user to a particular WorkSite(in Sakai) and land him to that Worksite.</p>
<p>Now you have <strong>sakai.Session</strong> in place. You will redirect the user to a URL like this : <a href="#">http://somehost/portal/worksiteName?sakai.session=sakai-seesion-received-by-you</a>. Now in order to fulfill our requirement we need to place some code in <strong>org.sakaiproject.portal.charon.SkinnableCharonPortal.java</strong>.</p>
<p>First of all we need to add a handler in SkinnableCharonPortal's init() method, that will handle request for a particular WorkSite. Lets say our WorkSite name is <strong>testSite </strong>so we will create a handler named <strong>TestSiteRequestHandler.java</strong> which will extend org.sakaiproject.portal.charon.handlers.WorksiteHandler.<br />
Code for adding a new handler in <a href="http://qa1-nl.sakaiproject.org/codereview/trunk/api/org/sakaiproject/portal/charon/SkinnableCharonPortal.java.html">SkinnableCharonPortal.java</a>'s the init() method : </p>
<pre class="brush: java; title: ; notranslate">
public void init(ServletConfig config) throws ServletException
{
	 super.init(config);
	 portalContext = config.getInitParameter(&quot;portal.context&quot;);
	 if (portalContext == null || portalContext.length() == 0)
	 {
		 portalContext = DEFAULT_PORTAL_CONTEXT;
	 }

	 boolean findPageAliases = ServerConfigurationService.getBoolean(&quot;portal.use.page.aliases&quot;, false);

	 siteHelper = new PortalSiteHelperImpl(this, findPageAliases);

	 portalService = org.sakaiproject.portal.api.cover.PortalService.getInstance();
	 M_log.info(&quot;init()&quot;);

	 forceContainer = ServerConfigurationService.getBoolean(&quot;login.use.xlogin.to.relogin&quot;, true);

	 handlerPrefix = ServerConfigurationService.getString(&quot;portal.handler.default&quot;, &quot;site&quot;);

	 gatewaySiteUrl = ServerConfigurationService.getString(&quot;gatewaySiteUrl&quot;, null);

	 basicAuth = new BasicAuth();
	 basicAuth.init();

	 enableDirect = portalService.isEnableDirect();
	 // do this before adding handlers to prevent handlers registering 2
	 // times.
	 // if the handlers were already there they will be re-registered,
	 // but when they are added again, they will be replaced.
	 // warning messages will appear, but the end state will be the same.
	 portalService.addPortal(this);

	 galleryHandler = new GalleryHandler();
	 worksiteHandler = new WorksiteHandler();
	 siteHandler = new SiteHandler();

	 addHandler(siteHandler);
	 addHandler(new SiteResetHandler());

	 addHandler(new ToolHandler());
	 addHandler(new ToolResetHandler());
	 addHandler(new PageHandler());
	 addHandler(worksiteHandler);
	 addHandler(new WorksiteResetHandler());
	 addHandler(new RssHandler());
	 addHandler(new PDAHandler());
	 addHandler(new AtomHandler());
	 addHandler(new OpmlHandler());
	 addHandler(galleryHandler);
	 addHandler(new GalleryResetHandler());
	 addHandler(new NavLoginHandler());
	 addHandler(new PresenceHandler());
	 addHandler(new HelpHandler());
	 addHandler(new ReLoginHandler());
	 addHandler(new LoginHandler());
	 addHandler(new XLoginHandler());
	 addHandler(new LogoutHandler());
	 addHandler(new ErrorDoneHandler());
	 addHandler(new ErrorReportHandler());
	 addHandler(new StaticStylesHandler());
	 addHandler(new StaticScriptsHandler());
	 addHandler(new DirectToolHandler());
	 addHandler(new RoleSwitchHandler());
	 addHandler(new RoleSwitchOutHandler());
	 addHandler(new TimeoutDialogHandler());
         //Adding our custom Handler
         addHandler(new TestSiteRequestHandler());
}
</pre>
<p>Now the below code written in SkinnableCharonPortal's doGet() method will send the request to appropriate handler(which is TestSiteRequestHandler.java in our case). </p>
<pre class="brush: java; title: ; notranslate">
// recognize what to do from the path
String option = req.getPathInfo();
String[] parts = option.split(&quot;/&quot;);
Map&lt;String, PortalHandler&gt; handlerMap = portalService.getHandlerMap(this);
PortalHandler ph = handlerMap.get(parts[1]);
if (ph != null)
      stat = ph.doGet(parts, req, res, session);
</pre>
<p>Immediate question comes into mind how that happens? Why TestSiteRequestHandler's doGet is called? Here goes the reasoning : When you request the following url with session received in first step of SSO : <a href="#">http://somehost/portal/worksiteName?sakai.session=sakai-seesion-received-by-you</a> the String variable option in the above code will get "/testSite" as its value. And parts[1] is having "testSite" as its value. Thus we are able to retrieve and call the appropriate handler.<br />
The doGet() method of TestSiteRequestHandler looks like : </p>
<pre class="brush: java; title: ; notranslate">
@Override
public int doGet(String[] parts, HttpServletRequest req, HttpServletResponse res, Session session)
throws PortalHandlerException {
User user = UserDirectoryService.getCurrentUser();
if (user != null &amp;&amp; !&quot;&quot;.equals(user.getId())) {
	UserEdit userEdit;
	try {
		userEdit = UserDirectoryService.editUser(user.getId());
		// do all the setting here
		userEdit.set
		userEdit.set
		userEdit.set
		// commit edit
		UserDirectoryService.commitEdit(userEdit);
		// 2nd part is site id
		SiteService.join(AliasService.getInstance().getTarget(&quot;testSite&quot;).split(&quot;/&quot;)[2]);
	} catch (UserNotDefinedException e) {
		log.error(e);
	} catch (UserPermissionException e) {
		log.error(e);
	} catch (UserLockedException e) {
		log.error(e);
	} catch (UserAlreadyDefinedException e) {
		log.error(e);
	} catch (IdUnusedException e) {
		log.error(e);
	} catch (PermissionException e) {
		log.error(e);
	} catch (InUseException e) {
		log.error(e);
	}
}
return 1;
}
</pre>
<p>In the above code you can find the CurrentUser using UserDirectoryService and then you can edit or validate some of the fields based on your requirements. On of the important things that I am doing in the above code is I am associating the current user with "testSite" in this line :</p>
<pre class="brush: java; title: ; notranslate">SiteService.join(AliasService.getInstance().getTarget(&quot;testSite&quot;).split(&quot;/&quot;)[2]);</pre>
<p>which is very important. Basically the AliasService(Sakai's inbuilt Service) is used here to return the UUID formatted unique id of the WorkSite required by SiteService for joining a user.</p>
<p><strong>Handling Multiple WorkSites</strong><br />
In order to achieve our requirements of multiple worksites. Simply add another YourSiteRequestHandler.java in SkinnableCharonPortal.java's init() method. And create a similar doGet() method for YourSiteRequestHandler.java. And then you will be ready to go.</p>
<p>In this blog we learnt how to work with Sakai SSO and logging into different worksites based on some parameters. Hope you will find it useful.</p>
<p>Happy Reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/31/sakai-sso-and-multiple-worksites/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Example of RESTful webservice with XML and JSON using Maven, JAXB, Jersey, Tomcat and cURL</title>
		<link>http://xebee.xebia.in/2011/12/30/example-of-restful-webservice-with-xml-and-json-using-maven-jaxb-jersey-tomcat-and-curl/</link>
		<comments>http://xebee.xebia.in/2011/12/30/example-of-restful-webservice-with-xml-and-json-using-maven-jaxb-jersey-tomcat-and-curl/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 17:49:28 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Restful]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[jaxb]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[RestFul]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10731</guid>
		<description><![CDATA[In this post, I will demonstrate a simple example which will send a request to create a JAXBElement and retrieve it back in the form of XML and JSON using GET/POST HTTP methods respectively. This example will include all the steps from scratch till you get a RESTful web-service working for sending and getting back [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, I will demonstrate a simple example which will send a request to create a JAXBElement and retrieve it back in the form of XML and JSON using GET/POST HTTP methods respectively. This example will include all the steps from scratch till you get a RESTful web-service working for sending and getting back your sample data.</p>
<p>I will also address the exceptions/common mistakes that can be  encountered while using incorrect formats of  XML/JSON . I have however not covered the details of  Restful Services, Jersey, Maven and Tomcat assuming that the reader will be able to find plenty of resources on these topics easily.</p>
<p><span id="more-10731"></span><span style="color: #ffffff;"> </span></p>
<p><span style="color: #ffffff;"> </span></p>
<p><span style="color: #ffffff;"> </span><a href="http://xebee.xebia.in/2011/12/30/example-of-restful-webservice-with-xml-and-json-using-maven-jaxb-jersey-tomcat-and-curl/jerseyeg-3/" rel="attachment wp-att-10827"><img src="http://xebee.xebia.in/wp-content/uploads/2011/12/jerseyEg2.png" title="jerseyEg" class="alignleft size-full wp-image-10827" height="449" width="701" /></a></p>
<p>Let's start with our example.</p>
<p>Step 1. Create a simple maven project in your Eclipse/SpringsourceToolSuite by giving a project name, group and artifact ids, packaging as war.</p>
<p>Step 2. Add the following dependencies to your POM file. To learn more about Jersey and dependencies, click <a title="Jersey Dependency Injection" href="http://jersey.java.net/nonav/documentation/latest/chapter_deps.html" target="_blank">here</a></p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Jersey Server --&gt;
 &lt;dependency&gt;
      &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt;
      &lt;artifactId&gt;jersey-server&lt;/artifactId&gt;
      &lt;version&gt;1.11&lt;/version&gt;
 &lt;/dependency&gt;

&lt;!-- Jersey Servlet container --&gt;
&lt;dependency&gt;
      &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt;
      &lt;artifactId&gt;jersey-servlet&lt;/artifactId&gt;
       &lt;version&gt;1.11&lt;/version&gt;
 &lt;/dependency&gt;

&lt;!-- JSON Support --&gt;
&lt;dependency&gt;
     &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt;
     &lt;artifactId&gt;jersey-json&lt;/artifactId&gt;
     &lt;version&gt;${jersey-version}&lt;/version&gt;
 &lt;/dependency&gt;
</pre>
<p>Step 4. Add the following plugin in case your maven in not using the appropriate compiler plugin to recognize annotations. As a result of this, you will see the <span style="color: #ff0000;">exception -&gt; annotations are not supported in -source 1.3,</span> during compilation</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
   &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
   &lt;configuration&gt;
     &lt;source&gt; 1.6&lt;/source&gt;
     &lt;target&gt;1.6&lt;/target&gt;
   &lt;/configuration&gt;
 &lt;/plugin&gt;
</pre>
<p>Step 5. Create or modify your web.xml file under WEB-INF folder as:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot;
       xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
       xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee
       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
       id=&quot;WebApp_ID&quot; version=&quot;2.5&quot;&gt;
   &lt;display-name&gt;com.xebia.jersey&lt;/display-name&gt;
   &lt;servlet&gt;
     &lt;servlet-name&gt;Jersey REST Service&lt;/servlet-name&gt;
     &lt;servlet-class&gt;com.sun.jersey.spi.container.servlet.ServletContainer&lt;/servlet-class&gt;
     &lt;init-param&gt;
          &lt;param-name&gt;com.sun.jersey.config.property.packages&lt;/param-name&gt;
          &lt;param-value&gt;com.xebia.jersey&lt;/param-value&gt;
     &lt;/init-param&gt;
     &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
   &lt;/servlet&gt;
   &lt;servlet-mapping&gt;
       &lt;servlet-name&gt;Jersey REST Service&lt;/servlet-name&gt;
       &lt;url-pattern&gt;/rest/*&lt;/url-pattern&gt;
   &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
<p>Step 6. Create a JAXBElement , a java class in the package com.xebia.jersey which will act as the data store for this example. To learn more about JAXB with Jersey, click <a title="Jersey, JSON and JAXB" href="http://jersey.java.net/nonav/documentation/latest/json.html">here</a></p>
<pre class="brush: java; title: ; notranslate">
package com.xebia.jersey;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Employee{
 public String fieldSet;
 public Integer id;

 public Employee() {
 };

 public Employee(String fieldSet, int id) {
   this.fieldSet = fieldSet;
   this.id = id;
 }
}
</pre>
<p>Step 7: Create a holder java class in the same package to store multiple Employees as:</p>
<pre class="brush: java; title: ; notranslate">
package com.xebia.jersey;

import java.util.ArrayList;
import java.util.Collection;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Resource {
  public final Collection&lt;Employee&gt; customer = new ArrayList&lt;Employee&gt;();
  public int id;
}
</pre>
<p>Step 8: Create the handler class with annotation @Path("/status")  to tell our jersey servlet container that any request coming from URL ending with /rest/status will be entertained by this class.</p>
<pre class="brush: java; title: ; notranslate">
@Singleton
@Path(&quot;/status&quot;)
public class RequestHandler{

Resource resource= new Resource();

 @GET
 @Produces({ &quot;application/xml&quot;, &quot;application/json&quot; })
 public Resource getStatus() {
    return customers;
 }

 @POST
 @Consumes({&quot;application/xml&quot;, &quot;application/json&quot;})
 public Response createNew(Employee newResource) {
    resource.employee.add(newResource);
    System.out.println(&quot;Created a new Resource&quot;);
    return Response.created(null).build();
 }
}
</pre>
<p>Step 9: Compile your project to a war and rename it to say jersey.war to simplify the context root path of the URL. Now, deploy it to tomcat under wepapps folder. Start the server.<br />
Step 10: Test your app by first posting (HTTP POST ) an XML request to create an employee using cURL as. To download cURL, Click <a title="Download cURL" href="http://curl.haxx.se/download.html">here</a></p>
<pre class="brush: xml; title: ; notranslate">
curl -v -X POST --data-binary &quot;&lt;employee&gt;&lt;fieldSet&gt;richa;23145677;xyz@gmail.com&lt;/fieldSet&gt;&lt;id&gt;1&lt;/id&gt;&lt;/employee&gt;&quot; -H &quot;Content-Type: application/xml&quot; -H &quot;Accept: application/xml&quot; http://localhost:8080/jersey/rest/status
</pre>
<p>You will see the following output on your command prompt:</p>
<pre class="brush: java; title: ; notranslate">
 Connected to localhost (127.0.0.1) port 8080 (#0)
 POST /jersey/rest/status HTTP/1.1
 User-Agent: curl/7.19.3 (i386-pc-win32) libcurl/7.19.3 OpenSSL/0.9.8j
 Host: localhost:8080
 Content-Type: application/xml
 Accept: application/xml
 Content-Length: 107

 HTTP/1.1 201 Created
 Server: Apache-Coyote/1.1
 Content-Length: 0
 Date: Fri, 30 Dec 2011 04:43:15 GMT
</pre>
<p>Step 11: Try retrieving the Employee you just created in JSON and XML formats via HTTP GET using following cURL commands.</p>
<pre class="brush: xml; title: ; notranslate">
curl -v -X GET -H &quot;Accept: application/xml&quot; http://localhost:8080/jersey/rest/status
</pre>
<p><span style="color: #339966;">Result:</span></p>
<pre class="brush: xml; title: ; notranslate">

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/xml
Content-Length: 379
Date: Fri, 30 Dec 2011 06:53:17 GMT

xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;resource&gt;
 &lt;employee&gt;
  &lt;fieldSet&gt;richa;23145677;xyz@gmail.com&lt;/fieldSet&gt;&lt;id&gt;1&lt;/id&gt;
 &lt;/employee&gt;
 &lt;id&gt;0&lt;/id&gt;
&lt;/resource&gt;
</pre>
<pre class="brush: xml; title: ; notranslate">
curl -v -X GET -H &quot;Accept: application/json&quot; http://localhost:8080/jersey/rest/status
</pre>
<p><span style="color: #339966;">Result :</span></p>
<pre class="brush: java; title: ; notranslate">
&quot;employee&quot;:[{&quot;fieldSet&quot;:&quot;richa;97172345;rsinghal@gmaildd.com&quot;,&quot;id&quot;:&quot;2&quot;}],&quot;id&quot;:&quot;0&quot;}*
</pre>
<p><span style="color: #000080;"><strong>Common Exceptions</strong></span>:<br />
1. <span style="color: #ff0000;">HTTP/1.1 400 Bad Request</span><br />
Check the format of your XML/JSON input. While using XML, use the root tag of the element which corresponds to the argument object matches in the @POST method.</p>
<p>2. <span style="color: #ff0000;">HTTP/1.1 404 Not Found</span><br />
Confirm that the path contains the context root name correctly. Eg. if your war is deployed with the name 'jersey', and your web.xml contains url-pattern /rest/*. Then url must contain these locations like : <code><a href="http://localhost:8080/jersey/rest/status">http://localhost:8080/jersey/rest/</a></code></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/30/example-of-restful-webservice-with-xml-and-json-using-maven-jaxb-jersey-tomcat-and-curl/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Culture is the key to productivity</title>
		<link>http://xebee.xebia.in/2011/12/30/culture-is-the-key-to-productivity/</link>
		<comments>http://xebee.xebia.in/2011/12/30/culture-is-the-key-to-productivity/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 10:33:03 +0000</pubDate>
		<dc:creator>Avienaash Shiralige</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Leadership]]></category>
		<category><![CDATA[Project Development Methodologies]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10773</guid>
		<description><![CDATA[India is one of the most favored and favorable offshore/outsourced destination in the world - thanks to the mass scale of engineers it produces. But now the time has come for us to see how we can better productivity - without sacrificing quality (that goes without saying), which will contribute directly to our margins and [...]]]></description>
			<content:encoded><![CDATA[<p>India is one of the most favored and favorable offshore/outsourced destination in the world - thanks to the mass scale of engineers it produces. But now the time has come for us to see how we can better productivity - without sacrificing quality (that goes without saying), which will contribute directly to our margins and net profit. The game has changed from just scaling and being cost- effective to how we can provide maximum business value with less effort.</p>
<p>It’s high time we gave preference to productivity and quality rather than just harp on quantity. There are numerous factors that contribute towards productivity.</p>
<p>Here, I would like to discuss how good culture where ‘Self organized teams’ thrive can contribute to better productivity.</p>
<p><span id="more-10773"></span></p>
<p><img src="http://xebee.xebia.in/wp-content/uploads/2011/12/FourTypesOfTeam.jpg" alt="Four Types of team" /></p>
<p><strong>Steve Denning</strong>, in his research, found that "most of the high performing teams were not manager-led teams. They were teams whose management had deliberately stepped back, or were inattentive, thus enabling teams to self-organize"</p>
<p>Compared to them, the ‘self-governing’ teams did not demonstrate high-performance even on a single occasion. Their struggle for “what to do” always came in the way of their performance. Hence you need leaders on the team to set overall direction in technology, process, and business/product.</p>
<p>Most ‘Self-organized’ teams have the following characteristics</p>
<ul>
<li>Ability to commit to the sprint goals together</li>
<li>They work aggressively to remove impediments to their progress</li>
<li>Collective focus on highest-priority stories</li>
<li>Choose to pair wherever required</li>
<li>Freedom to take risks and to say NO</li>
</ul>
<div></div>
<div>All the above reasons help in generating lot of energy and passion for ‘self-organizing’ teams, which eventually leads to high productivity.</div>
<div></div>
<div></div>
<div>Now let’s look at the table, which is the result of <strong>Geert Hofstede’s years of research</strong> in this field. He has defined multiple parameters for us to understand the culture of different countries.</div>
<div></div>
<div></div>
<div><em>One of the parameters of research was <strong>PDI (Power Distance Index)</strong>. It reflects the extent to which less powerful members of a culture accept that power is unequally distributed and they don't resent the authority easily. This index varies across cultures with Denmark showing highest resentment while China the lowest. This stark variation across countries could be a very interesting and revealing study by itself.</em></div>
<div></div>
<div></div>
<div></div>
<table align="center" border="1">
<tbody>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Country</strong></span></td>
<td><span style="font-size: medium;"><strong>PDI</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>China</strong></span></td>
<td><span style="font-size: medium;"><strong>80</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>India</strong></span></td>
<td><span style="font-size: medium;"><strong>77</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Brazil</strong></span></td>
<td><span style="font-size: medium;"><strong>69</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>United States</strong></span></td>
<td><span style="font-size: medium;"><strong>40</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Netherlands</strong></span></td>
<td><span style="font-size: medium;"><strong>38</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>UK</strong></span></td>
<td><span style="font-size: medium;"><strong>35</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Finland</strong></span></td>
<td><span style="font-size: medium;"><strong>33</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Norway</strong></span></td>
<td><span style="font-size: medium;"><strong>31</strong></span></td>
</tr>
<tr style="background-color: #b5f905;">
<td><span style="font-size: medium;"><strong>Denmark</strong></span></td>
<td><span style="font-size: medium;"><strong>18</strong></span></td>
</tr>
</tbody>
</table>
<p><br mce_bogus="1" /></p>
<p>A PDI score of 70+ for India clearly indicates that people are far less likely to resist the changes – whatsoever - suggested by authority. Not a progressive sign, eh? This applies to teams as well.  They are more susceptible to if we hire a command and control manager/leaders and team may NOT resist this openly.</p>
<p><em><strong>Building an organization which has self-organizing character, with absolutely no hierarchy is immensely tough – more so – as it’s a constant struggle against our own culture/mind set. </strong></em></p>
<p>Preserving this self-organizing culture while we scale is a battle and hence it is extremely important who we bring on-board from middle to senior management. He/she should be a person who is open to work as <strong>servant leaders</strong>.</p>
<p>A key practice for hyper productivity teams is to have servant leaders like product owners and agile coach who provide team leadership as well as work for and with the teams to actively remove impediments.</p>
<p>A common pitfall that self-organized team face is the perception that they do not need any management. While it is true that ‘management’ –in its mere traditional roles - allocating tasks, monitoring progress etc - is not required for self-organized teams, the need for <strong>GOOD LEADERSHIP</strong> is paramount. A person, who is progressive in thinking, shows agility, open for change, and accept newer ways of doing &amp; who enjoys giving and taking freedom.</p>
<p>Good leadership on new agile teams includes</p>
<ul>
<li>Guiding them on collaborating effectively with customers</li>
<li>Showing way</li>
<li>Mentoring them on agile principles and practices</li>
<li>Gradually passing on these roles and responsibilities to the team members</li>
</ul>
<div>Leadership on new teams is usually taken up by Agile coaches (Scrum Masters, ex-Project Managers that have successfully acquired an agile mindset).</div>
<div></div>
<div>But, a common feeling among the managers is: '<strong>Who moved my cheese?</strong> I see this as an opportunity for them to explore new avenues in leadership, scaling different levels in project management then monotonous tasks allocation and reporting.</div>
<div></div>
<div style="text-align: center;"><span style="font-size: medium;"><strong>How effective are your teams self-organization?</strong></span></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/30/culture-is-the-key-to-productivity/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>iOS5 Storyboards: Custom Segue</title>
		<link>http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/</link>
		<comments>http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 08:49:03 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[segue]]></category>
		<category><![CDATA[storyboard]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10618</guid>
		<description><![CDATA[iOS5 have introduced Storyboards, using which you can connect your static views and easily prepare a navigation workflow. Prior to iOS5, we used to have .xib files for every view controller. With Storyboards, all the views (and their controllers) are in one single file with an extension .storyboard. View navigation using storyboard happens with Segues. Segues [...]]]></description>
			<content:encoded><![CDATA[<p>iOS5 have introduced <strong>Storyboards</strong>, using which you can connect your static views and easily prepare a navigation workflow. Prior to iOS5, we used to have .xib files for every view controller. With Storyboards, all the views (and their controllers) are in one single file with an extension .storyboard. View navigation using storyboard happens with <strong>Segues</strong>. Segues define a way using which you can define things like transition type, data flow, etc. To navigate from one view to another, you simply need to CTRL CLICK and DRAG from the source view controller to the destination view controller. For example, if on a click of a button you want the next screen to show up, CTRL CLICK and DRAG from that button to the desired view controller. When you release, you can see three options – PUSH, MODAL and CUSTOM. Push and Modal are self explanatory. But when do you want to use Custom Segues? Before the answer, lets have a look at a use case:</p>
<p><span id="more-10618"></span></p>
<p>A table view controller shows a list of certain categories. When you select a category, a new table view controller is pushed on to the stack and shows the available items in the selected category.</p>
<p><a href="http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/screen-shot-2011-12-28-at-10-36-36-am/" rel="attachment wp-att-10619"></a><a href="http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/screen-shot-2011-12-28-at-10-33-09-am/" rel="attachment wp-att-10620"><img height="300" width="159" src="http://xebee.xebia.in/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-10.33.09-AM-159x300.png" title="Screen Shot 2011-12-28 at 10.33.09 AM" class="alignleft size-medium wp-image-10620" /></a><a href="http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/screen-shot-2011-12-28-at-10-36-36-am/" rel="attachment wp-att-10619"><img height="300" width="159" src="http://xebee.xebia.in/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-10.36.36-AM-159x300.png" title="Screen Shot 2011-12-28 at 10.36.36 AM" class="alignleft size-medium wp-image-10619" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>It looked like i can easily use Segues here. In the .storyboard file, i created the navigation using segues for both the views, and using prepareForSegue: i passed on the required values. But this approach had a loophole. Whenever we use a Push or Modal segue, we are basically pushing a view controller on to the navigation stack. In my case, i would not like the navigationController to be full of the view controllers every time i have to select the item/category. But on the other hand, i do want to loose the ease of prepareForSegue: method. Then, whats the solution? The solution is to create a Custom Segue.</p>
<p>A custom segue extends <a target="_blank" href="http://developer.apple.com/library/IOs/#documentation/UIKit/Reference/UIStoryboardSegue_Class/Reference/Reference.html">UIStoryboardSegue</a>. UIStoryboardSegue contains following properties:</p>
<ul>
<li>sourceViewController</li>
<li>destinationViewController</li>
</ul>
<p>So you can easily specify the transition and navigation type between the source and destination view controllers. A custom segue class contains a <strong>perform</strong> method, where in you can specify the desired behavior.</p>
<p>When you create a segue between views, choose Custom from the options and specify your custom class in the Attributes Inspector (CMD+OPT+4) under Segue Class. In your custom segue class you can write something like below:</p>
<pre class="brush: plain; title: ; notranslate">
- (void) perform {

    UIViewController *src = (UIViewController *) self.sourceViewController;

    [UIView transitionWithView:src.navigationController.view duration:0.1
                       options:UIViewAnimationOptionTransitionNone
                    animations:^{
                        [src.navigationController popViewControllerAnimated:YES];
                    }
                    completion:NULL];

}
</pre>
<p>As you can see i am popping out the current view controller. So now when i perform a navigation between my views using this custom segue, i will be popping out the current view. With this, i am not filling my navigationController with unnecessary view controllers, and i am also able to use the power of prepareForSegue method.</p>
<p>I am attaching a working sample. Please download it from <a href="http://xebee.xebia.in/wp-content/uploads/2011/12/CustomSegues.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/28/ios5-storyboards-custom-segue/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>How to conceptualize a Location Aware Application?</title>
		<link>http://xebee.xebia.in/2011/12/28/how-to-conceptualize-a-location-aware-application/</link>
		<comments>http://xebee.xebia.in/2011/12/28/how-to-conceptualize-a-location-aware-application/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 05:27:43 +0000</pubDate>
		<dc:creator>sraheja</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Location Based Services]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Idea Conceptualization]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Location]]></category>
		<category><![CDATA[Location Aware Applications]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10553</guid>
		<description><![CDATA[With availability of location services in all upcoming smart phones, a number of location aware applications have hit the market. Groupon, Foursquare, Loopt, Roamz and many more are now popular names among users. First of all, let us try to understand usefulness of such applications. Location aware applications are intuitive and have much better user [...]]]></description>
			<content:encoded><![CDATA[<p>With availability of location services in all upcoming smart phones, a number of location aware applications have hit the market. <a href="http://itunes.apple.com/us/app/groupon/id352683833?mt=8">Groupon</a>, <a href="http://itunes.apple.com/in/app/foursquare/id306934924?mt=8">Foursquare</a>, <a href="http://itunes.apple.com/us/app/loopt/id281952554?mt=8">Loopt</a>, <a href="http://itunes.apple.com/us/app/roamz/id459343660?mt=8">Roamz </a>and many more are now popular names among users.</p>
<p>First of all, let us try to understand usefulness of such applications. Location aware applications are intuitive and have much better user experience. Let us say you are travelling and would like to know services and facilities available around you. All you have to do is open an application on your phone and will get to know about various eating outlets around you and much more.</p>
<p>Location awareness has enabled a number of new use cases. Things you earlier could have never thought off. User's location can be used to create solutions for various verticals:</p>
<ul>
<li><strong>Navigation</strong>: Google Maps, TomTom aid users in turn by turn navigation.</li>
<li><strong>Networking</strong>: Foursquare helps you in finding friends currently in your neighbourhood.</li>
<li><strong>Local information about facilities and services</strong>: Roamz shows you social content about places, events and activities around you.</li>
<li><strong>Geo marketing</strong>: Groupon features deals on the best stuff to do, see, eat and buy in your favourite neighbourhoods.</li>
<li><strong>Lifestyle</strong>: Location based reminders are now part of iOS5.</li>
<li><strong>Games</strong>: TrezrHunt is based on real locations where you have to find your way to witch Armagal's treasure.</li>
</ul>
<p>and many more. The benefits are immense for end users as well as business owners.</p>
<p>However, despite so many benefits, adoption rate of such applications is not catching up at the rate expected. According to a <a href="http://www.forrester.com/rb/Research/marketing_via_geosocial_apps_why_and_how/q/id/61072/t/2">new report from Forrester Research</a>, <em>out of 37000 U.S. online adults, only about 5% of  users use location aware applications once a month</em>.<br />
<span id="more-10553"></span><br />
<strong>Concerns</strong><br />
The major concern of the users is their<strong><em> Security and Privacy</em></strong>. They are not comfortable with idea that some one is watching them or someone is trying to look inside their head to understand their shopping behavior.</p>
<p>I have been working on location based solutions for quite some time now. Here are my findings about how such an application should be conceptualized and built so that it does not hinder with user's privacy and is readily accepted among them.</p>
<ul>
<li><strong>Awareness</strong><br />
First and foremost, a user should be well informed about the purpose of the application. How his location will be used to achieve the desired results? He should be made aware of optional and configurable features in the application.&nbsp;</p>
<p>Most of the smart phones do show a permission dialog as soon as application tries to use location for the first time. Sometimes it is not immediately apparent to the user why the application will use his location. If, at that,moment user disallows use of his location, your application will never get the location access. Unless he explicitly allows it from phone's settings, which is less probable.</p>
<p>So, one should always add appropriate information in the application description available on app store. iOS lately has introduced a customizable "Purpose Property" that is shown in the permission dialog required for authorization. One should make full use of such features to make user understand the context and benefits.</li>
<li><strong>Opt-in Tracking</strong><br />
User should be able to turn off location tracking as and when he wants. He should be able to define criteria when his location should be tracked. For example, he may like to do location aware networking during a trade fair, not when he is celebrating his marriage anniversary. Another example can be location aware services should be turned off at night when he is sleeping.User should also be able to configure accuracy level to achieve the desired results, thereby preserving his privacy to an extent and reap benefits as well.</li>
<li><strong>Opt-in Usage</strong><br />
User should be able to configure how his location should be used. For example, in geo marketing applications, user should be able to choose the brands from whom he should receive offers or on his social network, he should be able to filter his location updates among his friends. Some of the latest applications are mining location information to predict users' future locations. Such features should be optional and configurable.</li>
<li><strong>Secure</strong><br />
We should understand that location data is quite sensitive and personal, so if possible, the application should never store it. However, if not, application should either use one of the anonymization techniques or encrypt it before storing user's location specific data. Applications can also use obfuscate location by degrading the quality of information about an individual's location in order to protect his privacy.</li>
<li><strong>Accurate</strong><br />
The location detection algorithm should be accurate. It should take care of inaccurate and false readings. Some of the platforms do give cached locations till GPS hardware warms up. One should handle them appropriately. This is more on the implementation side, I will share my thoughts and techniques on this in a separate blog.</li>
<li><strong>Optimized</strong><br />
Finding accurate location is a battery draining operation for mobile phones. So, the solution should be optimized for battery consumption as per the requirements. Lets say for an application aiding user in turn by turn navigation, higher accuracy is needed along with frequent updates. However, for local weather updates, lower accuracy mode can also achieve the desired results.&nbsp;</p>
<p>Generally most of the periodic location aware solutions are either displacement based or time based. What that means is application will get the next location update from the device after x meters of displacement or after t seconds of time interval. One can play with these parameters and make them dynamic on each subsequent update to optimize battery usage</li>
</ul>
<p><strong>Conclusion</strong><br />
These are some of the basic concepts that one should incorporate while creating a location aware application. It is easy to fall into short term benefits trap by overlooking them, however, in the longer run, adhering to these fundamentals will ensure more acceptability among users.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/28/how-to-conceptualize-a-location-aware-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying Spring Roo MySQL Applications on  JBoss AS7</title>
		<link>http://xebee.xebia.in/2011/12/25/deploying-spring-roo-mysql-applications-on-jboss-as7/</link>
		<comments>http://xebee.xebia.in/2011/12/25/deploying-spring-roo-mysql-applications-on-jboss-as7/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 16:59:23 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[JBoss AS7]]></category>
		<category><![CDATA[Spring Roo]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10558</guid>
		<description><![CDATA[Today I spend some time deploying a simple Spring Roo application on JBoss AS 7. I faced lot of issues in making Spring Roo application run on JBoss AS7. This is a step by step guide from creating Spring Roo application using Roo shell to configuring different databases like h2 and MySQL and finally making [...]]]></description>
			<content:encoded><![CDATA[<p>Today I spend some time deploying a simple Spring Roo application on JBoss AS 7. I faced lot of issues in making Spring Roo application run on JBoss AS7. This is a step by step guide from creating Spring Roo application using Roo shell to configuring different databases like h2 and MySQL and finally making them run on JBoss AS7. So lets get started. Please make sure that you have downloaded latest Spring Roo version 1.2 and JBoss AS 7 from their respective web sites.</p>
<ol>
<li>Created a simple Spring Roo web application by typing the commands shown below.<br><br>
<pre class="brush: plain; title: ; notranslate">
project --topLevelPackage com.shekhar.bookshop --projectName bookshop
jpa setup --database H2_IN_MEMORY --provider HIBERNATE --jndiDataSource java:jboss/datasources/ExampleDS
entity jpa --class ~.domain.Book
field string --fieldName title --notNull
field string --fieldName author --notNull
field number --type double --fieldName price --notNull
web mvc setup
web mvc all --package ~.web
perform package
q
</pre>
</li>
<li>Make sure in the applicationContext.xml the jndi declaration look like as shown below
<pre class="brush: xml; title: ; notranslate">
&lt;jee:jndi-lookup id=&quot;dataSource&quot; jndi-name=&quot;java:jboss/datasources/ExampleDS&quot;/&gt;
</pre>
</li>
<li>Rename the bookshop-0.1.0.BUILD-SNAPSHOT.war to bookshop.war and copy it to &lt;JBoss-AS7-HOME&gt;/standalone/deployments folder and start the server using ./standalone.sh on *nix machines.<span id="more-10558"></span></li>
<li>The deployment will fail and you will see exception stacktrace on the console as show below.
<pre class="brush: plain; title: ; notranslate">
22:28:53,526 INFO  [org.hibernate.cfg.Environment] (MSC service thread 1-8) HHH00021:Bytecode provider name : javassist
22:28:53,555 INFO  [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-8) HHH00204:Processing PersistenceUnitInfo [
	name: persistenceUnit
	...]
22:28:53,584 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC00001: Failed to start service jboss.persistenceunit.&quot;bookshop.war#persistenceUnit&quot;: org.jboss.msc.service.StartException in service jboss.persistenceunit.&quot;bookshop.war#persistenceUnit&quot;: Failed to start service
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1780)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_26]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_26]
	at java.lang.Thread.run(Thread.java:662) [:1.6.0_26]
Caused by: java.lang.RuntimeException: error trying to scan &lt;jar-file&gt;: vfs:/content/bookshop.war/WEB-INF/classes/
	at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:849)
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:591)
	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:72)
	at org.jboss.as.jpa.service.PersistenceUnitService.createContainerEntityManagerFactory(PersistenceUnitService.java:143)
	at org.jboss.as.jpa.service.PersistenceUnitService.start(PersistenceUnitService.java:77)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1824)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1759)
	... 3 more
Caused by: java.lang.RuntimeException: could not load entity class 'void com.shekhar.bookshop.domain.Book_Roo_Jpa_Entity.ajc$declare_at_type_1()' with PersistenceUnitInfo.getNewTempClassLoader()
	at org.jboss.as.jpa.hibernate4.HibernateAnnotationScanner.getClassesInJar(HibernateAnnotationScanner.java:152)
	at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:479)
	at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:846)
	... 9 more
Caused by: java.lang.ClassNotFoundException: void com.shekhar.bookshop.domain.Book_Roo_Jpa_Entity.ajc$declare_at_type_1() from [Module &quot;deployment.bookshop.war:main&quot; from Service Module Loader]
	at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:361)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:310)
	at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:103)
	at org.jboss.as.jpa.hibernate4.HibernateAnnotationScanner.getClassesInJar(HibernateAnnotationScanner.java:148)
	... 11 more
</pre>
</li>
<li>This exception is because of the AspectJ ITD files. Move all the aspectj ITD to Java code using Refactor -&gt; Push in.</li>
<li>Create the package again using mvn clean package command and copy -&gt; rename the war to jboss deployments directory and start the server again using ./standalone.sh. This time you will get following exception.
<pre class="brush: plain; title: ; notranslate">
22:45:18,050 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service jboss.persistenceunit.&quot;bookshop.war#persistenceUnit&quot;: org.jboss.msc.service.StartException in service jboss.persistenceunit.&quot;bookshop.war#persistenceUnit&quot;: Failed to start service
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1780)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_26]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_26]
	at java.lang.Thread.run(Thread.java:662) [:1.6.0_26]
Caused by: java.lang.ClassCastException: org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory
	at org.dom4j.DocumentFactory.getInstance(DocumentFactory.java:97)
	at org.dom4j.DocumentHelper.getDocumentFactory(DocumentHelper.java:36)
	at org.dom4j.DocumentHelper.createDocument(DocumentHelper.java:41)
	at org.hibernate.envers.configuration.RevisionInfoConfiguration.generateDefaultRevisionInfoXmlMapping(RevisionInfoConfiguration.java:86)
	at org.hibernate.envers.configuration.RevisionInfoConfiguration.configure(RevisionInfoConfiguration.java:322)
	at org.hibernate.envers.configuration.AuditConfiguration.&lt;init&gt;(AuditConfiguration.java:94)
	at org.hibernate.envers.configuration.AuditConfiguration.getFor(AuditConfiguration.java:134)
	at org.hibernate.envers.event.EnversIntegrator.integrate(EnversIntegrator.java:63)
	at org.hibernate.internal.SessionFactoryImpl.&lt;init&gt;(SessionFactoryImpl.java:294)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1722)
	at org.hibernate.ejb.EntityManagerFactoryImpl.&lt;init&gt;(EntityManagerFactoryImpl.java:76)
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:899)
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:884)
	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
	at org.jboss.as.jpa.service.PersistenceUnitService.createContainerEntityManagerFactory(PersistenceUnitService.java:143)
	at org.jboss.as.jpa.service.PersistenceUnitService.start(PersistenceUnitService.java:77)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1824)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1759)
	... 3 more
</pre>
</li>
<li>To fix the exception above you will have to update your pom.xml file so that it does not bundle dom4j jar with war file. Update the pom.xml as shown below.
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
			&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
			&lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
			&lt;version&gt;3.6.8.Final&lt;/version&gt;
			&lt;exclusions&gt;
				&lt;exclusion&gt;
					&lt;groupId&gt;dom4j&lt;/groupId&gt;
					&lt;artifactId&gt;dom4j&lt;/artifactId&gt;
				&lt;/exclusion&gt;
			&lt;/exclusions&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;dom4j&lt;/groupId&gt;
			&lt;artifactId&gt;dom4j&lt;/artifactId&gt;
			&lt;version&gt;1.6.1&lt;/version&gt;
			&lt;scope&gt;test&lt;/scope&gt;
		&lt;/dependency&gt;
</pre>
</li>
<li>Again do mvn clean package and deploy the bookshop.war to jboss and start jboss using ./standalone.sh. This time you will get the exception shown below.
<pre class="brush: plain; title: ; notranslate">
23:07:05,205 ERROR [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-5) HHH00231:Schema export unsuccessful: java.lang.UnsupportedOperationException: The application must supply JDBC connections
	at org.hibernate.service.jdbc.connections.internal.UserSuppliedConnectionProviderImpl.getConnection(UserSuppliedConnectionProviderImpl.java:61) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.prepare(SuppliedConnectionProviderConnectionHelper.java:50) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.tool.hbm2ddl.DatabaseExporter.&lt;init&gt;(DatabaseExporter.java:52) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:354) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:291) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:280) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.internal.SessionFactoryImpl.&lt;init&gt;(SessionFactoryImpl.java:440) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1722) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.ejb.EntityManagerFactoryImpl.&lt;init&gt;(EntityManagerFactoryImpl.java:76) [hibernate-entitymanager-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:899) [hibernate-entitymanager-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:884) [hibernate-entitymanager-4.0.0.CR2.jar:4.0.0.CR2]
	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73) [hibernate-entitymanager-4.0.0.CR2.jar:4.0.0.CR2]
	at org.jboss.as.jpa.service.PersistenceUnitService.createContainerEntityManagerFactory(PersistenceUnitService.java:143) [jboss-as-jpa-7.0.2.Final.jar:7.0.2.Final]
	at org.jboss.as.jpa.service.PersistenceUnitService.start(PersistenceUnitService.java:77) [jboss-as-jpa-7.0.2.Final.jar:7.0.2.Final]
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1824)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1759)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_26]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_26]
	at java.lang.Thread.run(Thread.java:662) [:1.6.0_26]
</pre>
</li>
<li>To fix this exception update the persistence.xml to as shown below
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; version=&quot;2.0&quot;
	xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
	&lt;persistence-unit name=&quot;persistenceUnit&quot;
		transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
		&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;

		&lt;non-jta-data-source&gt;java:jboss/datasources/ExampleDS&lt;/non-jta-data-source&gt;
		&lt;class&gt;com.shekhar.bookshop.domain.Book&lt;/class&gt;
		&lt;properties&gt;
			&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.H2Dialect&quot; /&gt;
			&lt;!-- value=&quot;create&quot; to build a new database on each run; value=&quot;update&quot;
				to modify an existing database; value=&quot;create-drop&quot; means the same as &quot;create&quot;
				but also drops tables when Hibernate closes; value=&quot;validate&quot; makes no changes
				to the database --&gt;
			&lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;create&quot; /&gt;
			&lt;property name=&quot;hibernate.ejb.naming_strategy&quot; value=&quot;org.hibernate.cfg.ImprovedNamingStrategy&quot; /&gt;
			&lt;property name=&quot;hibernate.connection.charSet&quot; value=&quot;UTF-8&quot; /&gt;
			&lt;!-- Uncomment the following two properties for JBoss only --&gt;
			&lt;property name=&quot;hibernate.validator.apply_to_ddl&quot; value=&quot;false&quot; /&gt;
			&lt;property name=&quot;hibernate.validator.autoregister_listeners&quot; value=&quot;false&quot; /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
</li>
<li>Update the standalone.xml which exists in JBOSS_HOME/standalone/configuration. Basically you have to mark jta false because we will be using Spring TransactionManager. Please find below the H2 datasource configuration.
<pre class="brush: xml; title: ; notranslate">
&lt;datasource jndi-name=&quot;java:jboss/datasources/ExampleDS&quot; pool-name=&quot;H2DS&quot; enabled=&quot;true&quot; jta=&quot;false&quot; use-java-context=&quot;true&quot; use-ccm=&quot;true&quot;&gt;
                    &lt;connection-url&gt;
                        jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
                    &lt;/connection-url&gt;
                    &lt;driver&gt;
                        h2
                    &lt;/driver&gt;
                    &lt;pool&gt;
                        &lt;prefill&gt;
                            false
                        &lt;/prefill&gt;
                        &lt;use-strict-min&gt;
                            false
                        &lt;/use-strict-min&gt;
                        &lt;flush-strategy&gt;
                            FailingConnectionOnly
                        &lt;/flush-strategy&gt;
                    &lt;/pool&gt;
                    &lt;security&gt;
                        &lt;user-name&gt;
                            sa
                        &lt;/user-name&gt;
                        &lt;password&gt;
                            sa
                        &lt;/password&gt;
                    &lt;/security&gt;
                &lt;/datasource&gt;
</pre>
</li>
<li>Next  you have to do is add entity class declaration in persistence.xml as shown above in persistence.xml</li>
<li>Uncomment the two properties hibernate.validator.apply_to_ddl and hibernate.validator.autoregister_listeners as shown above in persistence.xml.</li>
</ol>
<p>After doing all these changes run the JBoss AS7 using ./standalone.sh file and you will be able to perform CRUD operations on Book.</p>
<p><strong>Switching to MySQL database</strong></p>
<p>Now that we have running Spring Application using H2 database its the time to switch to a production database like MySQL which we will be using normally in our day to day life.</p>
<ol>
<li>To switch database to MySQL we will again use Roo to do it for us. Fire the command show below.
<pre class="brush: plain; title: ; notranslate">
jpa setup --database MYSQL --provider HIBERNATE --jndiDataSource java:jboss/datasources/MysqlDS
</pre>
</li>
<li>Make sure your persistence.xml looks like this. If not please paste this.
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; version=&quot;2.0&quot; xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
&lt;persistence-unit name=&quot;persistenceUnit&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
        &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;non-jta-data-source&gt;java:jboss/datasources/MysqlDS&lt;/non-jta-data-source&gt;
        &lt;class&gt;com.shekhar.bookshop.domain.Book&lt;/class&gt;
        &lt;properties&gt;
            &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.MySQL5InnoDBDialect&quot;/&gt;
            &lt;!-- value=&quot;create&quot; to build a new database on each run; value=&quot;update&quot; to modify an existing database; value=&quot;create-drop&quot; means the same as &quot;create&quot; but also drops tables when Hibernate closes; value=&quot;validate&quot; makes no changes to the database --&gt;
            &lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;create&quot;/&gt;
            &lt;property name=&quot;hibernate.ejb.naming_strategy&quot; value=&quot;org.hibernate.cfg.ImprovedNamingStrategy&quot;/&gt;
            &lt;property name=&quot;hibernate.connection.charSet&quot; value=&quot;UTF-8&quot;/&gt;
            &lt;!-- Uncomment the following two properties for JBoss only --&gt;
            &lt;property name=&quot;hibernate.validator.apply_to_ddl&quot; value=&quot;false&quot; /&gt;
            &lt;property name=&quot;hibernate.validator.autoregister_listeners&quot; value=&quot;false&quot; /&gt;
        &lt;/properties&gt;
    &lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
</li>
<li>Next thing you have to do is configure MySQL datasource in JBoss. This is very eloquently explained at JBoss community web site <a href="http://community.jboss.org/wiki/DataSourceConfigurationInAS7">http://community.jboss.org/wiki/DataSourceConfigurationInAS7</a> so I am not explaining it here.</li>
<li>Once you have setup MySQL datasource your standalone.xml will have a mysql datasource as shown below.
<pre class="brush: xml; title: ; notranslate">
&lt;datasource jndi-name=&quot;java:jboss/datasources/MysqlDS&quot; pool-name=&quot;MysqlDS&quot; enabled=&quot;true&quot; jta=&quot;false&quot; use-java-context=&quot;true&quot; use-ccm=&quot;true&quot;&gt;
                    &lt;connection-url&gt;
                        jdbc:mysql://localhost:3306/bookshop
                    &lt;/connection-url&gt;
                    &lt;driver&gt;
                        com.mysql
                    &lt;/driver&gt;
                    &lt;pool&gt;
                        &lt;min-pool-size&gt;
                            10
                        &lt;/min-pool-size&gt;
                        &lt;max-pool-size&gt;
                            100
                        &lt;/max-pool-size&gt;
                        &lt;prefill&gt;
                            true
                        &lt;/prefill&gt;
                        &lt;use-strict-min&gt;
                            false
                        &lt;/use-strict-min&gt;
                        &lt;flush-strategy&gt;
                            FailingConnectionOnly
                        &lt;/flush-strategy&gt;
                    &lt;/pool&gt;
                    &lt;security&gt;
                        &lt;user-name&gt;
                            root
                        &lt;/user-name&gt;
                        &lt;password&gt;
                            password
                        &lt;/password&gt;
                    &lt;/security&gt;
                    &lt;statement&gt;
                        &lt;prepared-statement-cache-size&gt;
                            32
                        &lt;/prepared-statement-cache-size&gt;
                        &lt;share-prepared-statements/&gt;
                    &lt;/statement&gt;
                &lt;/datasource&gt;
         &lt;drivers&gt;

                    &lt;driver name=&quot;com.mysql&quot; module=&quot;com.mysql&quot;&gt;
                        &lt;xa-datasource-class&gt;
                            com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
                        &lt;/xa-datasource-class&gt;
                    &lt;/driver&gt;
                &lt;/drivers&gt;
</pre>
</li>
<li>Package the application using mvn clean package and deploy it to jboss and run the standalone.sh script. The application should work fine.</li>
</ol>
<p><strong>Conclusion</strong></p>
<p>So in this blog we looked at how we can deploy Spring Roo applications to JBoss and configure H2 datasource and mysql datasource. Hope this helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/25/deploying-spring-roo-mysql-applications-on-jboss-as7/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Grails Custom TextField Tag: Dynamically adding Domain level Field Constraints</title>
		<link>http://xebee.xebia.in/2011/12/19/grails-custom-textfield-tag-dynamically-adding-domain-level-field-constraints/</link>
		<comments>http://xebee.xebia.in/2011/12/19/grails-custom-textfield-tag-dynamically-adding-domain-level-field-constraints/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 11:31:55 +0000</pubDate>
		<dc:creator>Nitin Khattar</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10527</guid>
		<description><![CDATA[Recently in my project, I came across a requirement to add a custom grails textfield in the application. The application is primarily a Web based application with multiple domain classes having numerous nested level associations with each other. Corresponding to the domain classes, there are multiple view pages like Create, Edit, Show, Search, etc. The [...]]]></description>
			<content:encoded><![CDATA[<p>Recently in my project, I came across a requirement to add a custom grails textfield in the application. The application is primarily a Web based application with multiple domain classes having numerous nested level associations with each other. Corresponding to the domain classes, there are multiple view pages like Create, Edit, Show, Search, etc.</p>
<p>The requirement was to add field constraints like ‘<strong>maxSize</strong>’ to both domain classes as well as their respective view pages. Adding such constraints at the domain level is quite easier via ‘<a href="http://www.grails.org/doc/1.3.7/guide/7.%20Validation.html#7.2 Validating Constraints" target="_blank">static constraints block</a>’ within each domain class, but reflecting the same on the view page isn’t easy enough.</p>
<p>For e.g. Adding <strong>maxsize </strong>constraint for a field in a domain class is equivalent to adding <strong>maxlength </strong>property in a textbox corresponding to that field on the view page. So, if the maxSize of a field ‘Short Name’ is say 5, then similarly we can add maxlength equal to 5 in the textfield corresponding to ‘Short Name’. <em>The solution sounds simple &amp; straightforward, but it is neither scalable nor maintainable</em>.  Adding maxlength property to ‘Short Name’ textfield in every view page, where ‘Short Name’ is used, is a time-taking task and also manually updating the maxlength property in every textfield (on change of maxSize constraint at the domain level) is not at all efficient.</p>
<p>So, the question is How to fulfill this requirement, while taking into account the <strong>scalability </strong>&amp; <strong>maintainability </strong>of the solution.<br />
<span id="more-10527"></span></p>
<p>One definite solution is to <em>create a custom grails textfield which in some way reads the ‘maxSize’ constraint value from the domain class and populates the ‘maxLength’ property of the textfield</em>. In this manner, one need not to manually add or update the maxLength value on every view page, rather one just need to add or update maxSize constraint value at the domain level.</p>
<p>So the next thing to identify was How to create such a Smart Tag? Then, I came across this link "<a href="http://www.javathinking.com/2008/03/maxlength-html-attribute-for-domain-objects/" target="_blank">MaxLength HTML attribute for domain objects</a>" hosted on the official <a href="http://www.grails.org/Smarter+grails+tags" target="_blank">Grails Smart Tag webpage</a>. The solution is exactly what we discussed in the above lines.</p>
<pre class="brush: jscript; title: ; notranslate">
def maxlength = object.constraints.&quot;${attrs.name}&quot;.getMaxSize()
if(maxlength) {
attrs.put('maxlength', maxlength)
}
attrs.put('value', fieldValue(bean:object,field:attrs.name)) ...
</pre>
<p>In the above mentioned code, the key thing to look for is</p>
<p>“<strong>object.constraints."${attrs.name}".getMaxSize()</strong>”</p>
<p>**'<span style="text-decoration: underline;">constraints.field</span>’ snippet in the above line returns an object of type ‘<strong><a href="http://grails.org/doc/1.3.x/api/org/codehaus/groovy/grails/validation/ConstrainedProperty.html" target="_blank">ConstrainedProperty</a></strong>’ which in turn has a list of all applied constraints for that field. ConstrainedProperty Class has a vast api exposed for almost every type of <a href="http://grails.org/doc/1.3.x/api/org/codehaus/groovy/grails/validation/Constraint.html" target="_blank">Constraint</a> like <em>maxSize</em>, <em>blank</em>, <em>minSize</em>, <em>email</em>, etc.</p>
<p>But, the moment I tried implementing the same solution in my case, <span style="color: #ff0000;">it just didn’t worked</span>. The reason is that the solution is not compliant to <strong>nested level domain class associations</strong>. What I mean by Nested level associations is that suppose Class A has a field ‘b’ which is of type Class B, which in turn has a field ‘c’ of type String. Then referring to the above mentioned solution, the maxlength value of the textfield pertaining to field ‘b.c’ of Class A will be as follows:</p>
<p style="text-align: center;"><strong> “a.constraints.b.c.getMaxSize()”</strong></p>
<p>Hey, but<span style="color: #ff0000;"> this will not work</span>, because maxSize constraint for ‘c’ is defined within Class B &amp; not in Class A. The above statement should be something like this:</p>
<p style="text-align: center;"><strong> “a.b.constraints.c.getMaxSize()”</strong></p>
<p>Again, for the above statement to execute, ‘b’ must be initialized in order to access its constraints, but in a view page like Create for Entity A, you cannot make sure to initialize ‘b’. Therefore, the above solution is not foolproof.</p>
<p style="text-align: left;"><strong>What should be done in such a case? What could be a generic solution for this problem?</strong></p>
<p style="text-align: left;">An important thing to notice here is that ‘constraint block/closure in domain classes’ is a static block, so one need not to worry about whether the instance is initialized or not. The thing that one should worry about is how to determine the Class from the field name. The simplest way to determine Class from field name is using <strong><em><a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html" target="_blank">java.lang.Class</a>. </em></strong>‘Class.java’ has multiple getter methods out of which following are of great help:</p>
<ul>
<li>Field[] <strong>getFields</strong>() - Returns an array containing <strong><a href="http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html" target="_blank">java.lang.reflect.</a></strong><code><strong><a href="http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html" target="_blank">Field</a></strong></code> objects reflecting all the accessible public fields of the class or interface represented by this <code>Class</code> object.</li>
<li>Field <strong>getField</strong>(String name) : Returns a <code>Field</code> object that reflects the specified public member field of the class or interface represented by this <code>Class</code> object.</li>
<li>Field <strong>getDeclaredField</strong>(String name) : Returns a <code>Field</code> object that reflects the specified declared field of the class or interface represented by this <code>Class</code> object.</li>
</ul>
<p>Using <strong>getDeclaredField(String name)</strong> function, our objective can be easily achieved. ‘<em>getDeclaredField(String name)</em>’ function returns a Field Object for the selected field, which in turn has a property ‘type’ that returns you the Class of the selected field. From the returned Class you can then access the static constraints block. That's all and you are done!!!</p>
<p><strong>Let’s implement the above solution using a real world example:</strong></p>
<p><strong>"</strong>There is a <em>Car </em>domain class which has two fields - String companyName &amp; CarDetails cardDetails. <em>CarDetails </em>class in turn has a field – String color. ‘companyName’ field has a <em>maxSize </em>constraint of 20 characters &amp; ‘color’ has a maxSize constraint of 10. You need to design a ‘<em>create</em>’ view page in order to allow user to add new car entries into the database. The webpage create.gsp will have two textfields: Company Name &amp; Car Color with respective <em>maxLength constraints</em><strong>"</strong></p>
<p>Solution:-</p>
<p><strong>Domain Classes</strong> -</p>
<pre class="brush: java; title: ; notranslate">
class Car {
    CarDetails carDetails
    String companyName
    static constraints = {
        companyName maxSize: 20
    }
}

class CarDetails {
    String color
    static constraints = {
        color maxSize: 10
    }
}
</pre>
<p><strong>Custom TagLib</strong> -</p>
<pre class="brush: java; title: ; notranslate">
class CustomTagLib {
    static namespace = 'custom'
    def textField = {attrs -&gt;
        attrs.type = &quot;text&quot;
        attrs.tagName = &quot;textField&quot;

        def bean = attrs.bean
        String field = attrs.name
        if (bean) {
            Class parentBeanClass = bean.class;
            String fieldName = field
            if (field.indexOf('.')) {
                def val = bean
                def arr = field.split('\\.').toList()
                fieldName = arr.pop()
                arr.each {
                    parentBeanClass = parentBeanClass.getDeclaredField(&quot;$it&quot;)?.type
                }
            }
            if(parentBeanClass){
                ConstrainedProperty constrainedProperty =
                   parentBeanClass.constraints.&quot;${fieldName}&quot;
                def maxlength = constrainedProperty?.getMaxSize() ?: null;
                if(maxlength &amp;&amp; !attrs.maxlength) {
                    attrs.put('maxlength', maxlength)
                }
            }
        }

        def result = field(attrs)
        if (result) {
            out &lt;&lt; result
        }
    }
</pre>
<p><strong>create.gsp</strong> -</p>
<pre class="brush: xml; title: ; notranslate">
…
&lt;custom:textfield id=”companyName” bean=”${carInstance}” name=”companyName”/&gt;
…
&lt;custom:textfield id=”carColor” bean=”${carInstance}” name=”carDetails.color”/&gt;
…
</pre>
<p>In this way I learned how to create grails custom textfield for adding field constraints like ‘maxlength’ dynamically based on corresponding domain level constraints. In case you encounter more efficient ways to solve similar problems, please feel free to share.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/19/grails-custom-textfield-tag-dynamically-adding-domain-level-field-constraints/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introducing Apache Mahout</title>
		<link>http://xebee.xebia.in/2011/12/18/apache-mahout-clustering/</link>
		<comments>http://xebee.xebia.in/2011/12/18/apache-mahout-clustering/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 17:55:17 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[hadoop]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[mahout]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10517</guid>
		<description><![CDATA[Nowadays almost every application is dealing with a descently big amount of data. Irrespective of whether the application is of e-commerce, travel, learning, finance or social networking domain, they all have a good amount of customer data, feedback data, financial records etc. The origin of frameworks in nosql and distributed computing/storage field have also boosted the [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Nowadays almost every application is dealing with a descently big amount of data. Irrespective of whether the application is of e-commerce, travel, learning, finance or social networking domain, they all have a good amount of customer data, feedback data, financial records etc. The origin of frameworks in nosql and distributed computing/storage field have also boosted the applications urge to store all the data it can. Nowadays, servers running on commodity hardware can very easily support storage of billions of records. So, its not at all a big deal for any application to store whatever it can.</p>
<p style="text-align: justify;">The result of all this is a huge heap of records persisted on hard disks on various clouds hosted all around the world. And the world is happy keeping it over there. To add more and more of data every passing day. Apache Mahout can help them increase their happiness.</p>
<p style="text-align: justify;">Apache Mahout is a machine learning framework. Don't get scared by hearing machine learning. Its simple. There is no need for you to go through all the statistical, algorithmic, mathematical formulas to use Apache Mahout. Apache Mahout implements everything for you.<strong> Tells you which algorithm can help in which business scenario, and gives you java classes and CLI's ( Command Line Invocators) to run the algorithms.</strong></p>
<p style="text-align: justify;">Now, lets see what all it can do.</p>
<p style="text-align: justify;"><strong>Recommendation:</strong></p>
<p style="text-align: justify;">You have an application which sells books. The application stores data of who bought which book. This data will anyway be available as the customers and purchase records would be available.</p>
<p style="text-align: justify;">Now, generally readers have similar preferences. A person buying Flex books might be interested in HTML 5 book. A person buying book on Hadoop might be interested in a book on HBase. But how would you know that?<span id="more-10517"></span></p>
<p style="text-align: justify;">Here's where Apache Mahout's recommendation algorithms pitch in. <strong>Mahout has a number of recommendation algorithms which can find out similarity between users. </strong>You just need to provide it all the customer purchases and it would find out recommendations for customers by finding out similar customers. There are algorithms which can also use user ratings to further improve the recommendations.</p>
<p style="text-align: justify;">But, you say you have 1 billion records of customer data. Would Mahout be able to process it?</p>
<p style="text-align: justify;">Yes, another good thing about Apache Mahout is that it is built on top of Hadoop. So, if needed, you can run it on a Hadoop Cluster. If it finds Hadoop Configuration parameters like Hadoop home etc on the server, then it will automatically use the cluster and process data on it. It uses HDFS to read/write records and results when running on Hadoop.</p>
<p style="text-align: justify;">It does not mean that it can run only on Hadoop. Each algorithm is also having an sequential implementation. You have an option to run it on a distributed system or locally. If you have only some hundreds of thousands of records, then why go for a cluster. Just run it on your standalone machine.</p>
<p style="text-align: justify;"><strong>Clustering:</strong></p>
<p style="text-align: justify;">You have a social networking site where people share articles and thoughts. Wouldn't you like to provide users the option to read similar articles? Someone reading an article on tomcat configuration might be interested in articles on other web containers. But how would you find similar articles if there was no user information ever stored. The application does not keep the track of which user read what.</p>
<p style="text-align: justify;">This can be done by using Apache Mahout's Clustering Algorithms. <strong>Apache Mahout's clustering algorithms help in finding groups containing similar items.</strong></p>
<p style="text-align: justify;">How it works? Think of a n-dimensional ( for simplicity, you can also assume a 2-dimensional ) space. Now, plot co-ordinates (0,0), (0,1), (0,1), (1,1) and (5,5), (5,4),(4,5), (4,4) on it. You can very easily see two groups of points on the x-y (2 dimensional) space. One group around (0,0) and another group around (4,4). These groups can also be called as clusters of points.</p>
<p style="text-align: justify;">Apache Mahout's Clustering Algorithms helps in finding out clusters in a vector space. Suppose you are able to express an article in a n-dimensional vector, where each dimension of the vector is representing number of occurrences of a particular word in the article i.e. Suppose in another article, Number of occurrences of "server" = 5, "tomcat"=6, "port"=7 etc. Similarly, all articles having lots of these keywords can be of interest to the reader of Tomcat article (mentioned in the beginning of this section).</p>
<p style="text-align: justify;">Articles is just an example, you can use any of your product's features to find out similar groups. Mahout implements a number of Clustering algorithms, and it can run sequentially as well as on a Hadoop Cluster.</p>
<p style="text-align: justify;"><strong>Classification:</strong></p>
<p style="text-align: justify;"><strong>﻿</strong>When we talked about Clustering in the previous section, that was an example of unsupervised learning. What is unsupervised learning? When you don't have any prior information about the data and relation between them, and you try to extract some information/relation from it. We tried to do that using Clustering.</p>
<p style="text-align: justify;"><strong>﻿Another type of machine learning is supervised learning. In supervised learning, you need to train the algorithm with some prior information.</strong></p>
<p style="text-align: justify;">Lets take the example of a bank which wants to classify its customers into premium, average and useless category. It can pick out some features/properties of customers like balance, number of transactions, credit rating, age of account, number of accounts etc, and figure out premium, average and useless category of users manually for around 1% of the data.</p>
<p style="text-align: justify;">This information needs to be fed into the training algorithm. Now, the algorithm is supervised. It knows which type of user can belong to which category by analyzing the features of the other users. It can now instantly categorize the users into one of the categories.</p>
<p style="text-align: justify;">Classification algorithms generally take a sample input with predefined results and produce/train a model. The model then takes other records and classifies into categories.</p>
<p style="text-align: justify;">This was an overview of what all is in Apache Mahout. In future posts, I will be explaining how to use different features of Mahout.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/18/apache-mahout-clustering/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Advantage of using Regular Expression Extracter postprocessor over XPath exptractor in Jmeter</title>
		<link>http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/</link>
		<comments>http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 11:04:54 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Jmeter]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[JMeter]]></category>
		<category><![CDATA[performace testing]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Software testing]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Xpath Extractor in Jmeter]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10406</guid>
		<description><![CDATA[In my recent project I needed to do performance testing of SSO log-in with 1000 unique users  with JMeter as performance testing tool. With JMeter, it is very easy to pass values from response of one request to subsequent request by using its post-processor requests. During project time I came up with one scenario where [...]]]></description>
			<content:encoded><![CDATA[<p>In my recent project I needed to do performance testing of SSO log-in with 1000 unique users  with JMeter as performance testing tool. With JMeter, it is very easy to pass values from response of one request to subsequent request by using its post-processor requests. During project time I came up with one scenario where values were required to be read from HTTP request and then those values were required to be passed  to next request as input parameters. Please read scenario description which is given below:-</p>
<p><b>Scenario:-</b><b><br />
</b>It was required to extract two values from response of first HTTP request and passing those to subsequent request as parameters. First value was required to be extracted from <strong>body response</strong> of  HTTP request and other value was required to be extracted from its <strong>header response</strong>. Those values were:-</p>
<p>1. <strong>sessionid</strong> –it was required to be extracted from body response of first HTTP request.<br />
2. <strong>node number</strong> – it was required to be extracted from its header response.</p>
<p><b>Solution:-</b></p>
<p>The above problem can be solved by using JMeter’s <strong>Regular Expression Extractor</strong> which can be used to extract values from different response fields like response body, response headers, URL, response code, response message and then will store the extracted results into the given variable name in subsequent request.<span id="more-10406"></span></p>
<p><b>Advantage of Regular Expression Extractor over XPath extractor:-</b></p>
<p>XPath Extractor can also be used to extract values from response but there is advantage of using Regular Expression Extractor as it can read values from response body, response headers, URL, response code, response message but XPath Extractor can extract values from response body only. Secondly, using regular expression results in fast speed of execution as compared to Xpath extractors because regular expression matching is simpler and fast and it is a good replacement of XPath matching which is comparatively slower.</p>
<p><b>Check step by step use of Regular Expression Extractor and XPath Extractor in test plan below:-</b></p>
<p>The above problem has been showcased below by using both Regular Expression Extractor and XPath Extractor. Let’s discuss the steps to create a test plan which illustrates use of both types of extractors which detailing.</p>
<p>1. Create a Test Plan with HTTP sampler.</p>
<p>2. Now add XPath Extractor Post Processor to the first sampler request by right clicking on that request and enter the required reference name and XPath query. XPath Extractor has three fields, which are reference name, XPath query and default value. Let’s discuss what do these terms mean:-</p>
<p><a rel="attachment wp-att-10456" href="http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/xpath_extractor-6/"><img class="aligncenter size-large wp-image-10456" title="XPath_Extractor" src="http://xebee.xebia.in/wp-content/uploads/2011/12/XPath_Extractor5-1024x350.png" height="325" width="666" /></a></p>
<p><strong>Reference name</strong>:-It is a variable name given by user which stores the extracted value. In above example "sessionId" is being used as reference name.</p>
<p><strong>XPath query</strong>:- Functions like local-name() and namespace-uri() can be used in XPath query to match the local tag name and the URI associated with its namespace in JMeter.</p>
<p><strong>Default value</strong>: As name suggests it carries a default value of reference name in case XQuery fails to extract value and we do not want our test case to fail. It is not a mandatory field like above two.</p>
<p>3. Add <strong>Regular Expression Extractor</strong> to first sampler request to extract the value of interest into parameter given in reference name. It is added to first HTTP request to extract value of node number from its header response. It has five fields. Let’s understand what do these terms mean:-</p>
<p><a rel="attachment wp-att-10483" href="http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/regular_expression/"><img class="aligncenter size-large wp-image-10483" title="Regular_Expression" src="http://xebee.xebia.in/wp-content/uploads/2011/12/Regular_Expression-1024x344.png" height="344" width="666" /></a></p>
<p><strong>Reference name</strong>:- In above screenshot “<b>node”</b> is reference variable.</p>
<p><strong>Regular expression</strong>:-User can express any regular expression to search for matching string of text. Regular expression used in above screenshot “node=(.*?)” matches group name node in response containing values as any character 0 or more times</p>
<p><strong>Template</strong>:- The Template is used to create a string from the matches found. Its value can be $1$ and so on depending on which block we want to match. In my case above I wanted it to match with first string block which should match with “(.*?)” regular expression and gets save in variable name “node”. This is the reason I have taken template value as “$1$”.</p>
<p><strong>Match no</strong>:- It Indicates which match to use. The regular expression may match multiple times. In our case there was only one match so I can choose any number either 0 which means for random match or any positive integer which represent nth match. Its good to use positive number here to specify clear match.</p>
<p><strong>Default value</strong>:- It is not a mandatory field like above four.</p>
<p>4. Add next sampler request where you want to use these variables. In screenshot below where ${sessionid} and ${node} are passed as variables in sakai.session and node parameters respectively. Remember, whenever a variable value needs to be passed it should be passed with $ sign and variable name in brackets.</p>
<p><a rel="attachment wp-att-10488" href="http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/parameters/"><img class="aligncenter size-large wp-image-10488" title="Parameters" src="http://xebee.xebia.in/wp-content/uploads/2011/12/Parameters-1024x402.png" height="402" width="666" /></a></p>
<p>5. When Test Plan is run, Regular Expression and XPath Extractor will both execute with their sampler request in its scope and will extract values in given reference names from sampler request and then transfer them to subsequent request.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/12/06/advantage-of-using-regular-expression-extracter-postprocessor-over-xpath-exptractor-in-jmeter/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How would you react on Poor performance of website?</title>
		<link>http://xebee.xebia.in/2011/11/19/how-would-you-react-on-poor-performance-of-website-2/</link>
		<comments>http://xebee.xebia.in/2011/11/19/how-would-you-react-on-poor-performance-of-website-2/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 17:30:20 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[performance testing]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[performace testing]]></category>
		<category><![CDATA[performance testing cycle]]></category>
		<category><![CDATA[Slow performance of website]]></category>
		<category><![CDATA[Software testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10080</guid>
		<description><![CDATA[As Web users you would always want the website to be up whenever you visit it. In addition, you would want to feel that the access is fast.  But what would happen if you do not get the fast access? Would you like to use that website? What will be your immediate reaction?  Would you:- [...]]]></description>
			<content:encoded><![CDATA[<p>As Web users you would always want the website to be up whenever you visit it. In addition, you would want to feel that the access is fast.  But what would happen if you do not get the fast access? Would you like to use that website? What will be your immediate reaction?  Would you:-</p>
<p><strong>-</strong> Look for other alternative OR<br />
<strong>-</strong> Temporarily stop accessing the website OR<br />
<strong>-</strong> Abandon the site permanently</p>
<p>Its not necessary that everybody would have same type of reaction because a site which is fast for one person might not be fast for others. There are various factors which actually make you to take immediate reaction which can be either  patience level, age group,  your need for the site or your knowledge on internet.</p>
<p>Just from curiosity, I did one very small survey a few days ago with 100 facebook users of 18-25 age-group to understand  their different reactions on slow performance of website. They were asked two simple questions . Lets check out those questions and their responses :-<span id="more-10080"></span></p>
<p><em><strong>1. What if facebook becomes slow?</strong></em><br />
<img style="margin-left: 5px;" title="What if facebook becomes slow?" src="http://xebee.xebia.in/wp-content/uploads/2011/11/Screen-shot-2011-11-09-at-5.33.10-PM.png" alt="" width="350" height="250" /><br />
Page load times are very crucial for websites because it not only affects your business, but can leave longer negative effects also. We can see this effect from results of statistical analysis conducted on the data collected from young flock of people who are very active on Facebook. When they were given option of using slower site they had different responses like:-<br />
<strong> 19% of users said that they will delete their account.</strong></p>
<p><strong> 63% of users said they will stop using it and would look for alternative  which is faster because they do not  want to get annoyed.</strong></p>
<p><strong> 18% of users said as they addicted to Facebook , they will not abandon it  completely but may be they stop using it frequently.</strong></p>
<p><em><strong>2. How much time they can wait for each page to load? Below are three options which they were given :-</strong></em><br />
1. 5 Seconds<br />
2. 7 Seconds<br />
3. 10 Seconds<br />
<img title="How much time they can wait for each page to load? " src="http://xebee.xebia.in/wp-content/uploads/2011/11/second-graph.png" alt="" width="350" height="250" /><br />
Second question was asked  in order to discover what page load time make users so impatient. When they were asked with three options more than 60% of them opted for minimum time which is 5 seconds and 25% of them wanted page load time even lesser than 5 seconds.</p>
<p><strong>62% of users said they can bear maximum page response time 5 seconds</strong></p>
<p><strong> 25% said that in today’s world internet  is so fast and they have got faster  internet connections, so they want page response time less than 5 seconds.</strong></p>
<p><strong>13% of users said they can bear till 7  seconds </strong></p>
<p><strong> Surprisingly, there was nobody who opted third option</strong></p>
<p>From above statistics it can be inferred that more than 80% of users are those who do not want to compromise with slowness of Facebook at all and nearly 20% of users will be using Facebook just because they are addicted to it. This seems that majority of users do not want to use slow websites even if it is world’s number 1 social networking site Facebook . Suppose Facebook loses those 80% of its users. What would happen to its business? Definitely it will become outdated and others will capture market.</p>
<p>So, my question to developers or testers or stakeholders is that do we plan for performance testing of our application from the first day of project? I am sure many of  us think that functionality of our site should not break with load of n number of concurrent users per second but we don’t think what if site becomes slow with that much of load. During my last project, we thought about performance testing at the end and our main focus was that our functionality should work with load of baseline numbers given to us but we never thought about the page response time with that much of load which could have made our users irritate enough to abandon our site which in short means losing out business.</p>
<p>Just think how would our business be affected even if we loose 5% of users ?</p>
<p>So, are you ready to let your users go off  your  site just because of its slow performance  which can be improved with little more efforts and right time planning. According to my opinion, we should always think about performance of your site from its beginning because it really plays an important role to stabilize the business value .</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/11/19/how-would-you-react-on-poor-performance-of-website-2/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Scrum is Yogic way of doing software development</title>
		<link>http://xebee.xebia.in/2011/11/09/scrum-is-yogic-way-of-doing-software-development/</link>
		<comments>http://xebee.xebia.in/2011/11/09/scrum-is-yogic-way-of-doing-software-development/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 07:47:13 +0000</pubDate>
		<dc:creator>Avienaash Shiralige</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10133</guid>
		<description><![CDATA[Last few weeks I’ve been reading Speaking Tree – a weekend supplement of ‘Times of India’ and as I read every week, I felt there are lot of similarities between Yoga practice and Scrum philosophy. I’d like to share my perspective on how Yoga and Scrum overlap each other. What is a product here? The [...]]]></description>
			<content:encoded><![CDATA[<p>Last few weeks I’ve been reading Speaking Tree – a weekend supplement of ‘Times of India’ and as I read every week, I felt there are lot of similarities between Yoga practice and Scrum philosophy. I’d like to share my perspective on how Yoga and Scrum overlap each other.</p>
<p><strong>What is a product here?</strong></p>
<p>The product in the case of Yoga is our body (including mind). The product backlog is the list of issues/problems/ that you would like to fix in your body &amp; mind to enhance it. These issues could be physical problems or mental and emotional.</p>
<p><span id="more-10133"></span><br />
<strong>Different roles:</strong></p>
<p>Product Owner – It’s YOU. You are the owner of your body! Hence you will define roadmap for your mind and body.</p>
<p>The Team – It’s all your body parts - your head, hands, legs, lungs, heart (<strong>Imagine the level of collaboration!</strong>)</p>
<p>Scrum Master – Your brain – Toughest part of yoga is to keep a check on your thoughts and evade distractions/obstacles to concentrate on your goal which is to be able to meditate and, do the asanas (work on sprint tasks) without disturbance.</p>
<p><strong>Sprint Goal</strong>: Happy product Owner (You)</p>
<p>Sprint planning meeting: Prayer in each class where you make the commitment to end your 'issues'. You also commit not to add more items in the sprint till you clear the existing items (obviously you would not want more problems!)</p>
<p><strong>The Scrum Cycle in Yoga</strong></p>
<p>As a product owner you demand that you need the best product (mind and body). You have a list of issues (product backlogs); some of which you commit to a particular yoga class (sprint). You want your body parts (the team) to work collaboratively to complete the asanas (tasks) that will help you get the best body (product).</p>
<p>Your Brain (The Scrum master), helps you perform each asana (task) by removing any resistance and helping you focus. The more your brain is able to collaborate with each body part (team) the smoother is completion of asanas (tasks).</p>
<p><strong><em><span style="font-size: small;">There are different stages of yoga; you can't skip a level to achieve the pinnacle in yoga - it is a gradual progression.</span></em></strong></p>
<p>This is true in scrum too; where teams achieve excellence by gradually progressing through different stages of completion like - continuous integration--&gt; continuous deployment--&gt;continuous delivery.</p>
<p>Teams need to follow basic scrum practices to achieve sustained productivity and then move on to follow advanced practices to attain hyper productivity.</p>
<p>Interestingly our body is not designed to handle ‘big bang’ changes, it seeks incremental changes for itself to adapt to the ultimate change we want in your body.</p>
<p><strong><em><span style="font-size: small;">It is very interesting to notice that the essence of yoga is so inherent in scrum. This is testimony to the power of Scrum. So, get going and get yourself some Yoga and Scrum</span></em></strong>.</p>
<p style="text-align: center;"><strong><span style="color: green; font-size: small;">Do you mind being called a ‘Scrum Yogi’?</span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/11/09/scrum-is-yogic-way-of-doing-software-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Do You Think Your Strategy Would Succeed?</title>
		<link>http://xebee.xebia.in/2011/11/07/do-you-think-your-strategy-would-succeed/</link>
		<comments>http://xebee.xebia.in/2011/11/07/do-you-think-your-strategy-would-succeed/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 03:49:20 +0000</pubDate>
		<dc:creator>Avienaash Shiralige</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=10056</guid>
		<description><![CDATA[Small organisations/start-ups face a problem of scaling. People will like to stick to a company which is growing and showing tremendous progress in numbers. Organisations run by command and control have couple of people calling the shots. But agile organisations when it comes to growing, they want their teams to define the tasks of how to [...]]]></description>
			<content:encoded><![CDATA[<p>Small organisations/start-ups face a problem of scaling. People will like to stick to a company which is growing and showing tremendous progress in numbers.</p>
<p>Organisations run by command and control have couple of people calling the shots. But agile organisations when it comes to growing, they want their teams to define the tasks of how to execute a particular strategy. Good, if you have a very mature(great leaders) team who can come up with such a plan. But in many cases the team may require somebody to define those tasks very well for them.</p>
<p>Here we will talk about few common things that block organisations from making strategic progress on their business and some actions to address them.<br />
<span id="more-10056"></span><br />
<strong>Walking the Talk:</strong></p>
<p><em><strong>Smart Talking:</strong></em> Companies often talk about their strategies. Some people fall into the trap of believing, that providing brilliant insights about what is going on in the business is adding value. It isn't. Value comes from doing and showing results.</p>
<p><strong><em>10,000 feet goals:</em></strong> Very high level goals or I want to do this...are another form of talking. Definitely they are highly motivating, but they are vague too. This will not tell people what to do when they start the day!</p>
<p><em><strong>Measurable steps:</strong></em> Strategic progress is made in concrete steps by specific people. So these specific people should translate these goals to clear, comprehendable tasks/action steps that will ensure strategic progress.</p>
<p><strong>Weak alignment:</strong></p>
<p><strong><em>Passive vs Active agreement:</em></strong> There is a big difference between verbal agreements(nodding heads) vs people being ready, willing and committed to make this dream come true!(Active agreement).</p>
<p><strong><em>Get the whole organisation engaged:</em></strong> An org level business strategy should be well communicated and whole organisation should be motivated, involved, engaged to help execute strategic change.<br />
<em><strong> </strong></em></p>
<p><em><strong>Deal with Sabotage:</strong></em> Many times you will find people who will sabotage strategic progress because they disagree or they are personally threatened by change. Putting strategic things to action requires lot of effort with no immediate results. So tactical teams find it tough to accept this. Strategic goals and its tasks should be in the hands of highly motivated people, so that you know they would give their best and honest attempt. On the contrary, lesser motivated people prefer to pick up tactical work to show they are still contributing to the organisation as it shows some visible changes quickly.</p>
<p><strong>Lack of progress tracking and accountability:</strong></p>
<p><strong><em>Deadlines are respected:</em></strong> Deadlines come and go and nothing happens. Does your organisation let this happen? You need to measure, track and follow-up on low level tasks. You have to treat this as any other delivery/client project with specific milestones.</p>
<p>Agile organisation can do strategic stand-ups to measure and re-align tasks whenever required. If a deadline is missed then it's time to have a conversation(retrospective).</p>
<p><strong><em>Are you serious?:</em></strong> If you don't put sufficient time and effort in right direction to bring this change, then there is always reasons and temptations to go back to old way of doing things. This is not strategic failure, but execution failure.<br />
<strong><em> </em></strong></p>
<p><strong><em>Communicate/Connect:</em></strong> You need to communicate/connect with your people frequently to show them that you are dead serious about these strategic goals and by NOT making tactical decisions that undermine strategic progress.</p>
<p>Many organisations are too busy doing tactical things, invest too much effort on immediate needs. Hence they struggle or fail to make fast progress on strategic initiatives. So you need to constantly re-align, remind yourself or measure ROI of current effort.</p>
<p><strong><em>You have to strike a fine balance between tactical vs strategic things. You can't get to $100M business if you are too busy being a $10M business.</em></strong></p>
<p>You have to give <strong>sufficient time and people should have sufficient patience</strong> to see results on strategic initiatives.</p>
<p>You have to define a a <strong>timeline for yourself</strong> to measure and to conclude if you have failed or succeeded in your mission!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/11/07/do-you-think-your-strategy-would-succeed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accessing Scorm Engine using Spring MVC</title>
		<link>http://xebee.xebia.in/2011/11/01/accessing-scorm-engine-using-spring-mvc/</link>
		<comments>http://xebee.xebia.in/2011/11/01/accessing-scorm-engine-using-spring-mvc/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 16:45:47 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[Scorm]]></category>
		<category><![CDATA[ScormEngine]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9961</guid>
		<description><![CDATA[The other day I was working on a POC for one of our clients which involved accessing ScormEngine and syncing our local databases with ScormEngine's databases(as per the need). Initially it seemed tough, but finally I was able to do it. So I thought of sharing my experiences with everyone. Here I am explaining the [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I was working on a POC for one of our clients which involved accessing ScormEngine and syncing our local databases with ScormEngine's databases(as per the need). Initially it seemed tough, but finally I was able to do it. So I thought of sharing my experiences with everyone. Here I am explaining the whole code, hoping that it might help someone as ScormEngine with Spring is not very common.</p>
<p>Here is the GitHub Repository : <a href="https://github.com/vijayrawatsan/ScormEngineWithSpring" target="_blank">GitHub ScormEngineWithSpring</a></p>
<p>Let me briefly tell what Scorm is and what ScormEngine is all about?<br />
<span id="more-9961"></span></p>
<blockquote><p>Sharable Content Object Reference Model (SCORM) is a collection of standards and specifications for web-based e-learning. It defines communications between client side content and a host system called the run-time environment, which is commonly supported by a learning management system. SCORM also defines how content may be packaged into a transferable ZIP file called "Package Interchange Format".</p></blockquote>
<p>-Wikipedia</p>
<p><strong>ScormEngine </strong>is a popular implementation of SCORM provided by Rustici Software. ScormEngine does provide a clean client library(even an example java-web app) to access ScormEngine, but generally we also need to map/sync some ScormEngine database tables with our local database tables which was not covered in the java client. So, I thought of creating a standalone Spring MVC web-app for the same.</p>
<p>It provides basic functionality required by any Scorm client like uploading a course, previewing a course and launching a course(other functions like deleting are pretty straight forward).</p>
<p>Domain model of my application consists of User, Course and RegistrationDetail. User and Course classes include user and course details respectively, and have one to one mapping from course to user(only one owner of a course). In the diagram below you can see how the classes are related with each other:<br />
<img src="http://xebee.xebia.in/wp-content/uploads/2012/01/class.png" alt="Class Relationship" width="400px" height="325px"/><br />
<strong>RegistraionDetail </strong>is a very important domain object. We will require a little background to understand its requirement. Whenever Scorm Content(generally a tutorial/quiz/assignment) is played at client side. We need to collect some information like:</p>
<ul>
<li>which user played it,</li>
<li>how much time he spent on it,</li>
<li>does he/she completed the course,</li>
<li>when did he/she completed the course</li>
</ul>
<p>All this information is very important and stored in the ScormEngine. But in order to generate reports and implement business logic, we need to store that information at our end(with in our apps database) also. </p>
<p>We can see that I have used a <strong>ManyToOne</strong> mapping for User(i.e. learner) and <strong>OneToOne</strong> mapping for Course, this implies that, multiple registrations can occur for a single course(offcourse for different users).<br />
Thats all with the domain model. Now lets see how the ScormEngine services are consumed and the new Services are created for syncing of databases within our application.</p>
<p><strong>ScormEngineService : </strong>It is the core service provided by ScormEngine through which we can access all other services like CourseService, RegistrationService, etc.<br />
For setting up ScormEngineService as a singleton bean use the following scriptlet in your spring-context.xml (or <a href="https://github.com/vijayrawatsan/ScormEngineWithSpring/blob/master/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml">Click to view the Complete context</a>):</p>
<pre class="brush: xml; title: ; notranslate">
&lt;beans:bean class=&quot;com.rusticisoftware.hostedengine.client.ScormEngineService&quot; name=&quot;scormEngineService&quot;&gt;
		&lt;beans:constructor-arg index=&quot;0&quot; value=&quot;http://yourhost:yourport/EngineWebServices/&quot;&gt;&lt;/beans:constructor-arg&gt;
		&lt;beans:constructor-arg index=&quot;1&quot; value=&quot;appID&quot;&gt;&lt;/beans:constructor-arg&gt;
		&lt;beans:constructor-arg index=&quot;2&quot; value=&quot;password&quot;&gt;&lt;/beans:constructor-arg&gt;
&lt;/beans:bean&gt;
</pre>
<p>The first parameter to the constructor is ScormEngine web-service end point, the second parameter is your ApplicationID and the last parameter is the Secret  Key for your application.</p>
<p><strong>So how does this bean(scormEngineService) works?</strong> Basically ScormEngine exposes a list of webServices that we can access using our bean. These web services are of the form :<br />
<a href="#">http://host/api?method=[service.prefix].[methodName]&appid=[your app id]&origin=[your origin string](&any=other&methodparams=here)(&security=params)</a>. </p>
<ul>
<li><strong>method :</strong> This parameter specifies which method of a particular service to call.</li>
<li>Other method specific parameters are also passed like courseId, registrationid, redirectUrl , etc.</li>
<li><strong>appid :</strong> This parameter is your application id registered with ScormEngine.</li>
<li><strong>origin :</strong> This will be a string specifying the organization, application and version of the software making the request.</li>
<li><strong>security :</strong> For secured services a timestamp parameter(ts) of the form yyyyMMddHHmmss (ex. 20081217223530) is passed along with a signature(sig) parameter which is created by hashing(md5) the specifics of a request with your secret key.</li>
</ul>
<p>This bean provides us with instances of different services like CourseService, RegistrationService, UploadService, etc. And these Services will in turn call the webServices exposed by ScormEngine, abstracting the away the part where we need to create timestamp and signature. We will just need to use methods exposed by these Services.<br />
<strong>For example :</strong> Below method from CourseService<br />
ImportCourse(String, File.getAbsolutePath()) is equivalent to posting a file(as binary) on this webService url<br />
<a href="#">http://yourhost/api?method=rustici.course.importCourse&courseid=yourCourseId</a><br />
So in a way these Services abstract the webService calls for us and make these calls clean.</p>
<p><strong>Uploading:</strong><br />
For uploading a course, logic involved is as follows, first of all I will need to create a database entry in my local database and then upload the course to ScormEngine(all this stuff in a single transaction). For that, I created a course detail entry in my local database  and then use <strong>ImportCourse(String courseId, String absoluteFilePath)</strong>; method to import the course to ScormEngine. So basically the actual course file gets uploaded on ScormEngine, but not on my local machine. This one was pretty straight-forward. Below is the code snippet:</p>
<pre class="brush: java; title: ; notranslate">
public ImportResult uploadCourse(File file, String title, User owner) {
		CourseService courseService = scormEngineService.getCourseService();
		List importResults = null;
		try {
			Course course = createCourseLocally(title, owner);
			importResults = courseService.ImportCourse(course.getCourseId(), file.getAbsolutePath());

		}catch (Exception e) {
			logger.info(e.getMessage());
			return null;
		}
		return importResults.get(0);
	}

	private Course createCourseLocally(String title, User owner) {
		Course course = new Course();
		course.setDateCreated(new Date());
		course.setCourseId(&quot;Course-&quot;+UUID.randomUUID().toString());
		course.setOwner(owner);
		course.setTitle(title);
		courseDao.persist(course);
		return course;
	}
</pre>
<p><strong>Difference between previewing and launching:</strong><br />
Previewing means simply viewing the course stored in the ScormEngine without saving any information(usually used to check whether the course is uploaded successfully). On the other hand, Launching allows us to view the course as well as it saves the information like how much time it took, which user played the content, did he/she complete it, etc.</p>
<p>For <strong>Preview</strong> I used <strong>GetPreviewUrl(String courseId, String redirectUrl)</strong>; method to get the preview URLs as follows:</p>
<pre class="brush: java; title: ; notranslate">
List&lt;String&gt; getPreviewUrls(List&lt;CourseData&gt; courseDatas, CourseService courseService) throws Exception {

		List&lt;String&gt; previewUrls = new ArrayList&lt;String&gt;();
		Iterator&lt;CourseData&gt; courseDataIterator = courseDatas.iterator();
		while(courseDataIterator.hasNext())
			previewUrls.add(courseService.GetPreviewUrl(courseDataIterator.next().getCourseId(),&quot;http://localhost:8080/poc/home&quot;));

		return previewUrls;
	}
</pre>
<p><strong>Launch</strong> was a bit tricker. The logic was something like this :  When a user launchs a course the app first checks whether a registration exists for that course and user. If yes fetch the registrationID from database and fire <strong>GetLaunchUrl(String registrationID, String redirectUrl)</strong>; method to get the lauchUrl, else if registration for that course and user does not exist then create a new registration locally and in ScormEngine to GetLaunchUrl for newly created registration.<br />
Now when user exits from the course, we need to fetch/sync the information from ScormEngine to web-app's database. For that we use <strong>GetSummary(String registrationId)</strong>; method which returns information like time spent, complete or incomplete, success, etc.</p>
<p>Below is the code snippet for Launch functionality:</p>
<pre class="brush: java; title: ; notranslate">
public String getLaunchUrl(String courseId, String learnerId, String redirectOnExitUrl) {
		String launchUrl=&quot;&quot;;
		RegistrationService registrationService = scormEngineService.getRegistrationService();
		Course course = courseDao.findByCourseId(courseId);
		User learner = userDao.findUserByUserName(learnerId);
		RegistrationDetail registrationDetail = registrationDetailDao
				.getRegistrationByUserAndCourse(learner, course);
		if(registrationDetail==null) {
			String registrationId = createRegistrarion(course, learner);
			try {
				launchUrl = registrationService
						.GetLaunchUrl(registrationId, redirectOnExitUrl
								+ &quot;?registrationId=&quot; + registrationId);
			}catch (Exception e) {
				logger.info(&quot;Exception GetLaunchUrl : &quot;+ e.getMessage());
			}
		}
		else {
			try {
				launchUrl = registrationService.GetLaunchUrl(
						registrationDetail.getRegistrationId(),
						redirectOnExitUrl + &quot;?registrationId=&quot;
								+ registrationDetail.getRegistrationId());
			}catch (Exception e) {
				logger.info(&quot;Exception GetLaunchUrl : &quot;+ e.getMessage());
			}

		}
		return launchUrl;
	}
</pre>
<pre class="brush: java; collapse: true; light: false; title: ; toolbar: true; notranslate">
	private String createRegistrarion(Course course, User learner) {
		RegistrationDetail registrationDetail = createRegistrationDetailLocally(course,learner);
		RegistrationService registrationService = scormEngineService.getRegistrationService();
		try {
			registrationService.CreateRegistration(
			registrationDetail.getRegistrationId(), course.getCourseId(),
			learner.getUserName(), learner.getFirstName(),
			learner.getLastName());

		}catch (Exception e) {
			logger.info(&quot;Exception createRegistration : &quot;+ e.getMessage());
		}
		return registrationDetail.getRegistrationId();
	}
</pre>
<p>Well, in this blog we see how we can access ScormEngine and easily sync our local databases with all the required information. I will be writing a similar blog for creating a portlet which will access ScormEngine from Liferay. Till then happy reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/11/01/accessing-scorm-engine-using-spring-mvc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>All about Managed Domain &#8211; JBoss AS7</title>
		<link>http://xebee.xebia.in/2011/11/01/all-about-managed-domain-jboss-as7/</link>
		<comments>http://xebee.xebia.in/2011/11/01/all-about-managed-domain-jboss-as7/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 01:28:10 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Administration]]></category>
		<category><![CDATA[AS7]]></category>
		<category><![CDATA[Managed Domain]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9915</guid>
		<description><![CDATA[In a series of blogs I will deal with different aspects/features of JBoss AS7. This is first blog of the series. In this blog I will discuss a new feature in AS-7 called Managed Domain. After reading this blog readers should have good understanding of the managed domain, its use and advantages. Before I start [...]]]></description>
			<content:encoded><![CDATA[<p>In a series of blogs I will deal with different aspects/features of  JBoss AS7. This is first blog of the series. In this blog I will discuss a new feature in AS-7 called Managed Domain. After reading this blog readers should have good understanding of the managed domain, its use and advantages.</p>
<p><span id="more-9915"></span>Before I start the discussion on Managed Domain, it is  important to have a good understanding of the directory structure of  AS7 server. To read about directory structure click <a href="https://docs.jboss.org/author/display/AS7/Getting+Started+Guide#GettingStartedGuide-AS7DirectoryStructure">here</a>.</p>
<p><strong>What is a domain</strong></p>
<p>As developers all of us know that a single instance of JBoss server can be started by starting the JBoss installation in standalone mode. This is true for AS7 also. But the real world UAT or Production setup almost always has a cluster of JBoss application servers running from JBoss installations in different virtual/physical machines. The collection of such JBoss AS servers is called a domain.</p>
<div><a href="http://xebee.xebia.in/wp-content/uploads/2011/10/ManagedDomain1.png" target="_blank"><img class="aligncenter size-medium wp-image-9975" title="ManagedDomain" src="http://xebee.xebia.in/wp-content/uploads/2011/10/ManagedDomain1-300x182.png" alt="" width="300" height="182" /></a></div>
<p><strong>What is a managed domain</strong></p>
<p>If all the servers of a domain have to be managed independently then tasks like app deployment, configuration fine tuning, starting/stopping the server will have to be done for each servers individually. Suppose the servers in the  domain are divided into two groups, and say group-1 should have common apps deployed and a common start-up configuration then it becomes the responsibility of the administrator to ensure the details.</p>
<p>Managed Domain is one of the primary new features of AS7 which provides a single point of control to all application servers in the domain. Before we see how Managed Domain simplifies the task of managing the servers in a domain let us first understand how Managed Domain works on JBoss AS7.</p>
<p><strong>What is Domain Mode</strong></p>
<p>If  there is a need for a mutliple JBoss installation - multi server setup and want them to be Domain Managed then the JBoss installation should be started in Domain mode. To do that go to &lt;JBoss Home&gt;/bin folder and run domain.bat or domain.sh. Definitely some configuration information will have to be fed into some configuration file before you run the domain.sh. I will discuss the configuration details in my next blog.</p>
<p>When the JBoss instance is started in Domain mode then the processes HostController and the DomainController come into existence. HostController and Domain Controller are the basic processes which manage the server instances and help create a managed domain.</p>
<p>Summarily it can be said that HostControllers are responsible for managing all the server instances created from a single JBoss installation. Whereas the DomainController manages the complete domain that  includes all the servers in the domain by talking to all the HostControllers (one per JBoss installation) . Which means all the HostControllers act as slaves to the DomainController.</p>
<p><strong>HostController</strong></p>
<p>When you run the domain.sh/bat file the second line of info log will be</p>
<p>12:08:25,543 INFO  [org.jboss.as.process.Host Controller.status] (main) <strong>Starting process 'Host Controller'</strong>.</p>
<p>Which means that one of the first few process which start as part of domain mode start-up is the HostController.</p>
<p><strong>What is a HostController</strong></p>
<p>HostController is the process which is responsible for</p>
<ol>
<li>Starting up the servers it is supposed to start.</li>
<li>Provide the start up options and configuration information to each server it has started.</li>
<li>Expose the management and public interface to the servers started by it.</li>
<li>Administer the servers under its purview through the management interfaces.</li>
<li>Start up as Domain controller or register with the DomainController of the domain, as slave (Please wait till we discuss the DomainController).</li>
</ol>
<p>Starting up the servers it is supposed to start????? What does that mean? To understand this we will have to navigate to &lt;JBoss Home&gt;/domain/configuration folder. There you will find the file named host.xml. When the HostController starts up it refers to this file to take instructions/configuration information which you as administrator have provided. So let us take a brief look at what is host.xml all about:</p>
<p><strong>Host.xml contains</strong></p>
<ul>
<li><strong>Listing of servers</strong> - which the HostController should start. In the server element the name attribute uniquely identifies the server. 'group' attribute groups the servers of a domain into different groups. Just keep this in mind. We will discuss the grouping in detail when we discuss the DomainController. The auto-start attribute tells the HostController to auto-start the server on start-up or to suspend starting till it is explicitly instructed to start the server through the management interface. And other start up parameters can be passed to each server element which will be passed on by HostController to servers while starting them up.</li>
</ul>
<p><em>Lsiting 1-1</em></p>
<pre class="brush: plain; title: ; notranslate">
&lt;servers&gt;
 &lt;server name=&quot;server-one&quot; group=&quot;main-server-group&quot; auto-start=&quot;true&quot;&gt;
 &lt;jvm name=&quot;default&quot;/&gt;
 &lt;/server&gt;
 &lt;server name=&quot;server-two&quot; group=&quot;main-server-group&quot; auto-start=&quot;true&quot;&gt;
 &lt;jvm name=&quot;default&quot;&gt;
 &lt;heap size=&quot;64m&quot; max-size=&quot;256m&quot;/&gt;
 &lt;/jvm&gt;
 &lt;socket-binding-group ref=&quot;standard-sockets&quot; port-offset=&quot;150&quot;/&gt;
 &lt;/server&gt;
 &lt;servers&gt;
</pre>
<ul>
<li><strong>Management interface </strong> - Host controller also exposes the management interfaces. Management interface can be native or HTTP. Exposing the native interface is mandatory, because the DomainController uses the native interface to interact with the HostController and pass on the admin instructions to HostController. More on this when we discuss the DomainController.</li>
</ul>
<ul>
<li><strong>Master/Slave configuration </strong> - The host controller can be configured to act as the DomainController or the Master HostController of the Domain. To do that just add a &lt;local/&gt; element to the <em>domain-controller </em>declaration. Look at <em>Listing 1-2</em>. To make all other HostController in the domain slave HostControllers just add a remote element in the <em>domain-controller</em> declaration. The remote element provides the inet-addr of the DomainController and the port at which it is available. Please look at<em> Listing 1-3</em>. HostController uses these details to register itself with the domain controller at start up.</li>
</ul>
<p><em>Listing 1-2</em></p>
<pre class="brush: plain; title: ; notranslate">
&lt;domain-controller&gt;
 &lt;local/&gt;
&lt;/domain-controller&gt;
</pre>
<p><em>Listing 1-3</em></p>
<pre class="brush: plain; title: ; notranslate">
&lt;domain-controller&gt;
 &lt;remote host=&quot;192.168.1.143&quot; port=&quot;9999&quot;/&gt;
&lt;/domain-controller&gt;
</pre>
<p><strong>Conclusions</strong></p>
<ol>
<li>Every installation of JBoss servers when started in domain mode will have one HostController per host machine.</li>
<li>HostController can start zero, one or many servers, based on the server declarations in host.xml.</li>
<li>One HostController in a domain acts as DomainController(Master).</li>
<li>All other HostControllers act as slaves to the DomainController.</li>
<li>The HostControllers expose a native management interface so that the HostControllers can communicate with the DomainController and vice-versa.</li>
</ol>
<p><strong>DomainController</strong></p>
<p>You might have already taken a hint by now that one of the HostControllers in domain rises upto the situation and starts acting as the DomainController. Listing 1-2 and Master/Slave configuration section of  host.xml explains how that happens. Let me repeat that DomainController is the single point of control for all the server instances in a domain. The instructions/configuration information are passed from administrator to the DomainController with the help of domain.xml which can be found in<em> &lt;JBossHome&gt;/domain/configuration</em> folder.</p>
<p><strong>domain.xml contains</strong></p>
<ul>
<li>Server  groups - Server groups is logical way of grouping the servers in a domain. In domain.xml admin can define some server groups and assign the desired default settings to each server group. When defining the server elements in host.xml the value for attribute <em>group</em> (Please refer to <em>Listing 1-1 </em>)  should be name of one of  these <em>server-groups</em> defined in domain.xml.  Why  do we want to group the servers at all?  We may want to group the  servers for following reasons
<ol>
<li>If there are groups defined in the domain.xml then DomainController has the option to deploy different set of applications on different group of servers.</li>
<li>Admin can assign different set of capabilities to the groups of servers by assigning them different server profiles.</li>
<li>With groups DomainController can assign different set of socket bindings to the server groups.</li>
<li>Many more such fine tuning can be done at the group level which makes the tasks of the Administrator very simple. Like by deploying a content to one group using the management interface the admin effectively deploys the content to all the servers of the group.</li>
<li>DomainController also takes care of the integrity of the group of servers and if some action fails on any one node of the group, if required the DomainController can roll back the action on all other nodes of the group.</li>
</ol>
</li>
</ul>
<ul>
<li>Profiles &amp; Socket Binding Groups - Discussion on these profiles and Socket Binding Groups is beyond the scope of this blog.</li>
</ul>
<ul>
<li>deployments - Whenever a content is uploaded through the management interface a <em>deployment </em>declaration is added to the <em>deployments </em>declaration of domain.xml. And if the content is added to any of the server group then a <em>deployment</em> declaration is added to the <em>deployments </em>declaration of the server group.</li>
</ul>
<pre class="brush: plain; title: ; notranslate">
&lt;deployments&gt;
 &lt;deployment name=&quot;secured-app.war&quot; runtime-name=&quot;secured-app.war&quot;&gt;
 &lt;content sha1=&quot;b3fe2821a04a54b5000c9b0413f007e3c12cd099&quot;/&gt;
 &lt;/deployment&gt;
 &lt;/deployments&gt;
</pre>
<pre class="brush: plain; title: ; notranslate">
&lt;server-group name=&quot;main-server-group&quot; profile=&quot;default&quot;&gt;
 .........
 &lt;deployments&gt;
 &lt;deployment name=&quot;secured-app.war&quot; runtime-name=&quot;secured-app.war&quot;/&gt;
 &lt;/deployments
 &lt;/server-group&gt;
</pre>
<p><strong>Conclusions</strong><br />
DomainController is the single point of control of all the admin aspects of all servers in a domain.<br />
One of the HostControllers in the domain acts as the DomainController and acts as the master of all the other HostControllers in the domain.<br />
domain.xml is used as the configuration repository for the DomainController. Any changes made to the domain configuration through the management interface are persisted in the domain.xml and is available when the DomainController starts up again.<br />
DomainController uses the concept of server groups to make the administration of similar servers in the domain even simpler.<br />
Deployment of the content to the group is also simplified due the comcept of groups.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/11/01/all-about-managed-domain-jboss-as7/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Spring JSF integration made easy &amp; clean using Spring Annotations</title>
		<link>http://xebee.xebia.in/2011/10/31/spring-jsf-integration-made-easy-clean-using-spring-annotations/</link>
		<comments>http://xebee.xebia.in/2011/10/31/spring-jsf-integration-made-easy-clean-using-spring-annotations/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 17:59:34 +0000</pubDate>
		<dc:creator>Tarun Sapra</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[JSF]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9021</guid>
		<description><![CDATA[With Spring becoming the De-facto framework for Java EE development,  developers are choosing to build their applications around the Spring framework and leveraging the robust programming model of Spring Dependency Injection and it's flexibility to integrate seamlessly with other frameworks. JSF on the other hand is one framework whose component based model has gained wide [...]]]></description>
			<content:encoded><![CDATA[<p>With Spring becoming the De-facto framework for Java EE development,  developers are choosing to build their applications around the Spring framework and leveraging the robust programming model of Spring Dependency Injection and it's flexibility to integrate seamlessly with other frameworks.<br />
JSF on the other hand is one framework whose component based model has gained wide acceptance among the developer community and is becoming the framework of choice for applications involving heavy CRUD operations. This blog intends to showcase the use of Spring annotations to develop a much cleaner and simpler integration between JSF and Spring.</p>
<p><span id="more-9021"></span></p>
<p>When JSF is integrated with Spring, the JSF backing beans are loaded by the Spring container and also their scope are described &amp; managed by the Spring's <strong> @Scope </strong>annotations. Lets start by looking at a snippet from the web.xml of a project using this kind of JSF-Spring integration.</p>
<pre class="brush: xml; title: ; notranslate">
 &lt;listener&gt;
    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
 &lt;/listener&gt;
 &lt;listener&gt;
    &lt;listener-class&gt;org.springframework.web.context.request.RequestContextListener&lt;/listener-class&gt;
 &lt;/listener&gt;
 &lt;context-param&gt;
   &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
   &lt;param-value&gt;/WEB-INF/applicationContext.xml&lt;/param-value&gt;
 &lt;/context-param&gt;
</pre>
<p>In the above code ContextLoaderListener is the bootstrap listener to start up Spring's root WebApplicationContext and RequestContextListener is a listener exposes the request to the current thread.<br />
Now lets take a look at the <strong><em>faces-config.xml</em></strong> file.</p>
<pre class="brush: xml; title: ; notranslate">

 &lt;application&gt;
  &lt;el-resolver&gt;org.springframework.web.jsf.el.SpringBeanFacesELResolver&lt;/el-resolver&gt;
 &lt;/application&gt;
</pre>
<p>The above xml snippet from faces-config is the pivotal part of the JSF-Spring integration, as it delegates the JSF EL calls to the Spring WebApplicationContext.</p>
<p>The following is the JSP containing the JSF form along with JSF EL.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;body&gt;
 &lt;f:view&gt;
  &lt;h:form&gt;
    &lt;h:outputText value=&quot;Enter Your Name:&quot; /&gt;
    &lt;h:inputText value=&quot;#{userForm.userName}&quot; required=&quot;true&quot;/&gt;&lt;br&gt;
    &lt;h:outputText value=&quot;Enter Your Email:&quot; /&gt;
    &lt;h:inputText value=&quot;#{userForm.email}&quot; required=&quot;true&quot;/&gt;&lt;br&gt;
    &lt;h:outputText value=&quot;Enter Your Age:&quot; /&gt;&amp;nbsp;&amp;nbsp;
    &lt;h:commandButton action=&quot;#{userAction.action}&quot; value=&quot;Submit&quot; /&gt;
 &lt;/h:form&gt;
&lt;/f:view&gt;
&lt;/body&gt;
</pre>
<p>In the above form declaration you would have noticed couple of Beans, <em>userForm</em> and <em>userAction</em>. UserForm bean is basically a POJO having setters/getters but most examples of JSF you will find on internet pollute this POJO by adding  action/logic methods inside the POJO for handling the h:commandButton action call. The reason behind this is that the developer would need to write boiler-plate code to make data of one bean(userForm) accessible in another bean(userAction). Though with JSF 2.0 you can use <strong>@ManagedProperty</strong> for achieving this purpose. But with Spring by using <strong>@Autowired </strong>annotation you not only make userForm available in userAction but also other layers of the application(Logic/Dao) can also be injected easily into one-another. Lets see some code</p>
<pre class="brush: java; title: ; notranslate">
@Component
@Scope(&quot;session&quot;)
public class UserForm {

 private String userName;

 private String email;

 private String orderNo;

 private Date orderDate;

 //setters
 //getters

}
</pre>
<p>We have used Spring's @Component and @Scope annotation to declare UserForm as session scoped bean and on the UI(JSP/XHTML) this bean is accessed from JSF EL by the expression #{userForm.userName} (notice <em>userForm</em>, Spring enforces best practices by making beans available only through their corresponding camelCase!)</p>
<pre class="brush: java; title: ; notranslate">

@Component
@Scope(&quot;request&quot;)
public class UserAction {

 @Autowired
 UserForm userForm;

 @Autowired
 UserLogic userLogic;

 UserData userData;

 public String action() {

 userData = userLogic.getResults(userForm.getUserName());
 userForm.setOrderDate(userData.getOrderDate());
 userForm.setOrderNo(userData.getOrderNo());
 return &quot;welcome&quot;;
 }
}
</pre>
<p>Now in the above UserAction class we have used @Autowired to access userForm bean. The UserAction itself is request scope, as it's only purpose is to handle requests. Also in the above code we have <strong>@Autowired </strong>UserLogic class,  it's a class as the name suggests dedicated for carrying out any business logic.</p>
<pre class="brush: java; title: ; notranslate">

 @Component
 @Scope(&quot;prototype&quot;)
 public class UserLogicImpl implements UserLogic {

 @Autowired
 UserDao userDao;

public UserData getResults(String userName) {
 //some logic before calling dao
 return userDao.findByName(userName);
 }
 }
</pre>
<p>Inside UserLogic we have <strong>@Autowired</strong> our DAO class which can be extending any Spring ORM support class(HibernateDaoSupport/SQLMapClientSupport) .</p>
<p>Since we are leveraging  Spring Annotations everywhere, lets take a look at Spring's applicationContext xml file</p>
<pre class="brush: xml; title: ; notranslate">

&lt;context:component-scan base-package=&quot;com.xebia.sample&quot; /&gt;
</pre>
<p>You only need to specify the packages to scan.</p>
<p><span style="text-decoration: underline;"><strong>Conclusion</strong></span><strong> - </strong>Using Spring's annotations we can integrate JSF and Spring in a much cleaner and simpler way. Also you no longer need to write the "<em><strong>&lt;managed-bean&gt;</strong></em>" declaration in faces-config.xml as the bean and it's scope both are handled by the Spring Container.</p>
<p><span style="text-decoration: underline;"><strong> </strong></span></p>
<p><span style="text-decoration: underline;"><strong><br />
</strong></span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/31/spring-jsf-integration-made-easy-clean-using-spring-annotations/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Multitasking aka Multi-Processing in PHP</title>
		<link>http://xebee.xebia.in/2011/10/16/implementing-multithreading-in-php/</link>
		<comments>http://xebee.xebia.in/2011/10/16/implementing-multithreading-in-php/#comments</comments>
		<pubDate>Sun, 16 Oct 2011 08:52:19 +0000</pubDate>
		<dc:creator>Ram Sharma</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Advance PHP]]></category>
		<category><![CDATA[Concurrency]]></category>
		<category><![CDATA[Multithreading]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9938</guid>
		<description><![CDATA[PHP is now quite old in industry and has been used widely in web based applications. PHP has also evolved much more as enterprise web application language. But PHP still lacks a lot many features, which are very commonly and heavily used in Java, .Net or any other enterprise language. One of those lacking features [...]]]></description>
			<content:encoded><![CDATA[<p>PHP is now quite old in industry and has been used widely in web based applications. PHP has also evolved much more as enterprise web application language. But PHP still lacks a lot many features, which are very commonly and heavily used in Java, .Net or any other enterprise language. One of those lacking features in PHP is 'Multi-tasking' or support for concurrent processing.</p>
<p>To implement multi-tasking in PHP, people have found a couple of ways like by using pcntl_fork(), exec() and curl. You can Google out those solutions easily.</p>
<p>Today, I am going to explain you one more way to  implement 'Multi-tasking' using Gearman library and Gearman server. To implement Gearman solution for PHP, you first have to install Gearman server to your machine. You can find more details about Gearman and its installation here: <a title="Gearman" href="http://gearman.org" target="_blank">http://gearman.org/</a></p>
<p>Gearman server comes in 3 flavours C, Java and Perl.</p>
<p><span id="more-9938"></span></p>
<p>I am using Gearman C implementation 'gearmand' as Gearman server in this blog. You can download &amp; install gearmand from here <a title="download gearman" href="http://gearman.org/index.php?id=getting_started" target="_blank">http://gearman.org/index.php?id=getting_started</a>. After installing it you will have to start the server by running this command:</p>
<pre class="brush: php; title: ; notranslate">
$ /usr/local/sbin gearmand -d
#or
$ gearmand -d
</pre>
<p>If you are using windows or Mac, I would suggest you to use Java version of Gearman server. I have not tried that but I think Java version can easily be installed and run on Windows/Mac.</p>
<p>Now when you have Gearman server in place and running you can install any of the PHP client to work with Gearman server. There are two solutions available officially to use Gearman for PHP:</p>
<ol>
<li> 1. PHP extension (currently only supported on Linux but you can try to compile the library on Windows by using Cygwin)</li>
<li> 2. Net_Gearman - pure PHP implementation, a pear module</li>
</ol>
<p>I am using PHP extension on my Ubuntu machine to run examples to explain Multi-tasking. Once you installed extension on your machine (see here for help: http://docs.php.net/manual/en/book.gearman.php), do the following steps:</p>
<p>Create worker php file worker.php or gearman-worker.php. A gearman worker is thread running as worker to perform a specific task requested by clients. Like in this example we are going to use string reverse method as worker task. Here is the code for worker:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// following example code is taken from : http://www.php.net/manual/en/gearman.examples-reverse.php
echo &quot;Starting\n&quot;;

# Create our worker object.
$gmworker= new GearmanWorker();

# Add default server (localhost).
$gmclient-&gt;addServer();

# Register function &quot;reverse&quot; with the server. Change the worker function to
# &quot;reverse_fn_fast&quot; for a faster worker with no output.
$gmworker-&gt;addFunction(&quot;reverse&quot;, &quot;reverse_fn&quot;);

print &quot;Waiting for job...\n&quot;;
while($gmworker-&gt;work())
{
  if ($gmworker-&gt;returnCode() != GEARMAN_SUCCESS)
  {
    echo &quot;return_code: &quot; . $gmworker-&gt;returnCode() . &quot;\n&quot;;
    break;
  }
}

function reverse_fn($job)
{
  echo &quot;Received job: &quot; . $job-&gt;handle() . &quot;\n&quot;;

  $workload = $job-&gt;workload();
  $workload_size = $job-&gt;workloadSize();

  echo &quot;Workload: $workload ($workload_size)\n&quot;;

  # This status loop is not needed, just showing how it works
  for ($x= 0; $x &lt; $workload_size; $x++)   {     echo &quot;Sending status: &quot; . ($x + 1) . &quot;/$workload_size complete\n&quot;;     $job-&gt;sendStatus($x, $workload_size);
    sleep(1);
  }

  $result= strrev($workload);
  echo &quot;Result: $result\n&quot;;

  # Return what we want to send back to the client.
  return $result;
}
</pre>
<p>The above code is creating a GearmanWorker and attaching it to the default Gearman server (local gearmand server process, you can pass server ip and port if your gearman server running on different machine)</p>
<p>To see if the above worker is running properly and producing expected results, you have to run the worker by using the following command:</p>
<pre class="brush: bash; title: ; notranslate">
$ php gearman-worker.php
</pre>
<p>Now create a client to create Job for the worker. Here is the code for the client.php or gearman-client.php:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// following example code is taken from : http://www.php.net/manual/en/gearman.examples-reverse.php

# Create our client object.
$gmclient= new GearmanClient();

# Add default server (localhost).
$gmclient-&gt;addServer();

echo &quot;Sending job\n&quot;;

# Send reverse job
do
{
  $result = $gmclient-&gt;do(&quot;reverse&quot;, &quot;Hello!&quot;);

  # Check for various return packets and errors.
  switch($gmclient-&gt;returnCode())
  {
    case GEARMAN_WORK_DATA:
      echo &quot;Data: $result\n&quot;;
      break;
    case GEARMAN_WORK_STATUS:
      list($numerator, $denominator)= $gmclient-&gt;doStatus();
      echo &quot;Status: $numerator/$denominator complete\n&quot;;
      break;
    case GEARMAN_WORK_FAIL:
      echo &quot;Failed\n&quot;;
      exit;
    case GEARMAN_SUCCESS:
      break;
    default:
      echo &quot;RET: &quot; . $gmclient-&gt;returnCode() . &quot;\n&quot;;
      exit;
  }
}
while($gmclient-&gt;returnCode() != GEARMAN_SUCCESS);

?&gt;
</pre>
<p>Now when you run the above code by:</p>
<pre class="brush: bash; title: ; notranslate">
$ php gearman-client.php
</pre>
<p>It will generate a JOB for gearman worker(s) available on server (in our case, we created only one worker but you can run multiple workers for the same JOB).<br />
The above code is not running the reverse job in background or you can say not running in multi-threaded style. Like we have used:</p>
<pre class="brush: php; title: ; notranslate">
  $result = $gmclient-&gt;do(&quot;reverse&quot;, &quot;Hello!&quot;);
</pre>
<p>Which will hold the code execution of the client until it gets the result or response from worker. To make it multi-threaded you have to modify your code a bit. For example see below:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
//http://docs.php.net/manual/en/gearman.examples-reverse-bg.php
# create our client object
$gmclient= new GearmanClient();

# add the default server (localhost)
$gmclient-&gt;addServer();

# run reverse client in the background
$job_handle = $gmclient-&gt;doBackground(&quot;reverse&quot;, &quot;this is a test&quot;);

if ($gmclient-&gt;returnCode() != GEARMAN_SUCCESS)
{
  echo &quot;bad return code\n&quot;;
  exit;
}

echo &quot;done!\n&quot;;

?&gt;
</pre>
<p>Now just by making the call to worker as:</p>
<pre class="brush: php; title: ; notranslate">
$job_handle = $gmclient-&gt;doBackground(&quot;reverse&quot;, &quot;this is a test&quot;);
</pre>
<p>The code execution will not halt. doBackground() method is the method which is being used for creating a separate thread to perform a specific JOB. The above program will do:</p>
<pre class="brush: php; title: ; notranslate">
echo &quot;done!\n&quot;;
</pre>
<p>and finish the execution as soon as the Job is sent to worker (as it has nothing more to do, you can make some more logic and then check the client status and response)</p>
<p><strong>Conclusion</strong>: Multi-taskingin PHP is not supported in PHP natively, but you have several ways to achieve the same. Gearman server and client libraries is one of the ways you can choose to implement multi-processing in PHP very easily. You can user Gearman library for processing heavy application like: image processing, resizing or do bulk data manipulation, sending emails in bulk etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/16/implementing-multithreading-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why mobile application testing is challenging?</title>
		<link>http://xebee.xebia.in/2011/10/10/why-mobile-application-testing-is-challenging/</link>
		<comments>http://xebee.xebia.in/2011/10/10/why-mobile-application-testing-is-challenging/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 18:23:09 +0000</pubDate>
		<dc:creator>Priyanka</dc:creator>
				<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Mobile Testing]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9900</guid>
		<description><![CDATA[During the last decade, there has been tremendous growth in the number of mobile users and mobile devices. Total number of mobile users have grown more than 852 million in India and 2.6 billion worldwide. This tremendous growth of mobile users has opened up a new market which is flooded with various mobile platforms and [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">During  the last decade, there has been tremendous growth in the number of  mobile users and mobile devices. Total number of mobile users have grown  more than 852 million in India and 2.6 billion worldwide. This  tremendous growth of mobile users has opened up a new market which is  flooded with various mobile platforms and devices like Blackberry,  iPhone, Android devices, other smart phones and tablets, and thousands  of applications to run on them. Gradually, businesses are shifting focus  towards mobile because users are more interested in browsing the web on  their pocket size devices which are more portable. This is the reason  why mobile applications and websites are becoming increasingly important  for enterprises and they are progressively looking towards mobile  while looking to extend their business solutions to reach a wider  audience.</p>
<p>The  diversity of mobile environment, small size of mobile devices and  complexity of mobile hardware and software bring in several challenges  in quality assurance which demand advanced testing strategies. Below are  some points which explain in brief that what the real challenges are in  mobile testing, and why such challenges arise?<span id="more-9900"></span></p>
<p><strong>1) Diversity in Mobile Device platforms:-</strong></p>
<p style="text-align: left;">Android,  Blackberry, Nokia’s Symbian and Apple’s iPhone have together grabbed a  large part of the Smartphone market, but these are not the only mobile  platforms; there are many other mobile platforms that are in use like  BREW, BREWMP, Windows 7, etc. While testing any multiplatform mobile  application, it would be required to test it on each platform while  carrying out  UI testing, functionality testing,etc. It is bit difficult  and challenging because there might be chances of inconsistency in  terms of functionality or UI across multiple platforms as there are  thousands of mobile platforms in market and every platform may have some  limitations.It is simply not possible to test mobile app exhaustively  on each type device available in market.</p>
<p>In  addition, there are few other testing areas that needs to be taken care  for each and every platform. I am explaining few additional testing  aspects for some commonly used platforms below:-</p>
<p><em><strong>Apple:-</strong></em><br />
While making iphone applications we need to keep in mind few things like:-</p>
<ol>
<li> UI Guidelines from Apple need to be adhered to when making applications/websites for IOS.</li>
<li>They should have Backward OS compatibility</li>
<li>Only one application should be allowed to run at a time.</li>
</ol>
<p><em><strong>Android:-</strong></em><br />
We need to keep in mind some additional testing aspects while working for android platform which are :-</p>
<ol>
<li> Android allows to run multiple applications in background</li>
<li> Application gets normally minimized on exiting.</li>
</ol>
<p><em><strong>Blackberry:-</strong></em><br />
Some additional testing aspects for Blackberry applications are given below:-</p>
<ol>
<li>It  allows running multiple applications in background</li>
</ol>
<ul>
<li> Device Reboot is needed for clearing cached data</li>
<li> Device Reboot is needed for uninstalling/installing any application.</li>
<li> Should be Signed/certified by RIM</li>
</ul>
<p><strong>2) Diversity of the Mobile Devices:-</strong></p>
<p>There  is a huge variety of mobile devices available  in market with different  screen sizes , different input methods like touchscreen, qwerty  keypads, trackball and each of them having different hardware  capabilities. We know the fact that testing on every device is not  possible and feasible because we cannot buy every handset and test on  each. We know that exhaustive  testing of user interfaces is very important to ensure compatibility of  the application and verifying UI consistency on every device is  important which is really challenging and time consuming task. It seems that the diversity in handsets is a big challenge for testing.<br />
We know that mobile devices also have different application runtimes  like Binary Runtime Environment for Wireless Java and embedded visual  basic runtime, etc which means applications should be tested specific to runtime  also.</p>
<p><strong>3) Diversity in Hardware Configuration:-</strong></p>
<p>Apart  from diversity in platform and mobile devices, there is diversity in  their hardware also. There are many drawbacks of diverse hardware  configurations. Some of the drawbacks are discussed here like Mobile  environment provides lesser memory and processing power for computing as  compared to PC which results in limitations in processing speed and  variations in performance of applications. Therefore, testing should  ensure that the applications deliver optimum performance for all desired  configurations of hardware. Some mobile devices communicate through WAP  and some use HTTP for communication. Applications should be tested for  their compatibility with WAP-enabled as well as HTTP-enabled devices.</p>
<p><strong>4) Diversity in Network</strong></p>
<p>We  know there is always unpredictability in network latency when  applications communicate over network boundaries, leading to  inconsistent data transfer speeds. It demands testing to measure the  performance of applications for various network bandwidths of various  service providers. Wireless network use data optimizers like gateways to  deliver content and it may result in decreased performance in case of  heavy traffic.  Therefore, testing should be performed to determine the  network traffic level at which gateway capabilities will impact the  performance of the mobile application.</p>
<p>There  are few solutions which can be used to overcome few of  the challenges mentioned above while testing mobile application. I  would recommend mobile testers to use a combination of the below  mentioned techniques along with testing applications on real devices on  real network: -</p>
<ul>
<li>Using  Test automation to increase the test coverage. Some automation tools  available for mobile apps testing are TestComplete, Test Quest Pro,  Robotium, Sikuli, Deviceanywhere, FoneMonkey(iPhone), Eggplant(iPhone),  TestiPhone(For iPhoneMobileWeb), IBM® Rational® Performance Tester  (RPT), MITE(A Mobile content testing and validation tool for Mobile Web  app).</li>
</ul>
<ul>
<li> Testing  on Mobile Emulators mainly for Unit and Integration testing. The  emulators could be used to conduct performance, GUI and compatibility  testing also but the testing using actual devices is preferred.</li>
</ul>
<ul>
<li> Testing on Remote Real devices using Remote Device Access.</li>
</ul>
<ul>
<li>Testing  on cloud-based platforms, like the Perfecto Mobile Handset Cloud which  helps QA teams to test their widgets, applications and mobile content on  variety of handsets.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/10/why-mobile-application-testing-is-challenging/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>when &amp; why rule engines?</title>
		<link>http://xebee.xebia.in/2011/10/09/when-why-rule-engines/</link>
		<comments>http://xebee.xebia.in/2011/10/09/when-why-rule-engines/#comments</comments>
		<pubDate>Sat, 08 Oct 2011 22:11:43 +0000</pubDate>
		<dc:creator>Nikhil</dc:creator>
				<category><![CDATA[BRMS]]></category>
		<category><![CDATA[Rule Engine]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9885</guid>
		<description><![CDATA[var _gaq = _gaq &#124;&#124; []; _gaq.push(['_setAccount', 'UA-30218999-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); For many complex applications, business policies keep on changing very frequently and mostly they are too [...]]]></description>
			<content:encoded><![CDATA[<p><head><br />
<script type="text/javascript"></p>
<p>  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-30218999-1']);
  _gaq.push(['_trackPageview']);</p>
<p>  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();</p>
<p></script><br />
</head><br />
<span style="line-height: normal;">For many complex applications, business policies keep on changing very frequently and mostly they are too complex to be modified in the source code.</span></p>
<p style="line-height: normal;" class="MsoNormal"><span><span style="background: white;">Such application includes applications in domains such as insurance (for example, insurance rating), financial services (loans, fraud detection, claims routing and management), government (application process and tax calculations), telecom customer care and billing (promotions for long distance calls that needs to be integrated into the billing system), ecommerce (personalizing the user's experience)</span></span><span><span style="mso-bidi-font-family: Arial; color: black; background: white;"> </span></span></p>
<p style="line-height: normal;" class="MsoNormal"><span><span style="background: white;">If your business logic code includes thousands of if-else statements (that too keep changing</span></span><span><span style="font-size: 10.0pt; background: white;"> </span><span style="background: white;">frequently), you should consider using a</span></span><span><span style="font-size: 10.0pt; background: white;"> </span><strong><span style="background: white;">Rule Engine</span></strong></span><span><span style="font-size: 10.0pt; background: white;"> </span><span style="background: white;">else not</span></span><span><span style="font-size: 10.0pt; background: white;">.</span></span></p>
<p><span id="more-9885"></span></p>
<p style="line-height: normal;" class="MsoNormal"><span><span style="mso-bidi-font-family: Arial; color: black; background: white;">Few challenges in such applications:</span></span></p>
<p style="line-height: normal;" class="MsoNormal"><span><span><span>1.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>The process of automating business policies, procedures, and business logic is simply too dynamic to manage effectively as application source code.</span></p>
<p><strong>Solution</strong>: <span> </span>A rule engine enables to accommodate the inevitable business/decision logic <span> </span>that are consequences of the market changes that no one can predict or plan for during design.</p>
<p><span style="line-height: normal;"><span><span><span>2.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>Having business rules mixed with rest of our code is not a good approach. Doing so we end up having a tight coupling of the application-code with the business policies.</span></span></p>
<p><strong>Solution: </strong>The rule engine applies rules and actions as defined by end users without affecting how the application runs. The application is built to deal with the rules, which are designed separately.</p>
<p><span style="line-height: normal;"><span><span><span>3.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>Maintaining complex Boolean logic becomes a difficult task. Even a simple change to one line of code can cost an organization thousands of dollars.</span></span></p>
<p><strong>Solution</strong>:<span> </span>Using business rules can help you develop <strong>more cost effective</strong> and <strong>more agile</strong> applications.</p>
<p><span style="line-height: normal;"><span><span><span>4.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>Sometimes when there are so many rules, developers find it difficult to decide the order of multiple if- else statements.</span></span></p>
<p><strong>Solution: </strong>Rule Engines have better mechanism for the deciding execution order <span> </span>of the rules through <strong>Salience</strong>(priority ordering).</p>
<p><span style="line-height: normal;"><span><span><span>5.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>Every time when a developer adds a new if-else rule to the application, whole application requires re-building, compiling and deploying.</span></span></p>
<p style="text-indent: -.25in; line-height: normal; mso-list: l0 level1 lfo1;" class="MsoListParagraphCxSpMiddle"><span> <strong><br />
Solution</strong>: A rule engine evaluates and executes rules, which are expressed as if-then statements. The power of business rules lies in their ability both to separate knowledge from its implementation logic and to be changed without changing source code.</span></p>
<p style="text-indent: -.25in; line-height: normal; mso-list: l0 level1 lfo1;" class="MsoListParagraphCxSpMiddle"><span><span><span>6.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>Developers should least bother about the policy changes; instead this task should be delegated to some business experts (business analysts).</span></p>
<p><strong>Solution</strong>: As somebody who has knowledge of business rules, you'll be able to feed the Rule Engine with what you know. The tool that is used to do this is known as the <strong>Business Rules Management System.<br />
</strong></p>
<p><strong><span style="font-weight: normal; line-height: normal;"><span><span><span>7.<span style="font: 7.0pt &quot;Times New Roman&quot;;"> </span></span></span></span><span>E</span>ven for a small change in business logic developer has to recode.</span></strong></p>
<p><strong>Solution:</strong> We should rather look for some alternatives where business related changes can be done by non-technical business experts.In rule engine based applications we can achieve this just by minor changes in rules which even a business person can do very easily</p>
<p>References: http://java.sun.com/developer/technicalArticles/J2SE/JavaRule.html</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/09/when-why-rule-engines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Enterprise Application Development</title>
		<link>http://xebee.xebia.in/2011/10/06/android-enterprise-application-development-2/</link>
		<comments>http://xebee.xebia.in/2011/10/06/android-enterprise-application-development-2/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 15:44:53 +0000</pubDate>
		<dc:creator>Paramvir Singh</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[android development]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9872</guid>
		<description><![CDATA[For past two years, Android has evolved from an immature mobile OS to a popular choice for users as well as device manufacturers.  Google is continuously updating Android and adding features to make it more and more powerful and competent with other mobile OS mainly iPhone and Blackberry. One major thing which Android was lacking from its [...]]]></description>
			<content:encoded><![CDATA[<p>For past two years, Android has evolved from an immature mobile OS to a popular choice for users as well as device manufacturers.  Google is continuously updating Android and adding features to make it more and more powerful and competent with other mobile OS mainly iPhone and Blackberry.</p>
<p>One major thing which Android was lacking from its competitors was: Enterprise solutions. Now it’s no more a weakness for Android.<br />
<span id="more-9872"></span><br />
<strong><em>What are Enterprise applications:</em></strong> Enterprise applications enable an organization's employees to have access to important organization information/data through mobile applications anywhere, anytime. On the same time, organizations can enforce security policies on every device to control the communication, restrict the flow of data and protect the device from loss or theft.</p>
<p><strong><em>Why they are important:</em></strong> Mobile phones and tablet computers have had a significant impact on the way people think, communicate or work. Organizations are making enterprise applications for mobile phones to improve productivity and communication. "Anywhere and anytime access to information" can be a powerful tool for organization to enhance productivity and reduce cost.</p>
<p><strong><em>How other mobile platforms do it: </em></strong>In Blackberry, enterprise solutions are provided by Blackberry enterprise server setup directly. In iPhone, enterprise applications are supported by Apple to some extent. Organization can develop and distribute in-house iPhone applications. For developing and testing these applications, Apple also provides code level technical support with a fee of US $299 per year.</p>
<p><strong><em>How Android is doing it :</em></strong></p>
<p>On the release of Android OS version 2.2(froyo), Google added new API called “Android Device Administration”. By using this API, developers can create "security aware" enterprise applications through which an organization can enforce its own “settings” on their employees’ devices. These applications will be loaded with following features:</p>
<p><strong><em>Data Sharing: </em></strong><em>Users can have access to sensitive system information and organization data.</em></p>
<p><strong><em>Security:</em></strong></p>
<p><strong><em>When organizations allow sensitive data to be accessed remotely, one thing which is most important is security. Android device administrator can enforce security policies that can be either hard-coded into the app, or the application can dynamically fetch policies from a third-party server.</em></strong></p>
<ol>
<li><strong>Password policies</strong>:       Administrator can enforce a password policy. The password policy can      be set using terms like minimum password length, alphanumeric password,      minimum letters required, minimum lowercase letters, password expiration      timeout, maximum inactivity time lock and other various conditions.</li>
<li><strong>Remote lock: </strong>The      device can be immediately locked remotely by the administrator      if required in case of theft or loss.</li>
<li><strong>Encryption of data:</strong> Android      apps can use SSL tunnels through which data can be transported. However,      the data stored on the device (phone memory and SD) is up to the      applications. Prior to honeycomb (Android 3.0) there is no support for      turning on encryption on the device.</li>
</ol>
<p>If a user fails to comply with the policies (for example, if a user sets a password that violates the guidelines), it is up to the application to decide how to handle this. However, typically this will result in the user not being able to sync data.</p>
<p>Consider a use case where a device attempts to connect to a server (which belongs to an enterprise) that requires policies which are not supported in the Device Administration API, the connection will not be allowed.</p>
<p><strong><em>Device control /Device management:</em></strong></p>
<p><strong><em>Remote wipe: Facility for controlling administration to remotely wipe the device (to restore factory settings) in case the device is lost or stolen.</em></strong></p>
<ol>
<li><strong>Two way benefits</strong>:      System admin can implement the security policies and the device user can      have access to the sensitive system and data and may be able to sync data.</li>
<li><strong>Provisioning: mass deployment of      application: </strong>Though  Android does not      have an automated provisioning solution, a system admin can distribute the      application by following ways:</li>
</ol>
<ul>
<li>Uploading the application in Android Market.</li>
<li>Enabling non-market installation.</li>
<li>Distributing the application through email or website.</li>
</ul>
<p>3<strong>. Wipe the device remotely: </strong>The administrator can wipe the device data remotely and restore the factory settings.</p>
<p><strong><em>To uninstall an existing device admin application, users need to first unregister the application as an administrator</em></strong>.</p>
<p>Developers can create robust enterprise application using the Device Administration API. I am working on a small demo application using this API, will post code snippets in next blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/06/android-enterprise-application-development-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Orchestrating JBoss ESB Services from Intalio business processes (Part-2)</title>
		<link>http://xebee.xebia.in/2011/10/06/orchestrating-jboss-esb-services-from-intalio-business-processes-part-2/</link>
		<comments>http://xebee.xebia.in/2011/10/06/orchestrating-jboss-esb-services-from-intalio-business-processes-part-2/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 19:12:47 +0000</pubDate>
		<dc:creator>Amit Sharma</dc:creator>
				<category><![CDATA[business process]]></category>
		<category><![CDATA[e-Commerce]]></category>
		<category><![CDATA[EA Patterns]]></category>
		<category><![CDATA[Enterprise service bus]]></category>
		<category><![CDATA[Intalio]]></category>
		<category><![CDATA[Java2WSDL]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[JBoss ESB]]></category>
		<category><![CDATA[jboss tools]]></category>
		<category><![CDATA[Restful]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9858</guid>
		<description><![CDATA[In this video series, we are going to learn how to orchestrate jboss services from within Intalio BPM processes. In the part 1  http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/ we have created a JBoss ESB service and published it as a web service. This part will focus more on the Intalio BPM and will show you how to call the [...]]]></description>
			<content:encoded><![CDATA[<p>In this video series, we are going to learn how to orchestrate jboss services from within Intalio BPM processes.</p>
<p>In the part 1  <a href="http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/">http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/</a> we have created a JBoss ESB service and published it as a web service. This part will focus more on the Intalio BPM and will show you how to call the JBoss ESB service from within the process.</p>
<div><span id="more-9858"></span></div>
<p><object width="640" height="480"><param name="movie" value="http://www.youtube.com/v/3lB6F3EhHOU?version=3&amp;hl=en_US&amp;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/3lB6F3EhHOU?version=3&amp;hl=en_US&amp;hd=1" type="application/x-shockwave-flash" width="640" height="480" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/06/orchestrating-jboss-esb-services-from-intalio-business-processes-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why Agile is Awesomeeee..!!?? A Fresher&#8217;s Perspective</title>
		<link>http://xebee.xebia.in/2011/10/03/why-agile-is-awesomeeee-a-freshers-perspective/</link>
		<comments>http://xebee.xebia.in/2011/10/03/why-agile-is-awesomeeee-a-freshers-perspective/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 10:32:01 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Pair Programming]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9840</guid>
		<description><![CDATA[Requirements -&#62; Design -&#62; Implementation -&#62; Integration -&#62; Testing -&#62; Maintenance , I have been forced to learn this for years. Even though I always thought how can some one design an application so big in one single go. But the educational structure that prevails in India don't let you think differently. Lets not change the subject [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Requirements -&gt; Design -&gt; Implementation -&gt; Integration -&gt; Testing -&gt; Maintenance</strong> , I have been forced to learn this for years. Even though I always thought how can some one design an application so big in one single go. But the educational structure that prevails in India don't let you think differently. Lets not change the subject here and instead of talking about India's educational structure lets talk more about the awesomeness of <strong>Agile</strong>.<span id="more-9840"></span></p>
<p>Before joining an <strong>Agile</strong> firm like "<strong><a title="Xebia India" href="http://xebia.in" target="_blank">Xebia</a></strong>" I was into a mindset that "Architectural or any design level task is supposed to be performed by technology heads or team leads and we are the mere workers who will simply code the designed architecture". Well the next line may seem a bit over-exagerated. But literally the previously stated thought of mine was broken into pieces when on the second day after joining the project(as a fresher) I was asked to discuss with team the design of the upcoming module." Thats the beauty of Agile it makes you feel that you are not a fresher but a "<strong>team member</strong>".</p>
<p>I always thought after joining as a fresher "a Team lead/Project Manager or someone superior to me will be assigning me tasks and I will be completing those tasks without questioning them before the so-called deadline". Again I was bowled at my second pre-planning and planning meeting as I was asked, "Vijay which stories do you think you can pick in this sprint". It was something that I never expected I literally asked, aren't you guys supposed to tell me what to do. That day I learned, in <strong>Agile </strong>environment you yourself estimate your work and pick your work on your own. Well that may seem a bit scary initially but on the flip side it makes you more responsible and confident.</p>
<p>One of the toughest thing when you join a project in between and that too as a fresher, is surely, getting along with the code base but <strong>Agile</strong> have a solution for every damn thing. Pair-programming in action. You pair-program with fellow programmers and you get to know every little thing about the codebase. One day you are with 0% knowledge of the technology stack and with in a week the knowledge rise to easily around 60%.</p>
<p>The best thing about pair programming is when you pair-program with your team members the team dynamics and communication increase. In a day you turn from a stranger to co-worker and with in a week a "<strong>team member</strong>". So Agile comes out victorious again.</p>
<p>Thank you for reading.</p>
<p><strong>PS:</strong></p>
<div id="attachment_33" class="wp-caption aligncenter" style="width: 250px"><a href="http://vijayrawatsan.files.wordpress.com/2011/09/kungfu.jpg"><img class="size-medium wp-image-33 " title="kungfu" src="http://vijayrawatsan.files.wordpress.com/2011/09/kungfu.jpg?w=300" alt="" width="240" height="135" /></a><p class="wp-caption-text">There is no charge for awesomeness...</p></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/10/03/why-agile-is-awesomeeee-a-freshers-perspective/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Packaging a Salesforce Application : Things to keep in mind</title>
		<link>http://xebee.xebia.in/2011/09/30/packaging-a-salesforce-application-things-to-keep-in-mind/</link>
		<comments>http://xebee.xebia.in/2011/09/30/packaging-a-salesforce-application-things-to-keep-in-mind/#comments</comments>
		<pubDate>Fri, 30 Sep 2011 03:38:46 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[SalesForce]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9801</guid>
		<description><![CDATA[While working on Salesforce applications, we came to know that 'Packaging' is a powerful ready-made tool which enables you to distribute your application including all the components to the Salesforce user. There are some other facilities also, like include your company logo, create trials/help for advertisements and publishing it via AppExchange. Before we create any [...]]]></description>
			<content:encoded><![CDATA[<p>While working on <strong>Salesforce </strong>applications, we came to know that '<strong><span style="color: #000080;">Packaging</span></strong>' is a powerful ready-made tool which enables you to distribute your application including all the components to the Salesforce user.</p>
<p>There are some other facilities also, like include your company logo, create trials/help for advertisements and publishing it via AppExchange.</p>
<p>Before we create any package, we already decide upon whether to create a <strong>managed </strong>or an <strong>unmanaged </strong>package ( the two ways of packaging available) . The former is used when we desire them to be upgraded in the  installer's organization.</p>
<p><span id="more-9801"></span></p>
<p><strong><span style="color: #0000ff;">Managed  packages</span></strong> allow the upgrade process by locking the code and the components at the target account where your application is being installed. Every time you create a managed package, you have a choice to upgrade the previous version or creating a new version altogether.</p>
<p><strong><span style="color: #0000ff;">Unmanaged  packages</span></strong> on the other hand do not include locked components and can not be upgraded.<strong> All they do is every time creating a new installation with a new version number and you need to uninstall the previous version on the target account to run the new set-up.</strong></p>
<p>You can find the detailed differences between the two method at Salesforce documentation.  e.g. <a href="http://wiki.developerforce.com/index.php/How_to_Create_and_Register_a_Package">http://wiki.developerforce.com/index.php/How_to_Create_and_Register_a_Package</a></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.<a rel="attachment wp-att-9827" href="http://xebee.xebia.in/2011/09/30/packaging-a-salesforce-application-things-to-keep-in-mind/packaging-2/"><img class="alignleft size-full wp-image-9827" title="packaging" src="http://xebee.xebia.in/wp-content/uploads/2011/09/packaging1.png" alt="" width="643" height="256" /></a></span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p>.</p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><strong>Based on my experience so far with the packaging stuff ,  I would like to share the following things with you which can help one in avoiding going through this process all over again for minor changes.</strong></p>
<ul>
<li>Something you can't start packaging without : Keep/Bring the test case coverage up to at least 75%. Salesforce will perform this check while uploading your package on the cloud.</li>
<li>Run all tests before you start the packaging process. None of them should fail, or you will get this error later.</li>
<li>Avoid writing the test cases which are specific to the environment/particular developer account. Those test cases might fail while you deploy the application on production accounts.</li>
<li>It could be wiser in the initial stages of the release process or testing, to start with 'unmanaged' package till you get to a stage where all your components/layouts/static resources are finalized. It will provide the room to view your code and edit the layout/custom components as otherwise they would be locked and stay in-editable for rest of their lives.</li>
<li>Check the name of organization from<span style="color: #0000ff;"> <em>Setup-&gt; Organization setup -&gt; Company profile -&gt; Company Information</em></span> as this will be the name which appears as the publisher of the application, on the target account where your application is installed.</li>
<li>Confirm and remove any custom tab/layout/resource that you have created but not intended to be shipped in the package from the list before clicking the '<strong>upload</strong>' button.</li>
<li>It would be nice to create an 'App' which can also include your company logo(<em>in case you forgot to choose one while creating the package initially</em>) and make it available in the package so that the account which installs your application can simply navigate to your custom layout with a single click, by choosing it from the app selection drop-down available on top right corner in the account.</li>
</ul>
<p>I shall keep updating this list as and when I encounter things that made me re-package my application <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .. Till then, happy packaging !!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/30/packaging-a-salesforce-application-things-to-keep-in-mind/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why should I use JBoss AS7</title>
		<link>http://xebee.xebia.in/2011/09/29/why-should-i-use-jboss-as7/</link>
		<comments>http://xebee.xebia.in/2011/09/29/why-should-i-use-jboss-as7/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 07:20:11 +0000</pubDate>
		<dc:creator>Anirudh Bhatnagar</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[JBoss AS7]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9755</guid>
		<description><![CDATA[In the last few months we have seen some aggressive marketing of JBoss AS 7 by RedHat.  Red Hat has been praising its perfromance, parallelism, jee6 compatibility and other deployment issues. So I decided to explore the new application server and verify the truth behind them. After downloading the app server I configured it with [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">In the last few months we have seen some aggressive marketing of JBoss AS 7 by RedHat.  Red Hat has been praising its perfromance, parallelism, jee6 compatibility and other deployment issues. So I decided to explore the new application server and verify the truth behind them.</p>
<p style="text-align: justify;">After <a href="http://www.jboss.org/jbossas/downloads/">downloading </a>the app server I configured it with eclipse using <a href="http://www.eclipse.org/m2e/">M2Eclipse </a>plugin, the details of how to configure it and deploy the quickstarts is given <a href="https://docs.jboss.org/author/display/AS7/Getting+Started+Developing+Applications+Guide">here</a>. The <a href="http://www.jboss.org/as7.html">homePage </a>itself looks impressive to begin with and documentation is very good (for a change).</p>
<p style="text-align: justify;">Below is my experience and analysis over the claims of the new JBoss AS7.<br />
<span id="more-9755"></span><br />
<strong>1. Blazingly fast -</strong> Well for the standalone part when there are no deployments it did start in less than 2 seconds. But as and when I started loading bulky applications it started taking little time. But yes, thanks to the new Module service Container, time taken was still less than 4 seconds.</p>
<p style="text-align: justify;">Let’s ponder on the reason behind this drastic performance change from its predecessors-</p>
<p style="text-align: justify;">One of the main and perhaps most grueling tasks for an application server is managing services. The services are not isolated and they are interdependent. When an application server starts or deploys a service, it has to make sure that it starts all the services in the correct order. And if some service is stopped then all services, which depend on this service, must stop in the reverse order.</p>
<p style="text-align: justify;">This all looks very chaotic when there are multiple threads doing the task. So the developers of AS7 decided to make a new service container from scratch: JBoss Modular Service Container.<br />
Instead of starting the services in a hierarchical manner now they get started concurrently and only the critical ones are started first. This seems to have worked for them.</p>
<p style="text-align: justify;"><strong>2. No more classNotFound / NoClassDefFound errors</strong> :I have yet to encounter these problems in the new app server. This app server seems to do the class-loading in a sane manner, and hence we see “Jar-Hell” no more. <a href="https://docs.jboss.org/author/display/MODULES/Home">JBoss Modules</a> achieves the goal of modularity and concurrent class loading by segmenting classes into proper modules, the concept that is very similar to OSGI.</p>
<p style="text-align: justify;"><strong>3. Hot, parallel deployment -</strong> I, then,  deployed bulkier applications – Added EJB3, JPA, JTA, hibernate . But to my surprise it was indeed fast. Not only the start-up but the deployments also happened in less than 2 seconds! So far so good.</p>
<p style="text-align: justify;"><strong>4. Fully Compatible JEE6 profile-</strong> I tried some of the features of JEE6 like CDI, JPA, EJB3, JTA, Hibernate,Servlet 3 API and not faced any issue. It certainly looks fully Java EE 6 compatible server. So for Java EE 6 components it’s a Thumbs Up!  Only other app server I can think of is Glass Fish which is fully JEE6 compatible.</p>
<p style="text-align: justify;"><strong>5. Automatic dependency resolution  -</strong> One of the best things I liked about Jboss AS7 was implicit and automatic dependency resolution. For example, If you are using CDI and have a beans.xml in your module, then the cdi jar would be automatically be there you need not define it in neither in your POM or in any other dependency.xml.</p>
<p style="text-align: justify;"><strong>6. New Improved deployment scanner-</strong> Another change that I observed was the deployment scanner does not work the same as the old one.<br />
If you have an exploded directory you need to suffix .dodeploy with it. But still if you are deploying WARs/EARs and you do not want to add the extra marker you can change it in the standalone.xml by changing the "auto-deploy" attributes on the deployment-scanner element in the standalone.xml configuration file.</p>
<p style="text-align: justify;">More details can be found in the deployments folder README.</p>
<p style="text-align: justify;"><strong>7. Admin console GUI –</strong> This still looks very basic although better than its previous counterparts.<br />
By default if you do http://localhost:9990/console you will land up on a very basic page which just shows the deployments, data sources, logging etc.</p>
<p style="text-align: justify;">Go to /standalone/configuration/mgmt-users.properties and you will see all the story about how to configure the port , how to put a security realm, these changes go in standalone.xml</p>
<p style="text-align: justify;">Managing the Jboss Server :I still think the previous JMX-Console had a lot of power to see and manage all the Mbeans and I am still trying to find how I can do things now in the new console.</p>
<p style="text-align: justify;"><strong>8. Integration testing -</strong> One can use <a href="http://www.jboss.org/arquillian/about.html">Arquillian </a>for executing the test cases inside the real runtime environment. It abstracts away all container lifecycle and deployment from the test cases business logic. This can be a very convenient tool for TDD.</p>
<p style="text-align: justify;"><strong>9. Support for Java 7 –</strong> Yes AS7 is fully compatible if you use JDK 7 to make your application.</p>
<p style="text-align: justify;">Well So far it looks great, less startup time, fast deployments, no”Jar-Hell”, implicit dependency resolution in a fully compatible JEE6 Web Profile server. Better and smarter than its predecessors with fantastic supporting documentation.  The next task would be to to move my application from AS5 to AS7.  Let’s see how easier it would be to migrate to this new avatar. Keep looking at this place for more details in time to come.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/29/why-should-i-use-jboss-as7/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Orchestrating JBoss Services from Intalio business processes (Part-1)</title>
		<link>http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/</link>
		<comments>http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 11:45:26 +0000</pubDate>
		<dc:creator>Amit Sharma</dc:creator>
				<category><![CDATA[BPM]]></category>
		<category><![CDATA[business process]]></category>
		<category><![CDATA[e-Commerce]]></category>
		<category><![CDATA[Enterprise service bus]]></category>
		<category><![CDATA[Intalio]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[JBoss ESB]]></category>
		<category><![CDATA[jboss tools]]></category>
		<category><![CDATA[Restful]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[User Centered Analysis Process]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9766</guid>
		<description><![CDATA[In this video series, we are going to learn how to orchestrate jboss services from within Intalio BPM processes. The video explains we start with first creating our service in JBoss ESB and then publish this as a web service. We will also show you how you can test such a service using Soap UI.In [...]]]></description>
			<content:encoded><![CDATA[<p>In this video series, we are going to learn how to orchestrate jboss services from within Intalio BPM processes.</p>
<p>The video explains we start with first creating our service in JBoss ESB and then publish this as a web service. We will also show you how you can test such a service using Soap UI.In the next video, we will show you how you can create a business process inside Intalio business Process Modeler and call the service created in Part-1 from within that process.</p>
<div><span id="more-9766"></span></div>
<p><object width="640" height="480"><param name="movie" value="http://www.youtube.com/v/WExEiedzpTc?version=3&amp;hl=en_US&amp;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/WExEiedzpTc?version=3&amp;hl=en_US&amp;hd=1" type="application/x-shockwave-flash" width="640" height="480" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/26/orchestrating-jboss-services-from-intalio-business-processes-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling DBRefs in MongoDB with Spring Data</title>
		<link>http://xebee.xebia.in/2011/09/20/handling-dbrefs-in-mongodb-with-spring-data/</link>
		<comments>http://xebee.xebia.in/2011/09/20/handling-dbrefs-in-mongodb-with-spring-data/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 10:52:12 +0000</pubDate>
		<dc:creator>Vijay Rawat</dc:creator>
				<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Data]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9727</guid>
		<description><![CDATA[Recently I was watching a presentation titled Why I Chose MongoDB for guardian.co.uk by Mat Wall. I thought of giving a look to mongoDB. Those who dont know what is mongoDB, well, its a document oriented database with some advantages over other relational databases. For more info you can have a look at MongoDb website. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was watching a presentation titled <a href="http://www.infoq.com/presentations/Why-I-Chose-MongoDB-for-Guardian" target="_blank">Why I Chose MongoDB for guardian.co.uk</a> by Mat Wall. I thought of giving a look to mongoDB. Those who dont know what is mongoDB, well, its a document oriented database with some advantages over other relational databases. For more info you can have a look at <a title="MongoDB" href="http://www.mongodb.org/" target="_blank">MongoDb</a> website. While I was researching on how to access mongoDB easily and more efficiently I found out <a title="Spring Data" href="http://www.springsource.org/spring-data" target="_blank">Spring Data</a>. I also found some useful blogs explaining integration of both. But I was still not able to find a concrete working example which explains how to handle class relationship with MongoDB(DBRefs). So I thought of writing a complete working <strong>Spring MVC + Spring Data + MongoDB application handling DBRefs.<span id="more-9727"></span></strong></p>
<p>I have created a simple example with three domain classes User, Post and Comment. User can create Post and Post can have Comment(keeping it as simple as that). Below are the domain classes(of the example),</p>
<pre class="brush: java; title: ; notranslate">
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class User {
	@Id
	private String id;
	private String userName;
	private String password;

        //getters &amp; setters
}
</pre>
<pre class="brush: java; title: ; notranslate">
import org.springframework.data.annotation.Id;

@org.springframework.data.mongodb.core.mapping.Document
public class Post {

	@Id
	private String id;
	private String subject;
	private String content;
	@org.springframework.data.mongodb.core.mapping.DBRef
	private User user;

        //getters and setters
}
</pre>
<pre class="brush: java; title: ; notranslate">
import org.springframework.data.annotation.Id;

@org.springframework.data.mongodb.core.mapping.Document
public class Comment {

	@Id
	private String id;
	private String content;
	@org.springframework.data.mongodb.core.mapping.DBRef
	private User user;
	@org.springframework.data.mongodb.core.mapping.DBRef
	private Post post;

        //getters and setters
}
</pre>
<p>You can see how the classes are linked with each other using <strong>@DBRef</strong> annotation. Now in order to access MongoDB and we need to create some DAO classes. Well thats a piece of cake with Spring Data's <strong>MongoRepository</strong>. Just extend MongoRepository&lt;T, X&gt; with you DAO where T is class name and X is class used for creating the key.</p>
<pre class="brush: java; title: ; notranslate">
import in.xebia.mongodb.blog.domain.User;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface UserDao extends org.springframework.data.mongodb.repository.MongoRepository&lt;User, String&gt; {

}
</pre>
<pre class="brush: java; title: ; notranslate">
import in.xebia.mongodb.blog.domain.Post;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface PostDao extends org.springframework.data.mongodb.repository.MongoRepository&lt;Post, String&gt; {

}
</pre>
<pre class="brush: java; title: ; notranslate">
import in.xebia.mongodb.blog.domain.Comment;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface CommentDao extends org.springframework.data.mongodb.repository.MongoRepository&lt;Comment, String&gt;{

}
</pre>
<p>MongoRepository provides basic CRUD operations like findOne(),findALL(),save(),delete(), etc. but in order to handle DBRefs we need to make custom use of <strong>MongoTemplate</strong> as shown below in the CommentService class:</p>
<pre class="brush: java; title: ; notranslate">
import static org.springframework.data.mongodb.core.query.Criteria.where;
import in.xebia.mongodb.blog.api.CommentDao;
import in.xebia.mongodb.blog.api.CommentService;
import in.xebia.mongodb.blog.domain.Comment;
import in.xebia.mongodb.blog.domain.Post;
import in.xebia.mongodb.blog.domain.User;
import java.util.List;
import java.util.UUID;
import javax.annotation.Resource;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service(&quot;commentService&quot;)
@Transactional
public class CommentServiceImpl implements CommentService {
	@Resource
	private CommentDao commentDao;
	@Resource
	private MongoTemplate mongoTemplate;
	public List&lt;Comment&gt; getAll() {
		List&lt;Comment&gt; comments = commentDao.findAll();
		return comments;
	}
	public Comment get(String id) {
		Comment comment = commentDao.findOne(id);
		return comment;
	}
	public Boolean add(Comment comment) {
		try {
			if(comment.getId()==null || comment.getId().length()==0)
				comment.setId(UUID.randomUUID().toString());
		   commentDao.save(comment);
		   return true;
		  } catch (Exception e) {
			  e.printStackTrace();
			  return false;
		  }
	}
	public List&lt;Comment&gt; get(Post post) {
		Query query = new Query(where(&quot;post.$id&quot;).is(post.getId()));
		List&lt;Comment&gt; comments = mongoTemplate.find(query, Comment.class);
		return comments;
	}
	public List&lt;Comment&gt; get(User user) {
		Query query = new Query(where(&quot;user.$id&quot;).is(user.getId()));
		List&lt;Comment&gt; comments = mongoTemplate.find(query, Comment.class);
		return comments;
	}

}
</pre>
<p>Last but not the least here is the config file for mongo:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xmlns:p=&quot;http://www.springframework.org/schema/p&quot;
    xmlns:mongo=&quot;http://www.springframework.org/schema/data/mongo&quot;
 xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/data/mongo

http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd&quot;&gt;

&lt;mongo:repositories base-package=&quot;in.xebia.mongodb.blog.api&quot; /&gt;

&lt;mongo:mongo host=&quot;localhost&quot; port=&quot;27017&quot;/&gt;
&lt;!--mongoTemplate is required as it is used by mongorepository --&gt;
&lt;bean id=&quot;mongoTemplate&quot; class=&quot;org.springframework.data.mongodb.core.MongoTemplate&quot;&gt;
&lt;constructor-arg ref=&quot;mongo&quot;/&gt;
&lt;constructor-arg name=&quot;databaseName&quot; value=&quot;test&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;populatorService&quot; class=&quot;in.xebia.mongodb.blog.impl.PopulatorService&quot; init-method=&quot;init&quot;/&gt;
&lt;/beans&gt;
</pre>
<p>Thats all I have for this blog you can download the complete RESTful web-app from the following git repository: <a title="HandlingDBRefsInMongoDBWithSpringData" href="https://github.com/vijayrawatsan/SpringDataWithMongoDB" target="_blank">HandlingDBRefsInMongoDBWithSpringData</a>. In order to use the web app you will require some tools like soapUI or Poster(mozilla addon) as there is no UI for application. Just publish the app and start making json requests(see example in <a href="https://github.com/vijayrawatsan/SpringDataWithMongoDB/blob/master/readme.txt">readme.txt</a>)</p>
<p>&nbsp;</p>
<p>Have a nice day.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/20/handling-dbrefs-in-mongodb-with-spring-data/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Grand Central Dispatch (GCD) vs NSThread</title>
		<link>http://xebee.xebia.in/2011/09/19/grand-central-dispatch-gcd-vs-nsthread/</link>
		<comments>http://xebee.xebia.in/2011/09/19/grand-central-dispatch-gcd-vs-nsthread/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 05:28:33 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[GCD]]></category>
		<category><![CDATA[iOS4]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[NSOperationQueue]]></category>
		<category><![CDATA[NSThread]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9664</guid>
		<description><![CDATA[In this post I will talk about Grand central dispatch, how it is better than using NSThread. But before that I would like to see how and where threads are used. There are n number of distinct reasons behind using threads based on the structure and complexity of the app, but the prime reason behind [...]]]></description>
			<content:encoded><![CDATA[<p>In this post I will talk about <a href="http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html">Grand central dispatch</a>, how it is better than using <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSThread_Class/Reference/Reference.html">NSThread</a>. But before that I would like to see how and where threads are used. There are n number of distinct reasons behind using threads based on the structure and complexity of the app, but the prime reason behind using threads is <strong>asynchronously working on a task</strong> and then (if required) notifying the main thread. The whole idea behind doing so is that we do not want to block the main thread while we are executing a task. So lets see how it is implemented. Here is the small code snippet where we use NSThread to start a task in a new thread, do some time consuming task and notify to the main thread when we are done so that it can update the UI (The main thread is/should be used to update the UI).<br />
<span id="more-9664"></span></p>
<pre class="brush: jscript; title: ; notranslate">
-(void)doSomeTask{
      [NSThread detachNewThreadSelector:@selector(handlerForTask) toTarget:self
                       withObject:nil];
}

-(void)handlerForTask{
       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       [self performSelectorOnMainThread:@selector(notifyMainThread) withObject:nil
              waitUntilDone:NO];
       [pool release];
}
</pre>
<p>The same implementation can be done using GCD as given below.</p>
<pre class="brush: jscript; title: ; notranslate">
-(void)doSomeTask{
         dispatch_queue_t queue = dispatch_queue_create(&quot;com.xebia.gcd&quot;, NULL);
         dispatch_queue_t mainQueue = dispatch_get_main_queue();
         dispatch_async(queue, ^{
                             [self processTask];
                             dispatch_async(mainQueue, ^{ [self notifyMainThread]; });
                    });
      dispatch_release(queue);
}</pre>
<p>See the obvious takeaway from the code above is that it is cleaner and easier to realize. In the threads we have to manage autorelease pool so that all the memory allocated is released properly. Also if we wanted to <strong>fire multiple selectors with multiple arguments</strong>, we could have easily done that using GCD. Here is the code snippet. </p>
<pre class="brush: jscript; title: ; notranslate">
-(void)doSomeTask{
         NSDictionary *info ;
         dispatch_queue_t queue = dispatch_queue_create(&quot;com.xebia.gcd&quot;, NULL);
         dispatch_async(queue, ^{
         // multiple selectors with multiple arguments
                             [self executeFirstTaskWithInfo:info];
                             [self executeSecondTaskWithInfo:info andTaskNumber:2];
                    });
      dispatch_release(queue);
}</pre>
<p>Apart from these here are the other advantages of using GCD instead of threads.</p>
<ul>
<li>The developer has to be careful about his/her strategy for using threads i.e. he/she has to manage problems like <strong>lockings, thread reuse</strong> etc. Where as GCD does all this for you.</li>
<li>Threads are highly memory consuming, whereas in GCD there are more cpu cycles available for executing tasks.</li>
<li><strong>Dispatch queues</strong> available in GCD helps us to schedule tasks more efficiently in GCD.</li>
</ul>
<p>To use GCD you just have to include "dispatch/dispatch.h" and it just works. In the next post I will try to analyze <strong>NSOperation and NSOperationQueue</strong>, which has also started using GCD instead of threads. </p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/19/grand-central-dispatch-gcd-vs-nsthread/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Identifying GIT Merge Conflicts with a Merge Tool</title>
		<link>http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/</link>
		<comments>http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/#comments</comments>
		<pubDate>Sun, 11 Sep 2011 13:06:20 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[GIT]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9599</guid>
		<description><![CDATA[One of the pain points in GIT was resolving merge conflicts. I have highlighted ‘was’ because at the end of this blog you will find your life easy the next time you encounter merge conflicts. Working with GIT in agile development increases the probability of merge conflicts, and the reason behind is straight forward – Parallel [...]]]></description>
			<content:encoded><![CDATA[<p>One of the pain points in GIT <strong>was</strong> resolving merge conflicts. I have highlighted ‘was’ because at the end of this blog you will find your life easy the next time you encounter merge conflicts. Working with GIT in agile development increases the probability of merge conflicts, and the reason behind is straight forward – Parallel Development.  As I mentioned in my earlier <a title="Analysing GIT Branching model with Kanban" href="http://xebee.xebia.in/2011/05/15/analysing-git-branching-model-with-kanban/" target="_blank">blog</a>, there are lot of advantages of using GIT branching model. But one of the pain points I mentioned was resolving merge conflicts. One has to manually open the files and identify conflicts. In this blog, I will share how you can configure and open a 3-way merging tool to identify your merge conflicts. <span id="more-9599"></span></p>
<p>Why a 3-way merging tool? You always have two branches that are involved in merging. But you might want to look at the common ancestor as well. A 3-way merging tool helps you in viewing and comparing the conflicts with your remote ancestor branch (master, for instance). Please download any 3-way merge tool before moving ahead.</p>
<p><strong>Note:</strong> WinMerge is not a 3-way merge tool. I will be using <a href="http://www.sourcegear.com/diffmerge/downloads.php" target="_blank">DiffMerge</a> here.</p>
<p>So the next time you see any merge conflict, please follow the steps below:</p>
<p>Type <strong>git mergetool</strong>. You will see the default merge tool candidates.</p>
<p><img class="alignleft" src="http://xebee.xebia.in/wp-content/uploads/2011/09/mergetool-default-300x57.png" alt="" width="300" height="57" /></p>
<p>You might feel relaxed to see that GIT is offering couple of tools for identifying conflicts. Unfortunately, they all are command-line based tools so we will be adding a visual tool to it, and next time when you write a mergetool command, you will see your own visual tool opened up with the file.</p>
<p>You might get a hint that we need to override the ‘mergetool’ so go ahead and open your .gitconfig file present in C:\Users\{user-name}\ (That’s for Windows 7 by the way). You will find tags like [gui], [user], etc. Add following lines to it:</p>
<pre class="brush: plain; title: ; notranslate">

[merge]

tool = diffmerge

[mergetool &quot;diffmerge&quot;]

cmd = git-merge-diffmerge-wrapper.sh &quot;$PWD/$LOCAL&quot; &quot;$PWD/$REMOTE&quot; &quot;$PWD/$BASE&quot;
</pre>
<p>You can specify the name of the mergetool you are using inside the [mergetool] tag, but make sure it matches the ‘tool’ property of [merge] tag. You can see [mergetool] requires git-merge-diffmerge-wrapper.sh. <a href="http://xebee.xebia.in/wp-content/uploads/2011/09/git-merge-diffmerge-wrapper.txt" target="_blank">Download it</a> and paste it inside {GIT_INSTALLATION_FOLDER}\cmd. Please change the extension of the file to .sh. You should have something like below:</p>
<p><a rel="attachment wp-att-9621" href="http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/mergetool-wrapper-location/"><img class="size-medium wp-image-9621 alignleft" title="mergetool-wrapper-location" src="http://xebee.xebia.in/wp-content/uploads/2011/09/mergetool-wrapper-location-300x65.png" alt="" width="300" height="65" /></a></p>
<p>Also, please add <em>{GIT_INSTALLATION_FOLDER}\cmd</em> in your PATH.</p>
<p>You can enter the path of the executable of the diff tool you wish to use in <em>git-merge-diffmerge-wrapper.sh.</em></p>
<p>And you are done! Go back to your GIT Bash and re-enter <strong>git mergetool</strong>. You will see the name of your diff tool.</p>
<p><a rel="attachment wp-att-9626" href="http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/mergetool-custom-tool/"><img class="size-medium wp-image-9626 alignleft" title="mergetool-custom-tool" src="http://xebee.xebia.in/wp-content/uploads/2011/09/mergetool-custom-tool-300x51.png" alt="" width="300" height="51" /></a></p>
<p>Once you hit ENTER, you can see your diff tool opening the file with three views. I dint get a way to find the branch names involved in the merging so I am referring the title of the views as CURRENT, BRANCH BEING MERGED and ANCESTOR. <strong>CURRENT</strong> – the branch accepting the merge, <strong>BRANCH BEING MERGED</strong> – as the name says and <strong>ANCESTOR</strong> – the remote copy of the file on origin.</p>
<p><a rel="attachment wp-att-9627" href="http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/mergetool-views/"><img class="alignleft size-medium wp-image-9627" title="mergetool-views" src="http://xebee.xebia.in/wp-content/uploads/2011/09/mergetool-views-221x300.png" alt="" width="221" height="300" /></a></p>
<p>If you have more than 1 file with conflicts, then your diff tool will be opened for each file. Once you fix the conflict, you can save the file and close the tool. You can then ADD and COMMIT the files.</p>
<p>Hope you can now indentify merge conflicts easily.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/11/identifying-git-merge-conflicts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing portlets using Spring Portlet MVC and Liferay ServiceBuilder</title>
		<link>http://xebee.xebia.in/2011/09/04/developing-portlets-using-spring-portlet-mvc-and-liferay-servicebuilder/</link>
		<comments>http://xebee.xebia.in/2011/09/04/developing-portlets-using-spring-portlet-mvc-and-liferay-servicebuilder/#comments</comments>
		<pubDate>Sun, 04 Sep 2011 16:56:56 +0000</pubDate>
		<dc:creator>Vikas Gupta</dc:creator>
				<category><![CDATA[Liferay]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9582</guid>
		<description><![CDATA[In my current project, I was exploring options to use a framework to develop portlets in Liferay portal. Finally, we decided to use Sprint Portlet MVC. We were successful in developing data driven portlets using Spring Portlet MVC and Hibernate. However, we were told to use Liferay ServiceBuilder to develop services instead of Spring and [...]]]></description>
			<content:encoded><![CDATA[<p>In my current project, I was exploring options to use a framework to develop portlets in Liferay portal. Finally, we decided to use Sprint Portlet MVC. We were successful in developing data driven portlets using Spring Portlet MVC and Hibernate. However, we were told to use Liferay ServiceBuilder to develop services instead of Spring and Hibernate. In the end, the tech stack to develop portlets was Spring Portlet MVC to develop the portlets and Liferay ServiceBuilder to develop services. This post mentions the problem we faced in integrating Spring Portlet MVC with Liferay ServiceBuilder. <span id="more-9582"></span></p>
<p>Liferay ServiceBuilder generates Spring and Hibernate configuration using ant scripts dynamically and loads them into Portlet Context using PortletContextLoaderListener. Whereas, by default, Spring Portlet MVC loads the Spring Configuration from the file named as portletname-portlet.xml when the portlet is getting deployed. While deploying the portlet, we got the following error</p>
<p><code><br />
21:29:43,468 INFO  [STDOUT] 21:29:43,466 ERROR [PortletHotDeployListener] java.lang.IllegalStateException: Root context attribute is not of type WebApplicationContext: com.liferay.portal.spring.context.PortletApplicationContext@1beaba: display name [Root WebApplicationContext]; startup date [Sun Sep 04 21:29:31 IST 2011]; root of context hierarchy<br />
java.lang.IllegalStateException: Root context attribute is not of type WebApplicationContext: com.liferay.portal.spring.context.PortletApplicationContext@1beaba<br />
: display name [Root WebApplicationContext]; startup date [Sun Sep 04 21:29:31 IST 2011]; root of context hierarchy<br />
        at org.springframework.web.portlet.context.PortletApplicationContextUtils.getWebApplicationContext( PortletApplicationContextUtils.java:79)<br />
        at org.springframework.web.portlet.FrameworkPortlet.initPortletApplicationContext( FrameworkPortlet.java:295)<br />
        at org.springframework.web.portlet.FrameworkPortlet.initPortletBean(FrameworkPortlet.java:269)<br />
        at org.springframework.web.portlet.GenericPortletBean.init(GenericPortletBean.java:116)<br />
</code><br />
It is clear from the error message when spring is initializing the portlet application context, it is expecting that Root ApplicationContext should be of type WebApplicationContext but it is finding root ApplicationContext to be of type PortletApplicationContext, which contains Liferay Services configuration and loaded by the container before Spring Portlet MVC configuration.  A bit more investigation revealed that PortletApplicationContext extended XmlPortletApplicationContext which is not compatible with WebApplicationContext. As I entered into the source code, I found the following line of code were responsible for creating ApplicationContext for Spring Portlet MVC</p>
<p><code><br />
		ApplicationContext parent = PortletApplicationContextUtils.getWebApplicationContext(getPortletContext());<br />
		ApplicationContext pac     = createPortletApplicationContext(parent);<br />
</code></p>
<p>The first line was getting the root applicationContext and second line creates an applicationContext with it's parent as the ServiceBuilder specific applicationcontext. If the execution of the above code was successful, we would have been successful in injecting ServiceBuilder specific beans in Spring Portlet MVC controllers. But, it was not necessary as ServiceBuilder provides utility classes to access ServiceBuilder services. Hence, we did not need to inject ServiceBuilder services inside Spring Portlet MVC controllers. So, we created a custom portlet which extended org.springframework.web.portlet.DispatcherPortlet which further extends org.springframework.web.portlet.FrameworkPortlet and overrided the initPortletApplicationContext changing the above two lines of code to </p>
<p><code><br />
		<strong>ApplicationContext parent = null;</strong><br />
		ApplicationContext pac     = createPortletApplicationContext(parent);<br />
</code></p>
<p>After making the above, our portlet got deployed successfully.</p>
<p>As a final note, the above mentioned problem occurred in Liferay 5.2.3 and when I checked the source code of Liferay 6.0, I found that Liferay's PortletContextLoaderListener, after loading ServiceBuilder applicationcontext, removes the applicationcontext from the portlet context. Further investigation of the source code indicates that the above mentioned problem should not occur in Liferay 6.0.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/09/04/developing-portlets-using-spring-portlet-mvc-and-liferay-servicebuilder/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Create a Custom Component using HTML and Javascript in SalesForce</title>
		<link>http://xebee.xebia.in/2011/08/01/create-a-custom-component-using-html-and-javascript-in-salesforce/</link>
		<comments>http://xebee.xebia.in/2011/08/01/create-a-custom-component-using-html-and-javascript-in-salesforce/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 03:24:06 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[SalesForce]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[numericstepper]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9354</guid>
		<description><![CDATA[In this post, I will describe the creation of a 'Numeric Stepper' custom component using basic HTML tags and JavaScript. This Numeric Stepper will be binded to a salesforce apex component using simple JavaScript. After that you should be able to create any html based custom component in salesforce and tie it to your visualforce [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, I will describe the creation of a 'Numeric Stepper' custom component using basic HTML tags and JavaScript. <strong>This Numeric Stepper will be binded to a salesforce apex component using simple JavaScript. </strong>After that you should be able to create any html based custom component in salesforce and tie it to your visualforce content in the same way.</p>
<p>For this demo, I have used images for up and down arrow keys. You can  download them from <a href="http://xebee.xebia.in/?attachment_id=9398">upImageLink </a>and <a href="http://xebee.xebia.in/?attachment_id=9397">downImageLink </a>respectively and upload as Static resources in <strong>Setup -&gt;  AppSetup -&gt; Develop -&gt;Static Resources.</strong></p>
<p><strong><br />
</strong></p>
<p><strong><span id="more-9354"></span><a rel="attachment wp-att-9798" href="http://xebee.xebia.in/2011/08/01/create-a-custom-component-using-html-and-javascript-in-salesforce/demo1-2/"><img class="size-full wp-image-9798 alignleft" title="demo1" src="http://xebee.xebia.in/wp-content/uploads/2011/08/demo11.png" alt="" width="547" height="239" /></a></strong><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p>.</p>
<p>.</p>
<p><strong> </strong>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>&nbsp;</p>
<p><span style="color: #ffffff;">.</span></p>
<p>&nbsp;</p>
<p><span style="text-decoration: underline;">Now,  lets create our 'Numeric Stepper'.</span></p>
<p><strong>Step 1</strong>: <strong><em>Goto Setup -&gt; AppSetup -&gt; Develop -&gt; Components</em></strong></p>
<p><strong>Step 2: <em>Click New and provide the desired label of your choice. This will be the name of your Custom component</em></strong></p>
<p><strong>Step 3: <em>Add the following code to your Component</em></strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;apex:component id=&quot;compId&quot;&gt;

 &lt;script language=&quot;JavaScript&quot; type=&quot;text/javascript&quot;&gt;

 function processInc(idRef){
   var value = document.getElementById(idRef).value;
   if(value&lt; 1000){
      value++;
   }
   document.getElementById(idRef).value = value;
 }

 function processDec(idRef,v){
   var weight = document.getElementById(idRef).value;
   if(value &gt; 0){
      value--;
   }
   document.getElementById(idRef).value = value;
 }
 &lt;/script&gt;

  &lt;apex:attribute name=&quot;idRef&quot; type=&quot;String&quot; required=&quot;true&quot;
                  description=&quot;inputbox id to which this component will be binded.&quot;/&gt;
      &lt;apex:panelGrid id=&quot;panel1&quot; columns=&quot;2&quot; &gt;
        &lt;apex:panelGroup &gt;
            &lt;img src=&quot;{!$Resource.upDefault}&quot; onClick=&quot;processInc('{!idRef}')&quot;/&gt;
            &lt;img src=&quot;{!$Resource.downHover}&quot; onClick=&quot;processDec('{!idRef}')&quot;/&gt;
         &lt;/apex:panelGroup&gt;
     &lt;/apex:panelGrid&gt;
   &lt;/apex:component&gt;
</pre>
<p>That's it. Your Custom component is ready. Now you need to tie these arrow keys to an input box which are present in a salesforce page and <span style="color: #000000;">whose value will be incremented and decremented as per your clicks on the up/down images. The attribute 'idRef' is a must as while using this component, w</span>e will supply the id of our apex:inputText as '{!$Component.inputFieldId}' . Don't forget to include the parent id's if involved.</p>
<p><span style="text-decoration: underline;"><span style="color: #000000;">Lets see how our salesforce page looks like:</span></span></p>
<pre class="brush: xml; title: ; notranslate">
&lt;apex:page controller=&quot;MyController&quot;&gt;
   &lt;apex:form id=&quot;aForm&quot;&gt;
       &lt;apex:panelGrid columns=&quot;2&quot;&gt;
             &lt;apex:inputText id=&quot;inputField&quot;  value=&quot;{!controllerBindedValue}&quot;/&gt;
             &lt;c:CustomNumericStepper idRef=&quot;{!$Component.aForm.inputField}&quot;/&gt;
       &lt;/apex:panelGrid&gt;
   &lt;/apex:form&gt;
&lt;/apex:page&gt;
</pre>
<p><span style="color: #000000;"><strong><code>Here CustomNumericStepper is our component and like any other custom component, the tag is prefixed by '&lt;c:'.</code> </strong>The attribute value is passed using the name of the attribute specified in the component. The only thing that you need to keep in mind is the correct id reference which will be passed to the </span>JavaScript method<span style="color: #000000;">. Also, at times using the '{!$Component.aForm.inputField}' reference directly in JavaScript doesn't show the updated value instantaneously. Passing it as a parameter is a safer option. You might also need to add the desired styles to your html or apex tags, like hover/margins etc which I have skipped in this post for simplicity. However, css can also be helped for if desired.<br />
</span></p>
<div id="_mcePaste" class="mcePaste" style="position: absolute; left: -10000px; top: 603px; width: 1px; height: 1px; overflow: hidden;"><strong><a rel="attachment wp-att-9798" href="http://xebee.xebia.in/2011/08/01/create-a-custom-component-using-html-and-javascript-in-salesforce/demo1-2/"><img class="size-full wp-image-9798 alignleft" title="demo1" src="http://xebee.xebia.in/wp-content/uploads/2011/08/demo11.png" alt="" width="547" height="239" /></a></strong><span style="color: #ffffff;">.</span><span style="color: #ffffff;">.</span></p>
<p>.</p>
<p>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/08/01/create-a-custom-component-using-html-and-javascript-in-salesforce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hadoop &#8211; What is MapReduce?</title>
		<link>http://xebee.xebia.in/2011/07/31/hadoop-what-is-mapreduce/</link>
		<comments>http://xebee.xebia.in/2011/07/31/hadoop-what-is-mapreduce/#comments</comments>
		<pubDate>Sun, 31 Jul 2011 14:36:13 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[hadoop]]></category>
		<category><![CDATA[MapReduce]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9518</guid>
		<description><![CDATA[In this post I will be explaining the concept of MapReduce and how Hadoop uses it. I will be talking mostly about what Hadoop is, what can it do, when to use it etc. So, lets try to associate Hadoop with the technical problem it solves. Suppose the application you are working on has ever [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">In this post I will be explaining the concept of <a href="http://hadoop.apache.org/mapreduce/" target="_blank">MapReduce</a> and how <a href="http://hadoop.apache.org/" target="_blank">Hadoop</a> uses it. I will be talking mostly about what Hadoop is, what can it do, when to use it etc. So, lets try to associate Hadoop with the technical problem it solves.</p>
<p style="text-align: justify;">Suppose the application you are working on has ever growing data. Let it be a search engine collecting data from crawlers. After a certain time, the data will become so huge that the database servers won’t be able to handle it. Then, you will buy more powerful database servers (machines) which can handle such data. But the data will keep growing, then you will again have to buy a more powerful and sophisticated machine and this will go on until more powerful machines are not there. These ultra masculine machines are pretty costly. They have special hardware which is not that common, this accounts for the high price.</p>
<p style="text-align: justify;">Before knowing what Hadoop is, and how it solves this problem, its necessary to know what MapReduce is. So, lets begin.<br />
<span id="more-9518"></span><br />
MapReduce is way of processing data. Its basic concepts are “mappers” (data transformers) and “reducers” (data aggregators). You can also think of MapReduce as an algorithm. Hadoop is an implimentation of MapReduce algorithm. Hadoop is an open source framework developed by Apache which enables you to easily create an application in a MapReduce model on a distributed system.</p>
<p style="text-align: justify;">What do I mean by distributed system here? Different machines act as different nodes of the cluster. Huge data is distributed on this cluster. The nodes map (transform) this data and then reduce it ( aggregate). Different nodes work on different parts of data, so the comuputation is done in parallel, and then, the aggregation is also done parallely. The only challenge is to write your program in a MapReduce form.</p>
<p style="text-align: justify;">So, you can think of the Hadoop cluster as a group of machines doing mapping and then distributing data again on cluster for reeducing. Somewhat like shown in the picture below:</p>
<p style="text-align: justify;"><a rel="attachment wp-att-9522" href="http://xebee.xebia.in/2011/07/31/hadoop-what-is-mapreduce/hadoop-cluster/"><img class="aligncenter size-medium wp-image-9522" title="Hadoop Cluster" src="http://xebee.xebia.in/wp-content/uploads/2011/07/Hadoop-Cluster-300x248.jpg" alt="" width="300" height="248" /></a></p>
<p style="text-align: justify;">The mapper mostly transform the data on different nodes, then, the output of the mapper is shuffled and partitioned,  between differenent reducer nodes, which the reducer aggregates. Lets try to understand Mappers and Reducers using an example. The most common example of this is : program to count words in a file. This MapReduce program is bundled ( in a jar ) as a example with hadoop installation files . It counts which word appeared how many times in a file.</p>
<p style="text-align: justify;">Suppose the file contains following lines, and different lines will go to different mappers (nodes in the cluster) for processing.</p>
<h4 style="text-align: justify;">“The first line.”</h4>
<p style="text-align: justify;">-------- This line will be processed by the first node (mapper)</p>
<h4 style="text-align: justify;">“The second line. The second line”</h4>
<p style="text-align: justify;">--------- This line will be processed by the second node (mapper)</p>
<p style="text-align: justify;">So, the Mapper can be written in such way, that, each mapper returns a list of words appearing in the line it got for processing and its word count.</p>
<p style="text-align: justify;">First Node’s mapper returns :</p>
<p style="text-align: justify;">Word, Count</p>
<h4 style="text-align: justify;">“The”, 1<br />
“first”, 1<br />
“line”, 1</h4>
<p style="text-align: justify;">Second Node’s mapper returns</p>
<p style="text-align: justify;">Word, Count</p>
<h4 style="text-align: justify;">“The” 2<br />
“second” 2<br />
“line” 2</h4>
<p style="text-align: justify;">Now, this data (output of mapper) will be distributed to the reducers. The reducer will aggregate this data and the end result can be.</p>
<h4 style="text-align: justify;">“The” 3<br />
“line” 3<br />
“first” 1<br />
“second” 2</h4>
<p style="text-align: justify;">What we have seen above is a mapreduce way for writing (designing) programs. The input is “mapped” (transformed) and then “reduced” (aggregated).</p>
<p style="text-align: justify;">So, when the data grows enormously, this data is distributed on different nodes for mapping. As the data increases, you can add new nodes at runtime. This helps to scale out as the data increases. This scale out is different than scale up of the “strong machine” concept. These machines of cluster are normal machines which are pretty cheap and can be easily added. The nodes can be added dynamically to the cluster.  No matter how big the data becomes, the nodes can be added as the data increases.</p>
<p style="text-align: justify;">This is all about the basic concept of Hadoop and MapReduce. Setting up hadoop is pretty easy on linux. It can be done on windows also using cygwin. Even Mac and other OS support it. Personally, I have tried it on windows I felt that it was a pain. Setting it up on linux is almost a piece of cake. Happy Hadooping.</p>
<h4 style="text-align: justify;"><span style="text-decoration: underline;">References :</span></h4>
<address style="text-align: justify;">Hadpoop in Action - For Hadoop and MapReduce concepts.<br />
<a href="http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-single-node-cluster/" target="_blank">http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-single-node-cluster/</a> - Excellent tutorial to setup hadoop on linux.</address>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/31/hadoop-what-is-mapreduce/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfony Functional Testing &#8211; Form POST and AJAX Request Testing</title>
		<link>http://xebee.xebia.in/2011/07/29/symfony-functional-testing-form-post-and-ajax-request-testing/</link>
		<comments>http://xebee.xebia.in/2011/07/29/symfony-functional-testing-form-post-and-ajax-request-testing/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 07:11:16 +0000</pubDate>
		<dc:creator>Ram Sharma</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Functional Testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9493</guid>
		<description><![CDATA[Symfony is a one of the best open-source PHP web application frameworks with a huge and comprehensive documentation. Symfony comes with default inbuilt testing framework for functional and unit testing. I recently started working on Symfony functional test cases. I personally found the testing framework very strong and useful. When I was writing functional test [...]]]></description>
			<content:encoded><![CDATA[<p>Symfony is a one of the best open-source PHP web application frameworks with a huge and comprehensive documentation. Symfony comes with default inbuilt testing framework for functional and unit testing. I recently started working on Symfony functional test cases. I personally found the testing framework very strong and useful.</p>
<p>When I was writing functional test cases for my recent application, I came across with various scenarios where Symfony's documentation lacks or very limited information available on web directly. Here, I am sharing my experiences and solutions for the various scenarios of functional testing.</p>
<p>Testing post request with forms:<br />
Let's take an example if you have any user registration feature and you want to test it (here is a simple code that I used to test):</p>
<p>Assuming that you have registration functionality working with Symfony framework and its URL is http://www.xyz.com/register and it shows a form:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;form action=&quot;/register&quot; method=&quot;post&quot; &gt;
 &lt;tr&gt;
   &lt;th&gt;&lt;label for=&quot;signup_username&quot;&gt;User Name&lt;/label&gt;&lt;/th&gt;
   &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;signup[username]&quot; id=&quot;signup_username&quot; /&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
   &lt;th&gt;&lt;label for=&quot;signup_email&quot;&gt;Email&lt;/label&gt;&lt;/th&gt;
   &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;signup[email]&quot; id=&quot;signup_email&quot; /&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
   &lt;th&gt;&lt;label for=&quot;signup_password&quot;&gt;Password&lt;/label&gt;&lt;/th&gt;
   &lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;signup[password]&quot; id=&quot;signup_password&quot; /&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
   &lt;th&gt;&lt;label for=&quot;signup_password_confirmation&quot;&gt;Confirm Password&lt;/label&gt;&lt;/th&gt;
   &lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;signup[password_confirmation]&quot; id=&quot;signup_password_confirmation&quot; /&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/form&gt;
&lt;pre&gt;</pre>
<p><span id="more-9493"></span></pre>
<p>I am assuming you have a fair idea of writing functional test cases in Symfony. Now to create a functional test case. Create a test file RegisterTest.php in your project's test/functional directory, you can do it manually or if you have used Symfony CLI to generate your module, it will automatically generate the test file and it will look like the following by default:</p>
<pre class="brush: php; title: ; notranslate">
 include(dirname(__FILE__).'/../../bootstrap/functional.php');

 $browser = new sfTestFunctional(new sfBrowser());

 $browser-&gt;
   get('/register')-&gt;
   with('request')-&gt;begin()-&gt;
     isParameter('module', 'UserRegistration')-&gt;
     isParameter('action', 'index')-&gt;
   end()-&gt;
   with('response')-&gt;begin()-&gt;
     isStatusCode(200)-&gt;
     checkElement('body', '!/This is a temporary page/')-&gt;
  end();
 </pre>
<p>To test general success of the registration page, if it  is properly loaded in the browser, update the above code with the following:</p>
<pre class="brush: php; title: ; notranslate">
 $browser-&gt;
   get('/register')-&gt;
   with('request')-&gt;begin()-&gt;
     isParameter('module', 'UserRegistration')-&gt;
     isParameter('action', 'index')-&gt;
   end()-&gt;
   with('response')-&gt;begin()-&gt;
     isStatusCode(200)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;signin[username]&quot;]',true)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;signin[password]&quot;]',true)-&gt;
 end();
 </pre>
<p>I am just checking only 2 fields of the form but you can check as many fields as you want. The above code will make a GET request to '/register' through a mock browser object '$browser' and check the response if the form have those required elements in it.</p>
<pre class="brush: php; title: ; notranslate">
 input[type=&quot;text&quot;][name=&quot;signin[username]&quot;] ~ &lt;input type=&quot;text&quot; name=&quot;signup[username]&quot; id=&quot;signup_username&quot; /&gt;
 </pre>
<p>When you run the above test case via Symfony command line tool:</p>
<pre class="brush: bash; title: ; notranslate">
 symfony test:functional yourapp RegisterTest
 </pre>
<p>it will give you a result something like:</p>
<pre class="brush: php; title: ; notranslate">
 # get /register
 ok 1 - status code is 200
 ok 2 - response selector form input[type=text][name=signin[username]] exists
 ok 2 - response selector form input[type=text][name=signin[password]] exists
 </pre>
<p>Now to extend the test case to test the functionality for actually registering the user with the form, use the code below:</p>
<pre class="brush: php; title: ; notranslate">
 $browser-&gt;
   get('/register')-&gt;
   with('request')-&gt;begin()-&gt;
     isParameter('module', 'UserRegistration')-&gt;
     isParameter('action', 'index')-&gt;
   end()-&gt;
   with('response')-&gt;begin()-&gt;
     isStatusCode(200)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;signin[username]&quot;]',true)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;signin[password]&quot;]',true)-&gt;
   end()-&gt;
   with('form')-&gt;begin()-&gt;
     setField('signup[username]', 'abc')-&gt;
     setField('signup[email_address]', 'abc@xyz.com')-&gt;
     setField('signup[password]', 'xyz')-&gt;
     setField('signup[password_confirmation]', 'xyz')-&gt;
   click('save')-&gt;
 end();
 </pre>
<p>Assuming the code redirects the user to some other page after successfully registration:</p>
<pre class="brush: php; title: ; notranslate">
 with('form')-&gt;begin()-&gt;
   setField('signup[username]', 'abc')-&gt;
   setField('signup[email_address]', 'abc@xyz.com')-&gt;
   setField('signup[password]', 'xyz')-&gt;
   setField('signup[password_confirmation]', 'xyz')-&gt;
   click('save')-&gt;
 end()-&gt;
 with('response')-&gt;begin()-&gt;
   isRedirected()-&gt;
   isStatusCode(302)-&gt;
   followRedirect()-&gt;
 end();
 </pre>
<p>Now there is a case in which the form had some errors while submitting, it will fail your test:</p>
<pre class="brush: php; title: ; notranslate">
 isRedirected()-&gt;
 isStatusCode(302)-&gt;
 </pre>
<p>and you have no clue why it is failing? What was the error on the form? or if the form had an error while submitting the request. Use the following code to check that:</p>
<pre class="brush: php; title: ; notranslate">
 with('form')-&gt;begin()-&gt;
   setField('signup[username]', 'abc')-&gt;
   setField('signup[email_address]', 'abc@xyz.com')-&gt;
   setField('signup[password]', 'xyz')-&gt;
   setField('signup[password_confirmation]', 'xyz')-&gt;
   click('save')-&gt;
 end()-&gt;
 with('form')-&gt;begin()-&gt;
   hasErrors(false)-&gt;
 end()-&gt;
 with('response')-&gt;begin()-&gt;
   isRedirected()-&gt;
   isStatusCode(302)-&gt;
   followRedirect()-&gt;
 end();
 </pre>
<p>By using the above code at-least you can now know that the form had errors and you can use debug method of the $browser object to debug that error:</p>
<pre class="brush: php; title: ; notranslate">
 with('form')-&gt;begin()-&gt;
   hasErrors(false)-&gt;
   debug()-&gt;
 end()-&gt;
 </pre>
<p>This is how you can write and debug test cases for Form POST request testing scenarios.</p>
<p>There is another interesting scenario I came across for AJAX request testing in Symfony application. You will hardly find information on the web directly, which talks about AJAX requests testing, except a small paragraph on <a title="Symfony AJAX Request Testing" href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/18" target="_blank">http://www.symfony-project.org/jobeet/1_4/Doctrine/en/18</a></p>
<p>The following simple test case includes both the scenarios: AJAX GET and AJAX POST request testing:</p>
<p>This is a simple scenario to add a new book in the books list in a library management system with AJAX. In this scenario we are testing that AJAX GET request should take a Book form in response with some basic fields and after putting the data in the form the page posts the data back to the server, if the book is added successfully it will send a redirection with Status code 302.</p>
<pre class="brush: php; title: ; notranslate">
 $browser-&gt;setHttpHeader('X-Requested-With', 'XMLHttpRequest')-&gt;
   get('/book/add')-&gt;
   with('request')-&gt;begin()-&gt;
     isParameter('module', 'Book')-&gt;
     isParameter('action', 'add')-&gt;
   end()-&gt;
   with('response')-&gt;begin()-&gt;
     isStatusCode(200)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;book[book_name]&quot;]',true)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;book[book_author]&quot;]',true)-&gt;
   end()-&gt;
   with('form')-&gt;begin()-&gt;
     setHttpHeader('X-Requested-With', 'XMLHttpRequest')-&gt;
     setField('book[book_name]', 'Symfony Testing')-&gt;
     setField('book[book_author]', 'Ram Sharma')-&gt;
     click('Save')-&gt;
   end()-&gt;
   with('form')-&gt;begin()-&gt;
     hasErrors(false)-&gt;
   end()-&gt;
   with('response')-&gt;begin()-&gt;
     isRedirected()-&gt;
     isStatusCode(302)-&gt;
    followRedirect()-&gt;
 end();
 </pre>
<p>In the above two cases, If you have the features only for Authenticated users, so you would not be able to PASS your test cases. For that you have to do mock login in your test case, like the code below:<br />
Assuming you have a login form like this:</p>
<pre class="brush: xml; title: ; notranslate">
 &lt;form action=&quot;/register&quot; method=&quot;post&quot; &gt;
   &lt;tr&gt;
     &lt;th&gt;&lt;label for=&quot;signin_username&quot;&gt;User Name&lt;/label&gt;&lt;/th&gt;
     &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;signin[username]&quot; id=&quot;signin_username&quot; /&gt;&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
     &lt;th&gt;&lt;label for=&quot;signin_password&quot;&gt;Password&lt;/label&gt;&lt;/th&gt;
     &lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;signin[password]&quot; id=&quot;signin_password&quot; /&gt;&lt;/td&gt;
   &lt;/tr&gt;
 &lt;/form&gt;
 </pre>
<p>so, your test case will look like this:</p>
<pre class="brush: php; title: ; notranslate">
 $browser-&gt;get('/login')-&gt;
   with('response')-&gt;begin()-&gt;
     isStatusCode(200)-&gt;
     checkElement('form input[type=&quot;text&quot;][name=&quot;signin[username]&quot;]',true)-&gt;
     setField('signin[username]', 'ram')-&gt;
     setField('signin[password]', 'test123')-&gt;
     click('Signin')-&gt;
 end()-&gt;
 /*
 * every method like end(), debug(), begin() or assert methods
 * returns back the $browser object
 */
 setHttpHeader('X-Requested-With', 'XMLHttpRequest')-&gt;
 get('/book/add')-&gt;
   with('request')-&gt;begin()-&gt;
     isParameter('module', 'Book')-&gt;
     isParameter('action', 'add')-&gt;
   end()-&gt;
 with('response')-&gt;begin()-&gt;
   isStatusCode(200)-&gt;
   checkElement('form input[type=&quot;text&quot;][name=&quot;book[book_name]&quot;]',true)-&gt;
   checkElement('form input[type=&quot;text&quot;][name=&quot;book[book_author]&quot;]',true)-&gt;
 end()-&gt;
 with('form')-&gt;begin()-&gt;
   setHttpHeader('X-Requested-With', 'XMLHttpRequest')-&gt;
   setField('book[book_name]', 'Symfony Testing')-&gt;
   setField('book[book_author]', 'Ram Sharma')-&gt;
   click('Save')-&gt;
 end()-&gt;
 with('form')-&gt;begin()-&gt;
   hasErrors(false)-&gt;
 end()-&gt;
 with('response')-&gt;begin()-&gt;
   isRedirected()-&gt;
   isStatusCode(302)-&gt;
   followRedirect()-&gt;
 end();
 </pre>
<p>Now you are able to test Form POST request, AJAX GET/POST and functional test cases for authenticated user features with Symfony's inbuilt test framework. In the end I just want to tell you that Symfony's testing framework is a very powerful tool but at times you may not find the appropriate help. So use debug() it will help you a-lot.</p>
<p>In case if you have any specific queries or problems, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/29/symfony-functional-testing-form-post-and-ajax-request-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Xpressions iPhone/iPod app</title>
		<link>http://xebee.xebia.in/2011/07/28/xpressions-iphoneipod-app/</link>
		<comments>http://xebee.xebia.in/2011/07/28/xpressions-iphoneipod-app/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 11:53:52 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[emotions]]></category>
		<category><![CDATA[feelings]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iphone app]]></category>
		<category><![CDATA[ipod]]></category>
		<category><![CDATA[Xebia]]></category>
		<category><![CDATA[Xpressions]]></category>
		<category><![CDATA[xpressions iphone app]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9447</guid>
		<description><![CDATA[Smartphones have made a deep impact on our lives. Applications not only provide services to the users or entertain them, but connect to them at an emotional level. At Xebia we strive to build apps that connect with users. Our first step in this direction was Talking Photos, an app which enables a user to [...]]]></description>
			<content:encoded><![CDATA[<p>Smartphones have made a deep impact on our lives. Applications not only provide services to the users or entertain them, but connect to them at an emotional level.</p>
<p>At Xebia we strive to build apps that connect with users. Our first step in this direction was <a href="http://itunes.apple.com/us/app/talking-photos/id404521194?mt=8">Talking Photos</a>, an app which enables a user to speak out his feelings and experiences related to an image and tie them onto the image in the iPhone, thus sealing them in memories.</p>
<p>Our next app <a href="http://itunes.apple.com/us/app/kalorific/id431603274?mt=8">Kalorific</a> empowered the user to keep track of his calorie intake, providing him a comparitive view of the calories that different eatables added to his diet. <strong>Our latest app <a href="http://itunes.apple.com/us/app/xpressions/id438903561?mt=8">Xpressions</a> adds an entirely new dimension to the way feelings can be expressed</strong>. The joy on the face of your loved one, when they see magical rose petals swirl around the iPhone screen and slowly rearrange into a custom message, cannot be expressed in mere words, rather as the following video shows, it can only be experienced.</p>
<p><span id="more-9447"></span><br />
<iframe width="640" height="480" src="http://www.youtube.com/embed/fX9gbB8lauY" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/28/xpressions-iphoneipod-app/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Component Instrumentation with RIATest (Part-2)</title>
		<link>http://xebee.xebia.in/2011/07/28/component-instrumentation-with-riatest-part-2/</link>
		<comments>http://xebee.xebia.in/2011/07/28/component-instrumentation-with-riatest-part-2/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 20:11:52 +0000</pubDate>
		<dc:creator>Amit Sharma</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Quality]]></category>
		<category><![CDATA[Quality Assurance]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[action script]]></category>
		<category><![CDATA[component instrumentation]]></category>
		<category><![CDATA[flex testing]]></category>
		<category><![CDATA[riatest]]></category>
		<category><![CDATA[supertabNavigator]]></category>
		<category><![CDATA[superTabNavigator automation]]></category>
		<category><![CDATA[UI testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9389</guid>
		<description><![CDATA[In the first part of this series http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/#more-9326 , we discussed how RIATest has a default support for automation of TabNavigator component. Now lets apply our learnings and try to automate a third party component SuperTabNavigator(STN) which is a part of FlexLib components. The SuperTabNavigator is an extension of the TabNavigator navigation container and it functions exactly [...]]]></description>
			<content:encoded><![CDATA[<p>In the first part of this series <a href="http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/#more-9326">http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/#more-9326</a> , we discussed how RIATest has a default support for automation of TabNavigator component. Now lets apply our learnings and try to automate a third party component SuperTabNavigator(STN) which is a part of FlexLib components. The SuperTabNavigator is an extension of the TabNavigator navigation container and it functions exactly like the TabNavigator, but adds some functionality. Added functionality includes:<br />
1. Draggable, re-orderable tabs<br />
2. Closable tabs<br />
3. Scrolling tab bar if too many tabs are open<br />
4. Drop-down list of tabs.</p>
<p><span id="more-9389"></span><br />
By looking at the code of SuperTabNavigator, found at <a href="http://code.google.com/p/flexlib/source/browse/trunk/src/flexlib/containers/SuperTabNavigator.as?r=212">http://code.google.com/p/flexlib/source/browse/trunk/src/flexlib/containers/SuperTabNavigator.as?r=212</a> , it becomes evident (hardly any surprises here) that it extends TabNavigator component. Also notice from the code that SuperTabNavigator component dispatches two events namely 'tabClose' and 'tabReordered'. In this part, we will only focus on the 'tabClose' event and the 'tabReader' automation is left for the reader as an exercise. The 'tabClose' event is dispatched whenever a user clicks the close icon present on the tab. Without automating the STN, we wont be able to record and replay this Event with RIATest. Ok so what do we have to do in order to automate SuperTabNavigator component's 'tabClose' event? Basically we have to perform following three steps in order to enable automation for STN. These are :-<br />
1.  Create a SuperTabNavigatorClassInfo.xml containing the ClassInfo details like events to be automated and properties to be verified. You need to create this xml inside a specific folder named 'classinfo' inside your RIAtest project Folder.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;AllClasses&gt;
  &lt;ClassInfo Name=&quot;SuperTabNavigator&quot; Extends=&quot;FlexTabNavigator&quot;&gt;
    &lt;Internal Class=&quot;flexlib.containers.SuperTabNavigator&quot;/&gt;
	&lt;Events&gt;
      &lt;Event Name=&quot;tabClose&quot;&gt;
        &lt;Internal Class=&quot;flexlib.events::SuperTabEvent&quot; Type=&quot;tabClose&quot;/&gt;
		&lt;Property Name=&quot;tabIndex&quot;&gt;
          &lt;PropertyType Type=&quot;Number&quot;/&gt;
        &lt;/Property&gt;
      &lt;/Event&gt;
    &lt;/Events&gt;
	&lt;Properties&gt;
      &lt;Property Name=&quot;popUpButtonPolicy&quot; Verify=&quot;true&quot;&gt;
        &lt;PropertyType Type=&quot;String&quot; /&gt;
      &lt;/Property&gt;
      &lt;Property Name=&quot;dragEnabled&quot; Verify=&quot;true&quot;&gt;
        &lt;PropertyType Type=&quot;Boolean&quot; /&gt;
      &lt;/Property&gt;
      &lt;Property Name=&quot;dropEnabled&quot; Verify=&quot;true&quot;&gt;
        &lt;PropertyType Type=&quot;Boolean&quot; /&gt;
      &lt;/Property&gt;
      &lt;Property Name=&quot;closePolicy&quot; Verify=&quot;true&quot;&gt;
        &lt;PropertyType Type=&quot;String&quot; /&gt;
      &lt;/Property&gt;
    &lt;/Properties&gt;

   &lt;/ClassInfo&gt;
&lt;/AllClasses&gt; 
</pre>
<p>In the classInfo above, the logical name of the STN is 'SuperTabNavigator' which will be used by RIATest engine. It extends 'FlexTabNavigator' (understandably so) which is defined in the flex_classes.xml in RIATest installation. The fully qualified name of the SuperTabNavagator is flexlib.containers.SuperTabNavigator. The event we want to automate is of type 'tabClose' while the fully qualified name of the Event is flexlib.events::SuperTabEvent. The logical name of the event to be used by RIATest for automation is 'tabClose'. The SuperTabEvent (have a look at the code found in automation.swc) needs the tab index as a parameter. So we have a property with name 'tabIndex' and type 'Number' for the 'Event' tag in classInfo. Also we have some properties of the SuperTabNavigator to be verified in the RIATest scripts.</p>
<p>2. Create a SuperTabNavigatorAutomationImpl class in your Flex Project source which should have the necessary methods overridden for record and replay of the events advertised in its classInfo.</p>
<pre class="brush: as3; title: ; notranslate">
package com.xebialabs.deployit.riatestdelegates
{
	import flash.display.DisplayObject;
	import flash.events.Event;

	import flexlib.containers.SuperTabNavigator;
	import flexlib.controls.SuperTabBar;
	import flexlib.controls.tabBarClasses.SuperTab;
	import flexlib.events.SuperTabEvent;

	import mx.automation.Automation;
	import mx.automation.IAutomationObject;
	import mx.automation.IAutomationObjectHelper;
	import mx.automation.delegates.containers.TabNavigatorAutomationImpl;
	import mx.controls.Button;
	import mx.core.mx_internal;

	use namespace mx_internal;

	[Mixin]
	public class SuperTabNavigatorAutomationImpl extends TabNavigatorAutomationImpl
	{

		private var superTabNavigator:SuperTabNavigator;

		//--------------------------------------------------------------------------
		//
		//  Class methods
		//
		//--------------------------------------------------------------------------

		/**
		 *  Registers the delegate class for a component class with automation manager.
		 *
		 *  @param root The SystemManger of the application.
		 */
		public static function init(root:DisplayObject):void
		{
			Automation.registerDelegateClass(SuperTabNavigator, SuperTabNavigatorAutomationImpl);
		}

		public function SuperTabNavigatorAutomationImpl(obj:SuperTabNavigator)
		{
			superTabNavigator = obj;
			super(obj);

		}

		//--------------------------------------------------------------------------
		//
		//  Event handlers
		//
		//--------------------------------------------------------------------------

		/**
		 *  Method which gets called after the component has been initialized.
		 *  This can be used to access any sub-components and act on the component.
		 */
		override protected function componentInitialized():void
		{
			super.componentInitialized();
			superTabNavigator.addEventListener(SuperTabEvent.TAB_CLOSE, tabCloseHandler, false, 0, true);
		}

		private function tabCloseHandler(superTabEvent:SuperTabEvent):void {
			recordAutomatableEvent(superTabEvent);
		}

		/**
		 *  Replays SuperTabEvents by dispatching a MouseEvent to the item that was
		 *  clicked. In case of ItemClickEvent it is passed on to the super class to handle.
		 *
		 *  @param interaction The event to replay.
		 *
		 *  @return &lt;code&gt;true&lt;/code&gt; if the replay was successful. Otherwise, returns &lt;code&gt;false&lt;/code&gt;.
		 */
		override public function replayAutomatableEvent(interaction:Event):Boolean
		{
			if(interaction is SuperTabEvent) {
				var tabCloseEvent:SuperTabEvent = interaction as SuperTabEvent;
				var help:IAutomationObjectHelper = Automation.automationObjectHelper;

				var replayer:IAutomationObject = superTabNavigator.getTabBar() as IAutomationObject;
				var superTab:Button = superTabNavigator.getTabAt(tabCloseEvent.tabIndex);
				var closeButton:DisplayObject;
				for(var i:int = 0; i&lt; superTab.numChildren; i++) {
 					closeButton = superTab.getChildAt(i);
 					if(closeButton is Button) {
 						break;
 					}
 				}
 				help.replayClick(closeButton);
 				return true;
 			}else {
 				return super.replayAutomatableEvent(interaction);
 			}
 		}
 	}
 }
 </pre>
<p>Since SuperTabNavigator extends TabNavigator, the SuperTabNavigatorAutomationImpl extends TabNavigatorAutomationImpl. We register this class as the automation delegate for the SuperTabNavigator component in the static method init. Notice that we have a [Mixin] metadata tag just above our class. When you put the [Mixin] metadata just above your class definition and add a static init function to the class, like we have in our class, the static init function will be called as soon as your application loads (assuming this class is referenced somewhere in the app). This is useful if you have some code that you want to run before any of the other code in the class.<br />
In the overridden componentInitialized method, we add a event listener to the superTabNavigator component which will listen to any event of type SuperTabEvent.TAB_CLOSE. In its handler tabCloseHandler, we call the recordAutomatableEvent method passing in the event which will record this event with the AutomationManager. In order to replay the event we need to first override the replayAutomatableEvent method and then dispatch the Mouse Click event on the close Icon of the tab specified by the tabIndex property of the event. The code above is fairly straightforward. We used the AutomationObjectHelper to replay the Click on the icon of the tab once is it retrieved. Also notice that this method replays the TabClose event only if the event is of type SuperTabEvent. For all other events it calls the replayAutomatableEvent of the super class. That's why you can still record and replay an 'itemClick' event of a SuperTabNavigator.<br />
Note - You need to have all the automation swcs in the project classpath. Since i was using Flex 3.5 sdk, which contains all the automation libraries, i didn't have to include any automation swc explicitly.</p>
<p>3. Make sure SuperTabNavigatorAutomationImpl  delegate class is referenced in your application for its static 'init' method to be called (Remember the 'Mixin' metadata tag that we've applied to the class above). Do this by adding an import statement in your main.mxml. For example -</p>
<pre class="brush: as3; title: ; notranslate">
import com.xebialabs.deployit.riatestdelegates.SuperTabNavigatorAutomationImpl;
</pre>
<p>Now you are ready to record and play the 'tabClose' event of the SuperTabNavigator with RIATest. When you click the 'closeIcon' of any tab in your application while recording in RIATest, you will get something like this in the RIA scripts: </p>
<p>SuperTabNavigator("editorTabBar")=>tabClose(1);</p>
<p>Here 'editorTabBar' is the id of the SuperTabNavigator component while 1 is the index of the tab to be closed. And when you try to replay the script, it should work like a charm.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/28/component-instrumentation-with-riatest-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Component Instrumentation with RIA Test (Part-1)</title>
		<link>http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/</link>
		<comments>http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 09:53:33 +0000</pubDate>
		<dc:creator>Amit Sharma</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[action script]]></category>
		<category><![CDATA[component instrumentation]]></category>
		<category><![CDATA[flex Automation]]></category>
		<category><![CDATA[Flex TabNavigator]]></category>
		<category><![CDATA[flex testing]]></category>
		<category><![CDATA[Instrumentation]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[record and play]]></category>
		<category><![CDATA[RIA Test]]></category>
		<category><![CDATA[supertabNavigator]]></category>
		<category><![CDATA[superTabNavigator automation]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9326</guid>
		<description><![CDATA[One of the key requirements of any modern day enterprise product is to have the capability of Automation. While there are many products in the market today that provide UI automation testing (read Record and Play) but when it comes to automate flex applications, RIA Test http://www.riatest.com is as close as you can get to [...]]]></description>
			<content:encoded><![CDATA[<p>One of the key requirements of any modern day enterprise product is to have the capability of Automation. While there are many products in the market today that provide UI automation testing (read Record and Play) but when it comes to automate flex applications, RIA Test <a href="http://www.riatest.com">http://www.riatest.com</a> is as close as you can get to have a perfect solution in place.</p>
<p>We have been using RIATest for quite some time in our product 'DeployIt' and i must say we have reaped huge benefits from it. Deployit by the way is XebiaLabs product for automated deployments.<br />
While RIATest IDE is very intuitive and RIATest itself supports automation for all basic UI components (and also Spark components) . It means that we don't have to do anything special to record and replay the events originating from those components. Unfortunately, things are not very simple if you want to automate  your own components which extends basic flex components. Things heat up even more in case you wish to automate any third party components.</p>
<p><span id="more-9326"></span></p>
<p>While RIATest has a default support for basic UI components and TabNavigator component is no exception. In this part 1, we will try to analyze how does RIATest support automation for TabNavigator in order to learn the technicalities of automation delegates.<br />
If you go to your RIATest installation, you will find a flex_classes.xml. This file contains the information in the form of 'ClassInfo' elements which tells the RiaTest Engine about all properties that can be verified for a particular component and which all events can be recorded and replayed.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;ClassInfo Name=&quot;FlexTabNavigator&quot; Extends=&quot;FlexViewStack&quot; SupportsTabularData=&quot;true&quot;&gt;
      &lt;Internal Class=&quot;mx.events::ItemClickEvent&quot; Type=&quot;itemClick&quot;/&gt;
      &lt;Events&gt;
        &lt;Event Name=&quot;itemClick&quot;&gt;
           &lt;Internal Class=&quot;mx.events::ItemClickEvent&quot; Type=&quot;itemClick&quot;/&gt;
           &lt;Property Name=&quot;relatedObject&quot;&gt;
             &lt;PropertyType Type=&quot;String&quot; Codec=&quot;tab&quot;/&gt;
           &lt;/Property&gt;
        &lt;/Event&gt;
      &lt;/Events&gt;
       &lt;Properties&gt;
         &lt;Property Name=&quot;horizontalAlign&quot; Verify=&quot;true&quot;&gt;
           &lt;PropertyType Type=&quot;String&quot; /&gt;
         &lt;/Property&gt;
         &lt;Property Name=&quot;horizontalGap&quot; Verify=&quot;true&quot;&gt;
           &lt;PropertyType Type=&quot;Number&quot; /&gt;
         &lt;/Property&gt;
         &lt;Property Name=&quot;tabHeight&quot; Verify=&quot;true&quot;&gt;
           &lt;PropertyType Type=&quot;Number&quot; /&gt;
         &lt;/Property&gt;
        &lt;Property Name=&quot;tabWidth&quot; Verify=&quot;true&quot;&gt;
          &lt;PropertyType Type=&quot;Number&quot; /&gt;
        &lt;/Property&gt;
      &lt;/Properties&gt;
&lt;/ClassInfo&gt;
</pre>
<p>For TabNavigator component, the 'Name' attribute of the classInfo element shows the logical name for the component that will be used by RIATest in the scripts. The 'Extends' attribute shows the logical name of the component that TabNavigator extends. In this case it is FlexViewStack and the component is ViewStack. The actual class name is provided in 'Class' attribute of 'Internal' element. All the events that need to be automated for TabNavigator are provided in the 'Event' element under 'Events'. Here 'Name' attribute depicts the logical name of the event to be used by RIATest in automation scripts. The 'Class' attribute of the 'Internal' tag under &lt;Event&gt; shows the fully qualified name of the actual event class while 'Type' attribute shows the actual event type. Then it is specified that this event needs to be passed an object which is actually the selected Tab. We use   a special attribute called 'Codec' with value 'tab'. The 'Properties' tag contains different 'Property' elements containing the 'Name' and 'Type' of the component properties which you want to verify in RIATest scripts.</p>
<p>For each ClassInfo element in flex_classes.xml, you will find a corresponding Automation class called Delegate in the automation.swc which is either included in Flex sdk or you have to include it as a library to support automation. Since we were using Flex sdk 3.5 this swc was bundled as part of the sdk. For TabNavigator, the automation delegate class is TabNavigatorAutomationImpl.</p>
<pre class="brush: as3; title: ; notranslate">
use namespace mx_internal;

[Mixin]

public class TabNavigatorAutomationImpl extends ViewStackAutomationImpl
{
    include &quot;../../../core/Version.as&quot;;

    public static function init(root:DisplayObject):void
    {
        Automation.registerDelegateClass(TabNavigator, TabNavigatorAutomationImpl);
    }

    public function TabNavigatorAutomationImpl(obj:TabNavigator)
    {
        super(obj);
    }

    protected function get tabNavigator():TabNavigator
    {
        return uiComponent as TabNavigator;
    }

    override public function get automationTabularData():Object
    {
        var delegate:IAutomationObject
                = tabNavigator.getTabBar() as IAutomationObject;

        return delegate.automationTabularData;
    }

    override public function replayAutomatableEvent(interaction:Event):Boolean
    {
        var replayer:IAutomationObject =
                    tabNavigator.getTabBar() as IAutomationObject ;
        return replayer.replayAutomatableEvent(interaction);
    }

    override protected function componentInitialized():void
    {
        super.componentInitialized();
        tabNavigator.getTabBar().addEventListener(AutomationRecordEvent.RECORD,
                                    tabBar_recordHandler, false, 0, true);
    }

    private function tabBar_recordHandler(event:AutomationRecordEvent):void
    {
        recordAutomatableEvent(event.replayableEvent);
    }

    }
}
</pre>
<p>This Automation Delegate class <em><strong>TabNavigatorAutomationImpl </strong></em>extends <em><strong>ViewStackAutomationImpl </strong></em>and it implements <em><strong>IAutomationObject </strong></em>interface . Remember that in its ClassInfo FlexTabNavigator extends FlexViewStack.  So its Automation class also matches the defined ClassInfo.  One of the most important methods of this delegate class is the static init method which takes the DisplayObject as its parameters.  This DisplayObject is the SystemManager of the application and this method registers this delegate class for the TabNavigator component class with automation manager.  The other important method in this delegate class is the overridden <em>componentInitialized</em> method which gets called after the component, which is TabNavigator in our case, gets initialized.  It is in this method only that an EventListener can be added. Notice that in this case, an event listener is added to the ''TabBar' of this TabNavigator component which listens for any recordable event. A handler method named <em>tabBar_recordHandler</em> is added. In this handler, <em>recordAutomatableEvent </em>of the <em>UIComponentAutomationImpl </em>class is called, passing the event which will call the <em>recordAutomatableEvent </em>of the <em>AutomationManager</em>.</p>
<p>For replaying  this event, we need to override <em>replayAutomatableEvent </em>which has the Event as its parameter. The event that was recorded earlier needs to be dispatched from that component. In this case, the ItemClickEvent needs to be replayed by dispatching a MouseEvent to the item (TabBar) that was clicked.  This MouseEvent.CLICK is handled ultimately in the <em>replayAutomatableEvent </em>of <em>UIComponentAutomationImpl </em>which is in the parent hierarchy of <em>TabNavigatorAutomationImpl </em>class.</p>
<pre class="brush: as3; title: ; notranslate">
public function replayAutomatableEvent(event:Event):Boolean
{
var help:IAutomationObjectHelper = Automation.automationObjectHelper;
if (event is MouseEvent &amp;&amp; event.type == MouseEvent.CLICK)
return help.replayClick(uiComponent, event as MouseEvent);
</pre>
<p>So in the overridden method replayAutomatableEvent of TabNavigatorAutomationImpl, we call this method of UIComponentAutomationImpl (Polymorphism). Notice that in this method, if the event is of type MouseEvent.CLICK, this method will take the help of AutomationHelper to replay the click event on this component and return true if the Click is replayed successfully. Now when you record the clicking of TabNavigator component in RIATest IDE, you have something like this in your script :</p>
<p><em>FlexTabNavigator("tabBar")=&gt;itemClick("Tab1");</em></p>
<p>Now when you run this script, this script will be replayed and the TabClick event will be replayed.</p>
<p>In this part we learned how RIATest supports automation of TabNavigator. In the next part of this series we will try to automate a third party component SuperTabNavigator(STN) which is a part of FlexLib components and is an extension of the TabNavigator navigation container.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/27/component-instrumentation-with-ria-test-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Deploying a Spring Hibernate MySQL Application on OpenShift Flex (RedHat PaaS Solution)</title>
		<link>http://xebee.xebia.in/2011/07/07/deploying-a-spring-hibernate-mysql-application-on-openshift-flex-redhat-paas-solution/</link>
		<comments>http://xebee.xebia.in/2011/07/07/deploying-a-spring-hibernate-mysql-application-on-openshift-flex-redhat-paas-solution/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 03:59:08 +0000</pubDate>
		<dc:creator>Shekhar Gulati</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[jboss tools]]></category>
		<category><![CDATA[openshift]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9280</guid>
		<description><![CDATA[Last XKE me and Sameer started a sandpit to evaluate the capabilities of OpenShift and see how easy or difficult will be to deploy an existing or new Java applications on OpenShift . OpenShift is a multi-language(PHP, Ruby, Python, Java), multi-framework Platform as a Service provided by RedHat with the goal to help developers build [...]]]></description>
			<content:encoded><![CDATA[<p>Last XKE me and Sameer started a sandpit to evaluate the capabilities of <a href="https://openshift.redhat.com/app/">OpenShift</a> and see how easy or difficult will be to deploy an existing or new Java applications on OpenShift . OpenShift is a multi-language(PHP, Ruby, Python, Java), multi-framework <a href="http://en.wikipedia.org/wiki/Platform_as_a_service">Platform as a Service</a> provided by <a href="http://www.redhat.com/">RedHat</a> with the goal to help developers build application without thinking much about infrastructure .</p>
<p>It is available in three editions :</p>
<ol>
<li><strong>Express</strong> : Express is a free PaaS for building and deploying  Ruby, PHP, and Python applications. Express now supports Java as well. When this article was written Java was not supported.</li>
<li><strong>Flex</strong> : Flex is a Paas for building and deploying web applications written in Java, JavaEE 6, or PHP . Flex also allows you to manage, monitor, and auto-scale applications from web interface. You need Amazon EC2 account to use Flex.</li>
<li><strong>Power</strong> : Power as the name suggests is the most powerful edition of OpenShift and can run any application written in any language on it. Power gives you the ultimate flexibility and access at the operating system configuration level.</li>
</ol>
<div>We decided to choose Flex edition as we wanted to deploy a standard Java Spring Hibernate MySQL application on OpenShift. Deploying an existing MySQL application on OpenShift was not straightforward so I am writing this blog to help other Java developers facing trouble deploying application on OpenShift. There was no documentation on how you can deploy a Java web application with MySQL as database.</div>
<div>In this blog will walk you step by step how you can deploy a Spring Hibernate MySQL application on OpenShift. The application server that we will be choosing for this application will be Tomcat. Flex support both JBoss and Tomcat server.<span id="more-9280"></span></div>
<h3>Let's get started</h3>
<div>
<ol>
<li><a href="https://openshift.redhat.com/app/user/new/flex">Create your account</a> for accessing Flex console.</li>
<li>Once you have created your account log in to <a href="https://openshift.redhat.com/flex/flex/index.html">Flex console</a>. Flex Console is the web interface which allows you to create, deploy, manage, or monitor your application.</li>
<li>Before we start using Flex Console lets create a simple Spring Hibernate MySQL application using Spring Roo (If you don't know about Spring Roo please refer to <a href="http://www.ibm.com/developerworks/java/library/os-springroo1/?ca=drs-">IBM DeveloperWorks</a> <a href="http://www.ibm.com/developerworks/java/library/os-springroo2/?ca=drs-">articles</a> ). Start the Roo shell and fire these commands
<pre class="brush: plain; title: ; notranslate">
project --topLevelPackage com.openshift.demo --projectName conference
persistence setup --database MYSQL --provider HIBERNATE --userName conference --password conference --databaseName conference
entity --class ~.domain.Speaker --testAutomatically
field string --fieldName fullName --notNull
field string --fieldName email --notNull
field string --fieldName bio --notNull --sizeMax 4000
entity --class ~.domain.Talk --testAutomatically
field string --fieldName title --notNull
field string --fieldName description --notNull --sizeMax 4000
field reference --type ~.domain.Speaker --fieldName speaker --notNull --class ~.domain.Talk
field set --fieldName talks --type ~.domain.Talk --class ~.domain.Speaker --cardinality ONE_TO_MANY
controller all --package ~.web
</pre>
<p>These commands will create a simple conference application which will let you create Speakers and Talks.You cannot create a talk unless you have created a Speaker for it. You can test it locally by creating a mysql database named conference and creating a user with username and password as conference. You can run the application by typing mvn clean install tomcat:run. Rename the war to conference.war as this name will in the application url.</li>
<li>After you have logged in to OpenShift Flex console, the first thing that you need to do is add a cloud account. Please click on the CLOUDS tab and you will see a screen as shown below. Currently only Amazon EC2 is supported but I think plan is to add support for multiple cloud platforms. You can give any name to account nickname field but you have to provide valid Amazon EC2 credentials to work with OpenShift. <a href="http://whyjava.files.wordpress.com/2011/07/clouds.png"><img height="300" width="294" src="http://whyjava.files.wordpress.com/2011/07/clouds.png?w=294" title="clouds" class="aligncenter size-medium wp-image-1275" /></a></li>
<li> Next you need to define a server cluster by clicking CLUSTERS tab. This will open up form to create a new Server Cluster. The field names are self-explanatory. Give server cluster some meaningful name, choose the cloud account you created in step 4, choose a location and for rest keep the default. It will take some time to create a cluster so please be patient.</li>
<li>After few minutes you will be able to see a cluster under CLUSTERS tab and a server under SERVERS tab. <strong>Please note that it will start large Amazon EC2 instance. </strong></li>
<li>Once the cluster and server have started we can deploy our conference application. Click on the APPLICATIONS tab and then click on ADD APPLICATION button. This will take you to the new application form.Please enter the details as shown below and press submit button and wait for few seconds.<br />
<a href="http://whyjava.files.wordpress.com/2011/07/new-application.png"><img height="300" width="221" src="http://whyjava.files.wordpress.com/2011/07/new-application.png?w=221" title="new-application" class="aligncenter size-medium wp-image-1277" /></a></li>
<li>This will take you to the application overview page as shown below. This page shows different tabs like overview, components, files, configure, and deploy changes. The only information that we will need from overview tab is the CLUSTER DNS conference14486738.prod.rhcloud.com. This is used to create the URL of the application by appending the application context name. In our case it will be conference.<br />
<a href="http://whyjava.files.wordpress.com/2011/07/application-overview.png"><img height="118" width="300" src="http://whyjava.files.wordpress.com/2011/07/application-overview.png?w=300" title="application-overview" class="aligncenter size-medium wp-image-1280" /></a></li>
<li>So far we have not defined the components of the application and we have also not uploaded the web application. Lets first add components by clicking the component tab under the conference application tab as shown below. I have used application server as Apace Tomcat and MySQL as database. There are other components like Zend, Memcached, and MongoDB also supported but we are not using them in this application.<br />
<a href="http://whyjava.files.wordpress.com/2011/07/application-components.png"><img height="144" width="300" src="http://whyjava.files.wordpress.com/2011/07/application-components.png?w=300" title="application-components" class="aligncenter size-medium wp-image-1283" /></a></li>
<li>After you press save button, on the DEPLOY CHANGES tab you will see that it shows that you have some files to deploy. These are configuration files which are created when we added components to our application. For now leave them as it is.</li>
<li>Next press the FILES tab to upload the conference war. Once you have uploaded the war you will see conference.war in exploded form as shown below <a href="http://whyjava.files.wordpress.com/2011/07/files.png"><img height="153" width="300" src="http://whyjava.files.wordpress.com/2011/07/files.png?w=300" title="files" class="aligncenter size-medium wp-image-1286" /></a></li>
<li>Apart from the conference.war file you have to also upload a sql file which will create the database and user for the application.<br />
Create a file named conference.sql and upload to bundle directory.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE if not exists conference;

GRANT USAGE ON conference.* TO 'conference'@'localhost';
DROP USER 'conference'@'localhost';

GRANT USAGE ON conference.* TO 'conference'@'%';
DROP USER 'conference'@'%';

--  Create conference users and grant all permissions.
CREATE USER 'conference'@'localhost' IDENTIFIED BY 'conference';
GRANT ALL ON conference.* TO 'conference'@'localhost';

CREATE USER 'conference'@'%' IDENTIFIED BY 'conference';
GRANT ALL ON conference.* TO 'conference'@'%';

use conference;
</pre>
</li>
<li>Now we have to configure the components that our application uses to run. To configure press the CONFIGURE tab, the only changes that we have to make are in the mysql-server sub-tab. There are two things that we need to change - Set Database Initialization SQL Script to bundle/conference.sql and Set configuration File Patterns to bundle/conference.war.extracted/WEB-INF/classes/META-INF/spring/database.properties.</li>
<li>Finally click on the DEPLOY CHANGES tab and press the deploy button. Once the application is started press the START button to start the application. You can view the application at http://conference14486738.prod.rhcloud.com/conference/ as shown below <a href="http://whyjava.files.wordpress.com/2011/07/conference.png"><br />
<img height="168" width="300" src="http://whyjava.files.wordpress.com/2011/07/conference.png?w=300" title="conference" class="aligncenter size-medium wp-image-1289" /></a></li>
</ol>
<p>I hope this blog will help you get started with deploying your existing Java applications on OpenShift. In case you have any queries please leave a comment. To know more about Xebia JBoss competency please visit our <a href="http://jboss.xebia.com/">website</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/07/07/deploying-a-spring-hibernate-mysql-application-on-openshift-flex-redhat-paas-solution/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Agile Team Dynamics : Developers vs Testers/Designers</title>
		<link>http://xebee.xebia.in/2011/06/22/agile-team-dynamics-developers-vs-testersdesigners/</link>
		<comments>http://xebee.xebia.in/2011/06/22/agile-team-dynamics-developers-vs-testersdesigners/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 11:56:19 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9246</guid>
		<description><![CDATA[Yesterday I had a conversations with one of my colleagues Prakash who works as a tester in an Agile project. “So how is it going on?”, I asked. Prakash took a deep breath and said, “Umm...workwise I think I am getting more confident on the application functionality now. However in one of our retrospectives I [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I had a conversations with one of my colleagues Prakash who works as a tester in an Agile project.</p>
<p>“So how is it going on?”, I asked.</p>
<p>Prakash took a deep breath and said, “Umm...workwise I think I am getting more confident on the application functionality now. However in one of our retrospectives I realized that I have to improve on some of my personal traits.”</p>
<p>“Interesting ! - and what are those?”, I asked.</p>
<p><span id="more-9246"></span></p>
<p>“One of the points, I also felt myself too is - I take a lot more time to solve a problem.</p>
<p>Second point is a bit confusing to me as team feels that in general I crib a lot but do very little to solve problem. It’s confusing as those same guys tell me to let them know the technical problems I am stuck with and raise alarm before it’s too late. However, I am not able to decipher the exact definition of “too late” here as I don’t know when telling problems to team transforms into cribbing.”, he replied.</p>
<p>I thought for a moment and continued, “At the outset, these two points look different but essentially they are smell to the problems in team dynamics.</p>
<p>From my experience, many a times, these problems occur just because testers are considered second class citizens in developers dominated Agile teams.</p>
<p>Whenever in a team we talk about "we vs they" (or testers vs developers), it essentially means that the team is not working for the success of a Sprint. Instead this team consists individuals who feel that developers and testers have to finish their individual work separately.</p>
<p>So here, the problems of testers do not become the problems of the team but rather become yet another impediment which a Tester has to solve himself. And that’s where the problem of “we vs they” become even more visible.</p>
<p>It looks like as if the team has forgotten  that the end goal for an Agile team is not about finishing individual goals (which may look good to one’s own ego) but to finish Sprint goals. </p>
<p>So in your case Prakash, it looks like developers do not have time to hear and solve your technical problems as that’s why they say you crib a lot. When you become very frustrated with their response and lack of help, you try to fix things on your own. Acquiring a new skill especially in another domain takes time. That way, you are bound to take a lot more time than it could be possible with collaboration within the team.</p>
<p>You could have avoided the problems you have if developers in your team would have been supportive to your cause. It is important in a team that everybody considers himself as a team-member first and developers/testers later. To achieve Sprint goals, everybody has to make efforts and help each other.</p>
<p>Last but not the least your Scrum Master should have taken steps to help you in fixing your technical impediments.”, I concluded.</p>
<h2>Conclusion</h2>
<p>To be honest it’s pretty common to see this “we vs they” attitude in a lot many Agile teams. It not only happens with testers but also with designers and technical writers too.  In a way, helping out tester/designer looks like an obstruction to the rhythm of developers. However essentially it can be blocker to entire Sprint SUCCESS. Definition of DONE for a customer not only includes the development effort but rather means fully tested software.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/06/22/agile-team-dynamics-developers-vs-testersdesigners/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Is Scala really Faster than Java?</title>
		<link>http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/</link>
		<comments>http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 13:07:32 +0000</pubDate>
		<dc:creator>Ravindra</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[java performance]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9185</guid>
		<description><![CDATA[Recently published paper from Google benchmarking different languages. It shows Scala to be faster compared to Java. I attempted to run the same benchmarks this weekend and am publishing my observations in this Blog. Observations in the blog may have been already made in the Google paper and by the developers involved. This topic was [...]]]></description>
			<content:encoded><![CDATA[<p>Recently published <a href="http://research.google.com/pubs/archive/37122.pdf">paper</a> from Google benchmarking different languages. It shows Scala to be faster compared to Java. I attempted to run the same benchmarks this weekend and am publishing my observations in this Blog. Observations in the blog may have been already made in the Google paper and by the developers involved.<span id="more-9185"></span></p>
<p>This topic was discussed in <a href="http://groups.google.com/group/scala-debate/browse_thread/thread/d42777ef7834517c">Scala debate mailing list</a> and i really appreciate the answer given by Martin Odersky. Analysis in Google paper attributes the lesser time taken by Scala to lesser time spent in garbage collection. Martin(and Google Analysis) also hints at use of ArrayList in java implementation(due to lack of typed Arrays) as the main culprit for lower speed of Java code. Martin did not compare the pro versions saying the implementations were not comparable.</p>
<p>My basic ( starter) understanding of Functional programming tells me that there should be more object churn in a functional language (implementation) and thus Scala should have trouble with GC not the Java implementation. I am looking forward to an explanation for this.</p>
<p>This debate seems a familiar one of whether Java is faster than C/C++. Thinking logically if some language is built on some other language then the derived language can be at most as fast as the underlying language. So how can Scala be faster than Java (after all Scala runs on JVM)? Going back to Java/C/C++ debate, it may sometimes be possible that the Hotspot generated code is faster as compared to hand written native code. So this brings in the human factor, a Scala program may perform as good as a Java program purely because of the programming model offered by Scala or Under the Hood optimizations.</p>
<p>I checked out the <a href="http://code.google.com/p/multi-language-bench/">code</a> for the benchmark , removed the -X UseCompressedOops setting as it was not available on my machine. I created a script to record -gcutil data from jstat utility and added it to run *target* in the MakeFiles. Data from jstat was then plotted using gnuplot.</p>
<p>A few basic assumptions/notes first:<br />
1. Programs were run using no special GC settings. So given equivalent type of code (Basic and Pro versions) and same environment which one would run fast.<br />
2. Comparisions are purely from a Garbage collection point of view, they do not account for implementation differences(Martin's point on pro versions).<br />
3. Observations do not discount the warm up period of the benchmark (but observations here are not absolute anyway).</p>
<p><strong>Observations:</strong></p>
<p><strong></strong><em>Java and Scala basic versions:</em></p>
<p style="padding-left: 30px;">1. Java implementation uses more memory (by comparing max memory before full GC)<br />
2. Java code spends more time in garbage collection (nothing new here).<br />
3. GC Analysis</p>
<p style="padding-left: 60px;">For Java Implementation<br />
GC Count java: 119 (minor &amp; major)<br />
Full GC Count java: 20 (major)<br />
GC Time: Young : Full : Total 31.495 21.131 52.626</p>
<p style="padding-left: 60px;">For Scala Implementation<br />
GC Count scala: 77<br />
Full GC Count scala: 5<br />
GC Time: Young : Full : Total 8.419 2.625 11.044</p>
<p style="padding-left: 30px;">4. Time collecting the young generation is significantly more in Java (more temporary objects)<br />
5. Size of old generation keeps on building till the Full GCs and much migher compared to scala implementation.</p>
<p style="padding-left: 30px;">These facts reflect the different big difference in implemantation details as the number of objects being created differ a lot between the implementations. Finer points like use of while being better than for loop.</p>
<p><em>Java and Scala Pro versions</em></p>
<p style="padding-left: 30px;">1. 	GC Analysis</p>
<p style="padding-left: 60px;">For Java Pro Implementation:<br />
GC Count java_pro: 31<br />
Full GC Count java_pro: 1<br />
GC Time: Young : Full : Total 3.623 0.286 3.910</p>
<p style="padding-left: 60px;">For Scala Pro Implementation:<br />
GC Count scala_pro: 18<br />
Full GC Count scala_pro: 3<br />
GC Time: Young : Full : Total 1.261 0.781 2.042</p>
<p style="padding-left: 30px;">2. Java implementation spends a lot of time in collecting Young generation (object churn).<br />
3. There is nothing much to read in size of old generations but a marked difference in Java Pro implementation is that the old generation becomes constant in size like the scala one.</p>
<p><strong>So what is the conclusion.</strong></p>
<p>It seems that difference in implementations is the cause for difference in the time taken by Java/Scala programs.  This is reflected in the different object creation patterns for the implementations. As you can see in the graphs below that the Java pro implementation managed to get similar old generation size patterns as to Scala. I have not gone in the details of implementations to be able to comment on why.</p>
<p>Like they say for cricket statistics, "they hide more than they reveal". It won't be fair to conclude that Scala is faster than Java in all cases. But having a language like Scala which provides better abstractions on top the existing JVM is great. Great work by guys at Google to create a benchmark which evaluates different aspects of a language.</p>
<p>But i am still looking for an answer on why there is more object churn in Java implementation compared to Scala (where i would expect a lot of immutables to be created).</p>
<p>PS: Results shown are only for a single run. Tests were run multiple time and in randon order by a script, but the general trends were same.</p>
<p>Update: Discussion on Hacker News (http://news.ycombinator.com/item?id=2678353)</p>
<table>
<tbody>
<tr>
<td><a rel="attachment wp-att-9190" href="http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/java-scala-old-generation-2/"><img class="size-medium wp-image-9190 alignleft" title="Java - Scala (old generation)" src="http://xebee.xebia.in/wp-content/uploads/2011/06/java-scala-old-generation1-300x225.png" alt="" width="300" height="225" /></a></td>
<td><a rel="attachment wp-att-9195" href="http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/java_pro-scala_pro-old-generation-2/"><img class="size-medium wp-image-9195 alignright" title="Java Pro &amp; Scala Pro Old generation" src="http://xebee.xebia.in/wp-content/uploads/2011/06/java_pro-scala_pro-old-generation1-300x225.png" alt="" width="300" height="225" /></a></td>
</tr>
<tr>
<td>Java - Scala (old generation)</td>
<td>Java Pro &amp; Scala Pro Old generation</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><a rel="attachment wp-att-9196" href="http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/java-scala-y-gc/"><img class="size-medium wp-image-9196 alignleft" title="Java Scala ( Time take for collecting young generation)" src="http://xebee.xebia.in/wp-content/uploads/2011/06/java-scala-y-gc-300x225.png" alt="" width="300" height="225" /></a></td>
<td><a rel="attachment wp-att-9197" href="http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/java_pro-scala_pro-y-gc/"><img class="size-medium wp-image-9197 alignright" title="Java Pro &amp; Scala Pro ( time taken for collecting young generation)" src="http://xebee.xebia.in/wp-content/uploads/2011/06/java_pro-scala_pro-y-gc-300x225.png" alt="" width="300" height="225" /></a></td>
</tr>
<tr>
<td>Java Scala ( Time take for collecting young generation)</td>
<td>Java Pro &amp; Scala Pro ( time taken for collecting young generation)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/06/20/is-scala-really-faster-than-java/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Drupal Webform : Add a dynamic select option list</title>
		<link>http://xebee.xebia.in/2011/06/14/drupal-webform-add-a-dynamic-select-option-list/</link>
		<comments>http://xebee.xebia.in/2011/06/14/drupal-webform-add-a-dynamic-select-option-list/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 10:20:01 +0000</pubDate>
		<dc:creator>Anubhav</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9035</guid>
		<description><![CDATA[Ever wanted to have a dynamic option list in your Webform select widget ( checkbox, radiobutton, dropdown ) ? Well, I wanted to load a dynamic list of dates in a Webform and display them as checkboxes. I faced this problem when I was developing a training website where each training class would have different [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to have a dynamic option list in your Webform select widget ( checkbox, radiobutton, dropdown ) ?</p>
<p>Well, I wanted to load a dynamic list of dates in a Webform and display them as checkboxes. I faced this problem when I was developing a training website where each training class would have different training dates.</p>
<p><em>So let's start and build our dynamic select option list.</em></p>
<p><span id="more-9035"></span></p>
<p>In order to achieve this you need to do the following steps:</p>
<p>1. Add a select widget to your Webform</p>
<div style="padding-top: 10px;"><a rel="attachment wp-att-9089" href="http://xebee.xebia.in/2011/06/14/drupal-webform-add-a-dynamic-select-option-list/webform_from-2/"><img class="alignnone size-large wp-image-9089" title="webform_from" src="http://xebee.xebia.in/wp-content/uploads/2011/06/webform_from1-1024x457.png" alt="" width="639" height="285" /></a></div>
<p>2. Create a custom Webform module ( webform_custom ) with the following files.</p>
<p><!-- p { margin-bottom: 0.08in; } --></p>
<ul>
<li><strong>webform_custom.info</strong> – as the name suggest contains the info of the module</li>
<pre class="brush: php; title: ; notranslate">
name = Webform Custom
description = Provides custom functionality for the Webform
core = 6.x
project = &quot;webform_custom&quot;
package = Other
</pre>
<li><strong>webform_custom.module</strong> – this file will contain the code that will generate our dynamic options list, for now just keep this file empty</li>
</ul>
<p>3. Active you custom module from 	<em><strong>Administer → Site building → Modules</strong></em></p>
<p>4. The following hook adds another item for “Load a pre-built option list” menu in Webform's select 	form component. This hook will go into the module file:</p>
<pre class="brush: php; title: ; notranslate">
function webform_custom_webform_select_options_info()

{

     $items = array();

     if (function_exists('_webform_get_dates'))
     {

          $items['training_dates'] = array(

       'title' =&gt; t('Training class dates'),

        'options callback' =&gt; '_webform_get_dates',

        );

   }

   return $items;

}
</pre>
<p>The result of the above function will add the following item in the select form component drop-down:</p>
<div style="padding-top: 10px;"><a rel="attachment wp-att-9105" href="http://xebee.xebia.in/2011/06/14/drupal-webform-add-a-dynamic-select-option-list/prebuilt-option-list-2/"><img class="alignnone size-full wp-image-9105" title="prebuilt-option-list" src="http://xebee.xebia.in/wp-content/uploads/2011/06/prebuilt-option-list1.png" alt="" width="631" height="138" /></a></div>
<p><!-- p { margin-bottom: 0.08in; } --></p>
<p>As you have noted already we still do not have the data yet. No worries!!</p>
<p>The following code fetches the data from the database and returns a list of all dates for a particular node/training class but you can return whatever you want as long as its an array:</p>
<pre class="brush: php; title: ; notranslate">
function _webform_get_dates()

{

   $dates = array();

   $node_id = arg(1);

   $select = db_query(db_rewrite_sql(&quot;

              SELECT t.nid, t.field_training_date_value as tdate

              FROM {content_type_training_class} c, {node} n

              WHERE c.nid='$node_id'

              and c.nid=n.nid

              ORDER BY field_training_date_value&quot;));

    while ($date = db_fetch_object($select)) {

     $td = $date-&gt;tdate;

     $dates[$td] = $td;

   }

  return $dates;

}
</pre>
<p>5. Now go back to the Webform select form component and choose the 'Training class dates' option from the “Load a pre-built option list” dropdown and save the field.</p>
<p>You can do a lot of customization with these hooks, which may not be possible to do via Drupal's admin interface. See the full list of Webform hooks <a title="here" href="http://api.lullabot.com/group/webform_hooks/7" target="_blank">here</a>.</p>
<p>That's it folks!!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/06/14/drupal-webform-add-a-dynamic-select-option-list/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>JBoss Drools &#8211; Performance and Memory Internals</title>
		<link>http://xebee.xebia.in/2011/06/10/jboss-drools-performance-and-memory-internals/</link>
		<comments>http://xebee.xebia.in/2011/06/10/jboss-drools-performance-and-memory-internals/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 20:32:16 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[JBoss]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=9025</guid>
		<description><![CDATA[The application I am working on nowadays extensively uses JBoss Drools. The application deals with lots of objects on which complex logic is applied in sequence. This part has been developed using JBoss Drools. The keywords here are "lots of objects" and "complex logic in sequence". These two keywords, when found together, often cause menace [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">The application I am working on nowadays extensively uses JBoss Drools. The application deals with lots of objects on which complex logic is applied in sequence. This part has been developed using JBoss Drools. The keywords here are "lots of objects" and "complex logic in sequence".</p>
<p style="text-align: justify;">These two keywords, when found together, often cause menace for developers.</p>
<p style="text-align: justify;">However, few days back, when I profiled the application, I was a bit amazed to see that "complex logic" on "lots of objects" was not taking that much time. And trust me, this is not what I was expecting. Before profiling, I was almost sure that this "logic on lots of objects" thing is the bottleneck in application's performance. So, the discovery of it being efficient was a bit shocking.</p>
<p style="text-align: justify;">Ok, I accept it. Its fast. The profiler can not be wrong. But how is it that fast?</p>
<p style="text-align: justify;">To get an answer to this question, I explored JBoss Drools internals. How JBoss Drools actually works? What's the thing that brings in this efficiency in JBoss Drools? I got few answers when I explored how it works. I will share my understanding of its architecture which, I think, makes it memory and performance efficient.</p>
<p style="text-align: justify;">JBoss Drools uses Rete's Algorithm to execute rules. Rete's algorithm is an efficient pattern matching algorithm.</p>
<p style="text-align: justify;">JBoss Drools has its own implementation of Rete's Algorithm. A rule in Drools is represented by a Rete tree.<span id="more-9025"></span> A Rete tree consists of nodes. These nodes are mostly conditional evaluations. Everything in a Drools rule is represented by a Rete tree node. Apart from conditional nodes, the Rete tree also consists of AND nodes, OR nodes and start/end nodes ( and few other types of nodes as well).</p>
<p style="text-align: justify;">The main part of the algorithm is the creation of the Rete tree. Whenever a fact(object) is inserted in the Drools engine, a Rete tree is created. The creation of this Rete tree is done by some intelligent algorithm. The Rete tree, once created executes in almost no time over the facts(objects) and gives the result. Most of the time is went into creating the Rete tree rather than executing it.</p>
<p style="text-align: justify;">This is something that I have also experienced during debugging. Whenever a fact is inserted into the Drools session, it takes a bit of time. However, the firing of rules is almost instantaneous.</p>
<p style="text-align: justify;">So, the way this Rete Algorithm has been implemented inside Drools accounts for its efficiency. But, the million dollar question is (a million is too much, but its just a quote), what will happen to the JBoss Drools efficient Rete Algorithm when "LOTS OF OBJECTS" will come into picture?</p>
<p style="text-align: justify;">The answer, I think, lies in two techniques that Drools uses to store nodes. Node Sharing and Node Indexing.</p>
<p style="text-align: justify;">Drools caches nodes while building Rete’s tree which is known as Node Sharing. Whenever a new node is created, its checked whether there is an equivalend node already present in the cache. If an equivalent node is found in the cache, the cached node is used instead and the new node is discarded. This makes Drools memory efficient.</p>
<p style="text-align: justify;">Drools keeps a hashtable of the object properties and Rete Tree Nodes .It is known as Node Indexing and is used to avoid evaluating same conditions multiple times. Node Indexing speeds up the propagation of nodes in the Rete Network which accounts for high performance of  the Drools engine.</p>
<p style="text-align: justify;">The in depth analysis of Rete Tree creation and node propagation in the Rete Network tells that the way rules are written might also effect the performance, as it directly impacts the propagation in Rete Tree. Rules, written in intelligent way can drastically reduce the number of nodes in the Rete Tree, thus, further increasing the performance.</p>
<p style="text-align: justify;">So, these techniques helps Drools to process large number of objects efficiently. What I have seen, is that, increasing number of objects in Drools hardly effects the total time taken to execute it.</p>
<p style="text-align: justify;">I still need to explore how to write efficient rules, however, it looked very logical and impressive when I saw how it is done. I will try to come out with one more post which explains efficient Rule writing.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/06/10/jboss-drools-performance-and-memory-internals/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Accessing Crowd with Python and enabling SSO</title>
		<link>http://xebee.xebia.in/2011/05/21/accessing-crowd-with-python-and-enabling-sso/</link>
		<comments>http://xebee.xebia.in/2011/05/21/accessing-crowd-with-python-and-enabling-sso/#comments</comments>
		<pubDate>Sat, 21 May 2011 09:08:35 +0000</pubDate>
		<dc:creator>Gaurav Kohli</dc:creator>
				<category><![CDATA[Crowd]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[crowd]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sso]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8816</guid>
		<description><![CDATA[What we are trying to have here is a python client which can talk to Crowd and be part of the Crowd SSO (Single sign-on)  along with other applications written in Java/.NET[1]. This is possible because of the SOAP &#38; REST API's which the Crowd exposes. In our organization we are still using Crowd 2.0.6, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">What we are trying to have here is a python client which can talk to Crowd and be part of the Crowd SSO (Single sign-on)  along with other applications written in Java/.NET[<a href="#1">1</a>]. This is possible because of the SOAP &amp; REST API's which the Crowd exposes. In our organization we are still using Crowd 2.0.6, so I would be explaining only about how to use  SOAP API's and not  the REST API's.</p>
<p style="text-align: left;">Crowd is a application from Atlassian world which provides you a framework for single sign-on and centralized authentication. And underneath it can connect to a lot of User Directories like LDAP, Microsoft Active Directory, SUN and Fedora Directories and many more. So for all your enterprise applications, you can use Crowd to manage all the User details, and it greatly simplifies the thing as now there is just one location where all the information is stored.</p>
<p style="text-align: left;"><span id="more-8816"></span></p>
<p style="text-align: left;">The Crowd's SSO capabilities enables you to log into one website and move between your other web applications without having to log in repeatedly. This provides a lot better User interaction and since all the applications are internal to one organization, it also doesn't make sense for each user to sign into each one of them again and again, even though he is using a same browser.</p>
<p style="text-align: left;">Now most of the SSO implementations are based on the concept of storing some HTTP cookies, since you need some way to acknowledge who is coming to your website and same is with Crowd Server. Usually everyone stores some authentication token in cookies which each application can use and have it validated by the main SSO server. Now the only problem with HTTP cookies is that only the application of same domain can have access to it. So now there could be two possibilities, either our python client is in the same domain as Crowd, in which case we can use the Crowd domain information or we are in some other domain and we will have to explicitly set our own cookie.</p>
<p style="text-align: left;">Let's get into some code now.</p>
<p style="text-align: left;">The code is written in python, but it is pretty simple SOAP usage, so you could  write the same thing in any language, you only need some basic SOAP understanding .</p>
<p style="text-align: left;">We start with installing the crowd server first. Once we have the crowd server, we can access the SOAP wsdl at http://localhost:8095/crowd/services/SecurityServer?wsdl [<a href="#2">2</a>]. The WSDL can help you understand all the functions which you can call on the Crowd Server. I have currently used just 4 functions: authenticateApplication, authenticatePrincipal, isValidPrincipalToken and getCookieInfo. For integration with Crowd application server, we first need to create a application from within Crowd server and specify the name, password and the ip address from where we would be using the application. This is just the snippets and full  code is uploaded on github[<a href="#3">3</a>]</p>
<p style="text-align: left;">We use Python Suds module for talking to the Crowd SOAP endpoint. We create a soap client using "Client(self.wsdlurl,doctor=doctor)"  and we  pass in the url for the Soap Wsdl. The second parameter which you see is the Suds way to clean the wsdl xml. The Crowd wsdl has some namespace problems for which we create a ImportDoctor which fixes the missing namespace for few of the elements in WSDL.</p>
<pre class="brush: python; title: ; notranslate">
class CrowdPy:
	def __init__(self):
		cfg = ConfigParser()
		cfg.read('crowd.properties')
		self.appname = cfg.get('default','application.name')
                #.... Read all the properties from the Configuration File

        #Use Pythin Suds module to create a SOAP client
	def createClient(self):
                # The Crowd Wsdl has some problems in namespace, so we need to patch thoes
		patches = { &quot;urn:SecurityServer&quot;: [&quot;http://authentication.integration.crowd.atlassian.com&quot;}
		doctor = dr.ImportDoctor()

		# Patch all the imports into the proper targetNamespaces
		for targetNamespace in patches:
		    for nsimport in patches[targetNamespace]:
			imp = dr.Import(nsimport)
			imp.filter.add(targetNamespace)
			doctor.add(imp)
                # Creating the Suds Client
		self.client = Client(self.wsdlurl,doctor=doctor)
		return self.client
</pre>
<p>Using the client we have to authenticate the application using the application name and the password specified when a new application was added in Crowd. The Crowd internally uses this information along with the ip address from where the request is coming to validate the application and then returns a application authentication token which we would use further on to authenticate Principal (User)</p>
<pre class="brush: python; title: ; notranslate">
	def authenticateApplication(self):
		auth_context = self.client.factory.create('ns1:ApplicationAuthenticationContext')
		auth_context.name = 'application name specified in crowd'
		auth_context.credential.credential = 'application password specified in crowd'
		self.token = self.client.service.authenticateApplication(auth_context)
		return self.token
</pre>
<p>Now we call the authenticatePrincipal function to authenticate the User using the application authentication token and the user credentials. This would return a user authentication token which we can save in the cookies. This is perfectly save, as this is valid only if used along with the application authentication token and also from the same machine ip address.</p>
<pre class="brush: python; title: ; notranslate">
	def authenticatePrincipal(self,username,passwd):
		user_context = self.client.factory.create('ns1:UserAuthenticationContext')
		user_context.application = 'application name specified in crowd'
		user_context.name = username
		user_context.credential.credential = passwd
		self.user_token = self.client.service.authenticatePrincipal(self.token,user_context)
		return self.user_token
</pre>
<p>So at this moment we have the user authenticated by Crowd, but where is the SSO ? For having the SSO feature, we have to do two things before even asking for username/password from user, first whenever we need the user authentication we need to check if the user was already authenticated by some other application. For doing that we have to check for cookies with key "cookie.token_key" and the value of the this key is the user authentication token saved by some other application. I would be telling how to validate this token in a minute. In case we don't have such a cookie in browser, we then ask username/password and call the function authenticatePrincipal specified above and then save the user token back into a new cookie.</p>
<p>And here is the code to validate the cookie in case it was already there in the browser. We have to use the user authentication token from the cookie and the application token and along with that we pass the Validataion Factors, which should have the correct IP address where the proxy application is running. In my case both the proxy and the Crowd server were on the same machine, so I have used "127.0.0.1"</p>
<pre class="brush: python; title: ; notranslate">
       def isValidPrincipalToken(self,user_token):
		vf1 = self.client.factory.create('ns1:ValidationFactor')
		vf1.name = 'remote_host'
		vf1.value =  '127.0.0.1'
		vf = [vf1]
		isValid = self.client.service.isValidPrincipalToken(self.token,user_token,vf)
		return isValid
</pre>
<p>So in this way either the application uses the cookie saved by some other application in the browser and have it validated by the Crowd server, or ask the user for username/password and have it authenticated from Crowd and creates a new cookie in the browser for all the other applications within the same SSO group to use. You just have to make sure the domain name in the cookie is same for all the applications.</p>
<p>1. <a title="Java Integration Libraries" name="1" href="http://confluence.atlassian.com/display/CROWDDEV/Java+Integration+Libraries">Java Integration Libraries</a></p>
<p>2. <a name="2" href="https://github.com/gauravkohli/Crowd-python/blob/master/Crowd-wsdl.xml">Sample Crowd 2.0.6 Soap Wsdl</a></p>
<p>3. <a name="3" href="https://github.com/gauravkohli/Crowd-python">Crowd Python Code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/21/accessing-crowd-with-python-and-enabling-sso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>File Drop Handler in JavaFx</title>
		<link>http://xebee.xebia.in/2011/05/18/file-drop-handler-in-javafx/</link>
		<comments>http://xebee.xebia.in/2011/05/18/file-drop-handler-in-javafx/#comments</comments>
		<pubDate>Wed, 18 May 2011 03:41:16 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[drag]]></category>
		<category><![CDATA[drop]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8944</guid>
		<description><![CDATA['Drag and drop' is not supported in a standard way in JavaFx 1.3.1 . However, there are some functions that work with Swing toolkit which enable the target resource to know that something thing has been dropped over it. Several objects can be dragged simultaneously and the objects can be in different formats like normal [...]]]></description>
			<content:encoded><![CDATA[<p>'<strong><span style="color: #000000;">Drag and drop</span></strong>' is not supported in a standard way in JavaFx 1.3.1 .</p>
<p><strong>However</strong>, there are some functions that work with Swing toolkit which enable the target resource to know that something thing has been dropped over it.</p>
<p>Several objects can be dragged simultaneously and the objects can be in different formats like normal .txt files, png's or pdf's e.t.c.</p>
<p>When you drag the browser link, the text associated with the link is placed in the buffer.</p>
<p><a rel="attachment wp-att-8955" href="http://xebee.xebia.in/2011/05/18/file-drop-handler-in-javafx/dropsampleimg/"><img class="size-full wp-image-8955 alignleft" title="dropSampleImg" src="http://xebee.xebia.in/wp-content/uploads/2011/05/dropSampleImg.png" alt="" width="400" height="231" /></a></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p>We are going to implement the same with dragging a file/folder from the  OS and dropping over an JavaFx component, which is a swing component  wrapped in JavaFx.</p>
<p><span id="more-8944"></span></p>
<p>Let's see how our basic <span style="text-decoration: underline; color: #000080;"><strong>Main.fx</strong> </span>looks like:</p>
<pre class="brush: java; title: ; notranslate">

import javafx.scene.Scene;
import java.io.File;
import java.lang.System;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.swing.JTextArea;
import javafx.ext.swing.SwingComponent;

public class Main {

  public var scene: javafx.scene.Scene;
  public-read var dashedImageView: ImageView;
  var customDropBoxTextArea: JTextArea;

  init {

     customDropBoxTextArea = new JTextArea(15, 30);
     customDropBoxTextArea.setEditable(false);
     customDropBoxTextArea.setOpaque(false);

     dashedImageView = ImageView {
     image: Image {
         backgroundLoading: true;
         url: &quot;{__DIR__}dashedbox3.png&quot;
         preserveRatio: true;
      }
     }

     scene = Scene {
         width: 431
         height: 247
         content: [dashedImageView, SwingComponent.wrap(customDropBoxTextArea)]
      }
    }

   }

   function run(): Void {
   var design = Main {};

    javafx.stage.Stage {
        title: &quot;Drop File Sample App&quot;
        scene: bind design.scene;
        resizable: false;
        onClose: function() {
        System.exit(0);
     }
   }
 }
</pre>
<p>Here, as you can see, <span style="color: #000080;">JTextArea</span> is essentially a swing component which we set as opaque just to show the underneath nice image below it.</p>
<p>It is wrapped using SwingComponent.wrap(customDropBoxTextArea) to be used as a node in the scene.</p>
<p>Now, we create a handler for listening to the DropEvent.</p>
<p>You can have desired implementation of this handler according to your requirements like highlighted border, effects etc.</p>
<p>View/download the source code from <strong><a rel="attachment wp-att-8950" href="http://xebee.xebia.in/2011/05/18/file-drop-handler-in-javafx/drophandler/">DropHandler.java </a></strong></p>
<p>After that we need a listener which triggers the 'fileDropped' method each time a file or folder is dragged and dropped over it.</p>
<p><span style="text-decoration: underline; color: #000080;"><strong>DropListener.java</strong></span></p>
<pre class="brush: java; title: ; notranslate">
public interface DropListener {

 public  void filesDropped(java.io.File[] files);
 }
</pre>
<p>That's all, Now all what you need to do is to add this listener to your Main.fx class so that the event propagates to your fx code.</p>
<p>Append the following lines of code just after we defined the scene. I have also added a textBox, that is shown in the output screenshot above and bind the text of my customDropBoxTextAreawith it to make it more usable.</p>
<pre class="brush: java; title: ; notranslate">
var listener = DropListener {
  override public function filesDropped(files: nativearray of File): Void {
    for (i in files) {
      customDropBoxTextArea.setText(i.getCanonicalPath());
     }
  }
 }
 var fileDrop: DropFileHandler = new DropFileHandler(customDropBoxTextArea, listener);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/18/file-drop-handler-in-javafx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Analysing GIT Branching model with Kanban</title>
		<link>http://xebee.xebia.in/2011/05/15/analysing-git-branching-model-with-kanban/</link>
		<comments>http://xebee.xebia.in/2011/05/15/analysing-git-branching-model-with-kanban/#comments</comments>
		<pubDate>Sun, 15 May 2011 15:45:02 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[GIT]]></category>
		<category><![CDATA[Kanban]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8899</guid>
		<description><![CDATA[We have been working with GIT branching model for a long time now. GIT allows you to maintain different branches in your codebase. It is a developer's choice when to make/merge branches. We, as a team decided on certain guidelines as to when make/merge branches. Apart from the user story specific branches, we had Development [...]]]></description>
			<content:encoded><![CDATA[<p>We have been working with GIT branching model for a long time now. <a href="http://git-scm.com/">GIT</a> allows you to maintain different branches in your codebase. It is a developer's choice when to make/merge branches. We, as a team decided on certain guidelines as to when make/merge branches. Apart from the user story specific branches, we had <em>Development </em>and <em>Master</em>. The concept of <em>Development </em>branch was introduced to keep our <em>Master </em>stable and be in a state to give release-ready builds. All the user story branches are merged into <em>Development</em>. <span id="more-8899"></span></p>
<p>Just to have an idea, here is how our Kanban board looks like -</p>
<p><img src="http://xebee.xebia.in/wp-content/uploads/2011/05/kanban-board.png" alt="Kanban Board" width="675" /></p>
<p>So for each story, we made a remote branch in GIT. To make is simpler and globalized, we named all branches as US-XXXX. The user story branches were created from <em>Development</em>, so that we always have the updated code. The developers, either individually or in a pair worked on user stories. The story moves from left to right. Once it reaches the <em>Acceptance Done</em> column, it's time to merge them to a standard branch named <em>Developmen</em>t. Finally, the <em>Development </em>branch is being merged into <em>Master </em>whenever there is a Release.</p>
<p>Over the time we realized there are some good things that comes with this approach.</p>
<ol>
<li> <strong><em>Master </em>always remain stable:</strong> With this approach, we were sure that we won't make any commit directly on master. We have enough buffer to check if our commit is not breaking any of the tests.</li>
<li><strong>Bugs:</strong> Whenever there is a new feature in the product, it is added as a user story. With the above approach we make a dedicated branch for that user story. So for any bug related to the user story, we always know which branch to work upon. So the bug can be worked upon in isolation.</li>
<li><strong>Test cases for each user story: </strong>Stories are not moved in <em>Development Done</em> untill there are Unit Test cases for it. So this way we make sure that the test cases are present on the branch only. The branch is fully testable before moving into the next column.</li>
<li><strong>Parallel development</strong>: Developers can work on work on their user story in parallel to others, which is  independent of other changes/modifications in the application.</li>
</ol>
<p>Apart from these positive points, there were some issues also with this approach.</p>
<ol>
<li><strong>Story might get blocked:</strong> This is the most common problem we faced while following this approach. A practical use case is - Developer A working on a user story US-AAAA, and the story is currently in <em>Development</em> column. Developer A does heavy refactoring which affects all stories related to US-AAAA. A related story say US-BBBB is being picked by Developer B. The refactoring done by Developer A is now required by Developer B. But Developer B won't have this refactoring untill the story reaches <em>Acceptance Done</em> column. Because after this column, the story will be merged into <em>Development</em>. So for that particular time, US-AAAA remains blocked.</li>
<li><strong>Merge conflicts:</strong> Whenever a story is being merged with 'Development', we often face merge conflicts. The reason is pretty clear - All stories have their own branches, which may have common files/classes being modified. So when they are merged, GIT is not able to able auto-merge those changes.</li>
</ol>
<p>We are using this approach for a good amount of time now, and we feel that the good things that we are getting with this approach is making our development smoother and efficient. Although we do come across some hurdles with this approach, but that's an opportunity to learn and adapt!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/15/analysing-git-branching-model-with-kanban/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby version management using RVM</title>
		<link>http://xebee.xebia.in/2011/05/12/ruby-version-management-using-rvm/</link>
		<comments>http://xebee.xebia.in/2011/05/12/ruby-version-management-using-rvm/#comments</comments>
		<pubDate>Thu, 12 May 2011 12:29:56 +0000</pubDate>
		<dc:creator>Vikas Gupta</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RVM]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8882</guid>
		<description><![CDATA[I had just started exploring Ruby and Rails and I came across a nice tool, RVM (Ruby Version Manager), which allows you to install and manage multiple versions of Ruby on the same machine. Although RVM works on Linux based systems only, but windows users can accomplish the same feat with Pik. RVM not only [...]]]></description>
			<content:encoded><![CDATA[<p>I had just started exploring Ruby and Rails and I came across a nice tool, RVM (Ruby Version Manager), which allows you to install and manage multiple versions of Ruby on the same machine. Although RVM works on Linux based systems only, but windows users can accomplish the same feat with <a href="Pikhttps://github.com/vertiginous/pik">Pik</a>. RVM not only helps in managing different versions of Ruby on the same machine, but it also facilitates working with different combinations of Ruby and Rails. In this blog, I will share my experience of installing RVM and using it to manage different Ruby and Rails versions.<br />
<span id="more-8882"></span><br />
<strong>Installing RVM</strong></p>
<p>To install RVM, use the following command</p>
<pre>bash &lt; &lt;(curl -s https://rvm.beginrescueend.com/install/rvm)</pre>
<p>The above command will download and install RVM. RVM will get installed in the <strong>.rvm</strong> folder inside the user's home directory. After installing RVM, please follow the instructions at<a title="https://rvm.beginrescueend.com/rvm/install/" href="https://rvm.beginrescueend.com/rvm/install/"> https://rvm.beginrescueend.com/rvm/install/</a> to complete and test the installation. While referring the instructions at this page, please keep in mind the difference between <code>.bash_profile </code>and <code>.bashrc</code> as it will come to use while executing point no. 2 of the installation steps. The main difference between <code>.bashrc</code> and <code>.bash_profile</code> is that while <code>.bash_profile</code> is executed for login shells, <code>.bashrc</code> is executed for interactive non-login shells. So, use the appropriate file while following the installation steps.</p>
<p>You can install RVM for all users also. For that, please refer to the RVM documentation.</p>
<p>In order to make RVM work properly, please ensure that operating system has all the dependencies mentioned required by RVM. To get the list of dependencies is very easy. Just type <code>rvm notes</code> and you will be displayed a list of dependencies which needs to be installed.</p>
<p><strong>Installing Ruby with RVM</strong></p>
<p>Once you have RVM installed, installing ruby with it fairly straightforward. Typing the following two commands would install Ruby versions 1.8.7 and 1.9.2 respectively.</p>
<p><code>rvm install 1.8.7</code></p>
<p><code>rvm install 1.9.2</code></p>
<p>Now, you have installed two version of Ruby and want to make one of them (say 1.9.2) as default, then use the following command</p>
<p><code>rvm --default use 1.9.2</code></p>
<p><code>ruby -v</code> will tell which Ruby is the default one now.</p>
<p><strong>Managing Gems with RVM</strong></p>
<p>Ruby programs are typically distributed via gems, which are self-contained packages of Ruby code. Since gems with different version numbers sometimes conflict, it is often convenient to create separate gemsets, which are self-contained bundles of gems. In particular, Rails is distributed as a gem, and there are conflicts between Rails 2 and Rails 3, so if you want to run multiple versions of Rails on the same system you need to create a separate gemset for each:<br />
<code><br />
rvm --create 1.8.7@rails2<br />
rvm --create use 1.9.2@rails3<br />
</code></p>
<p>Here the first command creates the gemset rails2 associated with Ruby 1.8.7, while the second command creates the gemset rails3 associated with Ruby 1.9.2 and uses it (via the <strong>use </strong>command) at the same time. RVM supports a large variety of commands for manipulating gemsets; see the documentation at <a title="http://rvm.beginrescueend.com/gemsets/" href="http://rvm.beginrescueend.com/gemsets/http://rvm.beginrescueend.com/gemsets/">http://rvm.beginrescueend.com/gemsets/</a>.</p>
<p>If you want to default to Ruby 1.9.2 and rails3 gemset, then we need to use the following command:</p>
<p><code>rvm --default use 1.9.2@rails3</code></p>
<p>This simultaneously sets the default Ruby to 1.9.2 and the default gemset to rails3. Please note that there is a default gemset associated with each version of Ruby installed via RVM.</p>
<p>By the way, if you ever get stuck with RVM, help is available at your doorstep via the following commands:</p>
<p><code>rvm --help<br />
rvm gemset --help</code></p>
<p>RVM makes installing and managing Ruby and gems very easy, but, the capabilities of RVM is not limited to these. It is a fairly extensive tool and has many more features which can be explored by visiting <a title="https://rvm.beginrescueend.com" href="https://rvm.beginrescueend.comhttps://rvm.beginrescueend.com">https://rvm.beginrescueend.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/12/ruby-version-management-using-rvm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Need of Agile Architect in Scrum Team</title>
		<link>http://xebee.xebia.in/2011/05/11/the-need-of-agile-architect-in-scrum-team/</link>
		<comments>http://xebee.xebia.in/2011/05/11/the-need-of-agile-architect-in-scrum-team/#comments</comments>
		<pubDate>Wed, 11 May 2011 14:36:25 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[agile architect]]></category>
		<category><![CDATA[agile architect role]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8822</guid>
		<description><![CDATA[Nobody can question if you implement the Agile practices in Waterfall projects. If you talk about XP practices in general, they are not really specific about any methodology. Pair-programming, CI, TDD etc all make sense in any methodology. However one of the key difference is – Waterfall doesn’t bound you in anything. It also doesn’t [...]]]></description>
			<content:encoded><![CDATA[<p>Nobody can question if you implement the Agile practices in Waterfall projects. If you talk about XP practices in general, they are not really specific about any methodology. Pair-programming, CI, TDD etc all make sense in any methodology. However one of the key difference is – Waterfall doesn’t bound you in anything. It also doesn’t say that the least engineering or project execution practices are these or those or that one except defining 4 phases of the methodology. So in my experience of 10 years with Waterfall some people used to adopt some good practices and some others didn’t. It used to be person dependent case how a Project Manager would like to execute a project.</p>
<p><span id="more-8822"></span></p>
<p>Scrum and Agile in general took some common-sense based practices formally which could be a beginning point of every project. Ceremonies are defined because they made a lot of sense and also provided a rhythm and discipline to the team (the way brushing teeth is a daily ceremony for everybody). You can do away with them if you want to but you need to have enough valid reasons to say that in your context it’s not making sense. So Scrum defines ceremonies, roles, project execution cycle in very formal manner. On top of it you need to apply the basic Agile principle “Inspect and Adapt” as you move further. So you can do the changes which make sense to you and that’s how you evolve some practices which are general or are project specific.</p>
<p>In this context, I feel the roles mentioned in my <a href="http://xebee.xebia.in/2011/05/03/missing-roles-in-scrum-and-holistic-success-of-the-software-projects/">previous blog</a> like Agile Architect make a lot of sense. We cannot get away with “get them whenever you need” the way we did earlier in Waterfall. The reason is “whenever” like "it depends" for many people becomes very confusing.</p>
<p>Further even these cases are not generally mentioned in any Scrum literature and to everybody in the world. From the outset it looks like that Scrum just works with generalist-specialist kind of people and it doesn't have any scope for any specialist and again it’s on need basis. However most of the time people don’t get to know those needs and get confused with just generalist team idea.</p>
<h2>Why do we need specialist also in the team?</h2>
<p>I feel it’s a chicken and egg kind of situation. The reason why we want specialized people to be “team member” is just because  of our bad experience with Waterfall world in which Architects used to work in their ivory tower where they couldn’t see the battle-field in real sense. That kind of architect culture didn’t work as Architects were getting out of touch as they grew in terms of the experience gradually.</p>
<p>In the beginning it looks like a great solution where specialist is no more a specialist but just a specialist-generalist which means based on their interest and capabilities people can give suggestions. However practically I have seen it failing not from emerging design point of view but in a sense of having a balance between emerging architecture and business+non-functional requirements. Sometimes they go tangential because of following reasons:</p>
<ul>
<li>As everybody is a generalist-specialist and the team is responsible for emerging architecture, the accountability doesn’t remain on one person. In such kind of situations where everybody is responsible for everything, it implies nobody is accountable in real sense.</li>
<li>There is a mix of responsibilities now. The guy is deep down developer also and has some iota of responsibility from architecture point of view too. So the boundary is very thin here. You never know, when an architect is going to lose the sense of looking out from third-person point of view.</li>
<li>When everybody is in deep mess in project development, the focus of every generalist-specialist is to get out of the mess. How you do that- doesn’t matter much sometimes. So that eye of somebody who continues to keep a tab on balancing both emerging architecture and non-functional requirements can go for a toss and you will not know when it really happened.</li>
</ul>
<p>All above cases are based on experience with real projects and with very experienced teams.</p>
<p>So making an architect a full-fledged developer doesn’t work in my view. Instead, I feel it will work when the focus factor for persons’ availabilty is less than 1 for project development. At the same time, it’s important to have some backlog from architecture point of view on which that person works along with multiple team-members for achieving certain non-functional goals.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/11/the-need-of-agile-architect-in-scrum-team/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex Validator : Custom Validator with multiple Listeners</title>
		<link>http://xebee.xebia.in/2011/05/10/flex-validator-custom-validator-with-multiple-listeners/</link>
		<comments>http://xebee.xebia.in/2011/05/10/flex-validator-custom-validator-with-multiple-listeners/#comments</comments>
		<pubDate>Mon, 09 May 2011 21:43:15 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8855</guid>
		<description><![CDATA[In this video we are going to learn how to write a custom validator for multiple listeners. The video explains the flexible flex Validator api, that can be easily extended to your requirements We start with first looking at what we already have as basics Validators and how we can extend it to have custom [...]]]></description>
			<content:encoded><![CDATA[<p>In this video we are going to learn how to write a custom validator for multiple listeners.</p>
<div>The video explains the flexible flex Validator api, that can be easily extended to your requirements</div>
<div>We start with first looking at what we already have as basics Validators and how we can extend it</div>
<div>to have custom one as per our needs by exploring the Framework code.</div>
<div><span id="more-8855"></span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><object width="425" height="344"><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/rLN9R5j46GI?hl=en&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
Attach is the source code <a href="http://xebee.xebia.in/wp-content/uploads/2011/05/TimeValidator.zip">TimeValidator</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/10/flex-validator-custom-validator-with-multiple-listeners/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When You Infer from Customer &#8211; &#8220;I Don&#8217;t Know What I Want&#8221;</title>
		<link>http://xebee.xebia.in/2011/05/09/i-dont-know-what-i-want/</link>
		<comments>http://xebee.xebia.in/2011/05/09/i-dont-know-what-i-want/#comments</comments>
		<pubDate>Mon, 09 May 2011 13:52:25 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Project Development Methodologies]]></category>
		<category><![CDATA[Project Management]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8841</guid>
		<description><![CDATA[As per our experience while working with Waterfall and Agile, upfront design doesn’t necessarily work and in all practical cases it’s rather evolved design which we need to target for. However the same may not hold true for project architecture. Though you’d like to change some of the implementation pointers in process, you'll not think [...]]]></description>
			<content:encoded><![CDATA[<p>As per our experience while working with Waterfall and Agile, upfront design doesn’t necessarily work and in all practical cases it’s rather evolved design which we need to target for. However the same may not hold true for project architecture. Though you’d like to change some of the implementation pointers in process, you'll not think on changing the structure itself completely. </p>
<p>It's a costly affair and may prompt you to rebuild the building from the scratch again. Sometimes this is the destiny of some failed software projects. And many a times, the root cause is - at the beginning of project, customer himself was not clear what he really wanted.</p>
<p><span id="more-8841"></span></p>
<p>Yesterday I had an interesting discussion with Srini. It started with me telling a story of a mentoring session I had with my mentee.</p>
<p style="text-align: center;"><strong><span style="text-decoration: underline;">Chapter I</span></strong></p>
<p>That mentor session was all about knowing each other better so that accordingly we could plan out the roadmap of the things he'd like to do in near future. I started the mentor session with a simple question – "what are your strengths as a person and a professional?"</p>
<p>This is what he said about his strengths:</p>
<ul>
<li>An      aptitude to work and pick up any latest technology</li>
<li>Happy      and friendly</li>
<li>Calm      as much as possible</li>
<li>Speaks      only when it’s needed</li>
<li>…</li>
</ul>
<p>With above mentioned points I couldn't find some worthwhile pointers. These are very generic facts and don’t give you much to ponder upon. So to know something more, I probed further and asked about his passion.  He said, "I like to work on new technologies".</p>
<p>Oh… damn!!! That was not the result I expected I thought. With that answer, still I had no clue about his real passion and strengths which could be handy for me to identify his personality traits. "If I know his true persona, I'll be able guide him in a certain direction", I thought. But at that point of time, that destination was looked too far.</p>
<p>I decided, Okay, let’s go even deeper and started asking about his college days and what all achievements he made during those years in which he could do something which he really liked the most. After some further probing this is what came out:</p>
<ul>
<li>He      was the head organizer of the tech fest held at his college and that      effort was very successful.</li>
<li>He      did a research software project so that he could transform the voice of a      person into some other voice based on already held deep research, formulas      and algorithms.</li>
<li>He      created a software project which could convert a human skull into some      recognizable human face which could to recognize the real person.</li>
</ul>
<p>I was just awestruck as I never imagined that a person with a bit of lost confidence has traits which we never knew before. From then on… I knew, I could figure out the puzzle.</p>
<p>I said, "So you should be termed as technically strong person who enjoys deep technical analysis, algos and stuff like that which for a usual developer is not the cup of tea”. He said, – "Yes!".</p>
<p>I continued, "Then don’t you think your passion is working with some challenging and deep technical stuff which deals with algorithms, deep research to know the unknown etc….?"</p>
<p>This time his face brightened up and he confidently and happily said, “Oh yeah…you are right. This is my passion!”</p>
<p>I said, "But you didn’t talk about it earlier". "Yes… but I was not sure if you are looking for that. I was rather figuring out what all things I would like to do in coming days", he said. <strong><span style="text-decoration: underline;">Interesting, I thought inside. If it can happen to him it can happen to many others.</span></strong></p>
<p style="text-align: center;"><strong><span style="text-decoration: underline;">Chapter II</span></strong></p>
<p>Back to discussion with Srini further, I continued, "It can happen to any customer also who has some vague idea about why he wants to execute a project but may not be very clear on what he really wants. So this kind of brainstorming I had with my mentee should similarly help a customer in figuring out overall objectives and the missing links of the end goals.</p>
<p>Srini agreed and he told me yet another instance…,”When we go and choose some ice-cream, sometimes we really are not sure what kind of taste we are really looking for. At those times, sometimes it’s because of others we chose a certain type of ice-cream. But confidently we are not so sure”.</p>
<p>“Similarly when we write some goals on the goal sheet given at the end of appraisal cycle, sometimes we fill the goals as they need to be filled in. Internally we may not be quite sure (as we didn’t probe deeply) if that's what we'd like to achieve in next 6 months in the organization.”, Srini continued.</p>
<p style="text-align: center;"><strong><span style="text-decoration: underline;">Conclusion</span></strong></p>
<p>So coming back again, similar to these stories, why do we expect customer to know everything at the beginning of the project? When project fails (because for instance he recognized something else in between which he never analyzed before or he comes to know it at the very end), we some time term that as customer failure and say that he didn't know what he wanted.</p>
<p>However with this analysis, I think it’s very clear that we as Consultants also didn’t try much to probe further from customer and we were just concerned and focused on the overall implementation.</p>
<p>I feel at the beginning of the project, enough time should be given both from customer and consultant’s point of view to just see what all we are trying to get from the project in overall business sense. Again that discussion doesn’t end at the beginning of project implementation. At that time of implementation, we may come to know many other pointers which may prompt us to think about project implementation from a different perspective.</p>
<p>For me, it’s important to be Agile in this perspective and weigh overall business goals continuously. If we really don’t worry at that time, chances are - the project is not used at all or not used to its potential.</p>
<p>This kind of analysis and effort provides avenues to know the business goals in real sense and also how they are related with architectural foundation of the project. With this aspect in mind, I hope we can expect to have more successful software implementations.</p>
<p style="text-align: left;"><span style="text-decoration: underline;"><strong>References</strong></span></p>
<ul>
<li><a href="http://xebee.xebia.in/2011/05/03/missing-roles-in-scrum-and-holistic-success-of-the-software-projects/">“Missing Roles in Scrum” and “Holistic Success of the Software Projects”</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/09/i-dont-know-what-i-want/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Missing Roles in Scrum&#8221; and &#8220;Holistic Success of the Software Projects&#8221;</title>
		<link>http://xebee.xebia.in/2011/05/03/missing-roles-in-scrum-and-holistic-success-of-the-software-projects/</link>
		<comments>http://xebee.xebia.in/2011/05/03/missing-roles-in-scrum-and-holistic-success-of-the-software-projects/#comments</comments>
		<pubDate>Tue, 03 May 2011 10:30:20 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[distributed agile]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8243</guid>
		<description><![CDATA[Recently I had a discussion with one of my colleagues over the definition of Agile Architect role. Scrum doesn't have any room for such role. The whole idea behind that is - just by labeling a person with a role named Architect, the person doesn't become Architect. Also architecture creation should be a collaborative effort [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had a discussion with one of my colleagues over the definition of Agile Architect role. Scrum doesn't have any room for such role. The whole idea behind that is - just by labeling a person with a role named Architect, the person doesn't become Architect. Also architecture creation should be a collaborative effort instead of defined by just single person. That's why by definition, any/all developers can contribute to shape the architecture of the application depending on their competency.</p>
<p>So the question is - why am I still talking about it? The answer lies in some scenarios I encountered while executing Scrum based projects where I felt the need of having a person with certain responsibilities and competency. In this blog, I am not just talking about the need of Agile Architects but also about some other roles which become very important for holistic success point of view.</p>
<p><span id="more-8243"></span></p>
<p><strong>Scenario 1 – To keep a tab on overall architecture and non-functional requirements</strong></p>
<p>Developers love coding and many a times they start churning out code from day 1 itself. At the beginning of project, we all talk about non-functional requirements and overall architecture. All that can go for a toss if someone doesn’t keep a tab on it. The much abused KISS principle though looks great from the outset, it also provides you a crutch to believe that things like non-functional requirements will be taken into consideration at the end. So from code functionality point of view, though we continue to talk about Continuous Integration, non-functional requirements are kept to the end. And it backfires sometimes.</p>
<p>Sometimes the entire building you created (by just believing on 'building bricks and refactoring' instead of ‘building brick and constantly looking at overall objectives and architecture’) needs to be rebuilt again as even refactoring further makes no more sense for meeting business and non-functional objectives.</p>
<p>So though the project got executed as a whole but it becomes useless. Yet again you’ll say that customer never informed about some hidden non-functional requirements. But then as Agile software service provider (ASSP) it’s your responsibility to bring that out from the customer using brainstorming and multiple questions-answers sessions. In this context I see a need of a person who has a responsibility to look at overall building all the time and doesn’t compromise on end goals. This guy can be called Agile Architect.</p>
<p><strong>Scenario 2 – Challenges of Product Owner Role</strong></p>
<p>As working in Agile environment is a complete paradigm shift for anybody working in Waterfall model before, Agile adoption poses a similar kind of challenge for Product Owner role as it does for a developer role. However in case of Product Owner, the problems become much more visible as they impact overall project. Let's take a look at some problems which you also might be able collate within your own project:</p>
<ul>
<li>No <a href="http://blog.xebia.com/2009/06/the-definition-of-ready/">READY</a> Sprint backlog in the Sprint planning meeting</li>
<li>Not enough information in the user-stories.</li>
<li>User stories too big to finish in one sprint.</li>
<li>The project roadmap is not clearly defined. Team has no      clear idea where does their current Sprint stand in whole roadmap.</li>
<li>PO doesn’t have enough technical background to execute      technical project, for instance building the backbone for importing data      files.</li>
<li>Similarly sometimes PO comes from a technical      background and you miss entire business vision, thinking and      farsightedness.</li>
</ul>
<p>Sometimes these problems come because of paradigm shift from Waterfall to Agile and sometimes they might come even from experienced Agile organization too based on the PO's capability. Irrespective of the reasons mentioned, most of the times, we say it’s the problem from PO end and customer should fix it. Sometimes, customer also doesn’t find any sure-shot solution to resolve it. Now one approach is – you continue the project as it is and as a result team continues to suffer. Projects may survive this problem but many times they don’t.</p>
<p>Agile software service provider (ASSP) can conveniently term it as a customer failure. But in that way we tend to forget that ASSP has a big stake in customer’s success or failure. It just doesn’t work if you just take the onus of success and put failure either under the wrap or attribute it as customer failure.</p>
<p>There is another approach to handle this situation. ASSP can send someone to help the product owner for figuring out some of the identified problems and in that way contribute towards project success. He doesn't take the role of Product Owner but does assists him with Sprint planning, release planning, making user-stories READY for Sprint backlog. This guy should have techno functional background which is easier to come from ASSP side as most of the technical people grow towards management roles.</p>
<p><strong>Scenario 3 – Program Management and not just Project Management</strong></p>
<p>One of the best practice and to me a philosophy to learn from Agile world is continuous integration. It came into picture just because it was very difficult to integrate at the very end and things used to fall apart at the time of integration. So instead of integrating at the end we started doing it more frequently.</p>
<p>In many situations, multiple ASSPs are part of a big Program (cluster of multiple projects to achieve a set of goals) in which each vendor focuses on to finish their own work. As multiple project teams deliver output at different point of view, the end-to-end integration of multiple applications also becomes a big challenge.</p>
<p>In such situations, most of the times, ASSP just cares about the success of their own project. So it might happen that as an individual project, your project works but entire Program fails. Yet again, if you as ASSP recognize this problem early and you find yourself in a position to help out the customer, you should definitely do that. One of the solutions could be – having just one single ASSP for the entire program. However many a times, it also doesn’t work. Even if it works, Program management is still a challenge.</p>
<p>So far, I just listed one single problem from Program Management point of view but Program Management means a lot of other things to be managed from corporate governance point of view. So here I see a missing role that could assist the customer from entire program management point of view.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/03/missing-roles-in-scrum-and-holistic-success-of-the-software-projects/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Retrospective Action Points : Theory of Randomness</title>
		<link>http://xebee.xebia.in/2011/05/03/action-points-theory-of-randomness/</link>
		<comments>http://xebee.xebia.in/2011/05/03/action-points-theory-of-randomness/#comments</comments>
		<pubDate>Mon, 02 May 2011 19:07:36 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[scrum action points]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8779</guid>
		<description><![CDATA[Problem : We had taken ~ 8 action point in the previous sprint and were about to start the retrospective. So while iterating over all the action points we found that we never achieved any action points in the sprint. Now this cycle carried on till next 4-5 sprints, we kept picking up ~8 action [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">Problem : We had taken ~ 8 action point in the previous sprint and were about to start the retrospective. So while iterating over all the action points we found that we never achieved any action points in the sprint. Now this cycle carried on till next 4-5 sprints, we kept picking up ~8 action points but only managed to achieve one or two. To give you a break up of how we picked action points, We were a team of 6, there would be couple of action points for all, and everyone would pick up one or two action points based in the retrospective.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;"><span id="more-8779"></span><br />
</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">One of the reason why we believed that we could not achieve action points was not allocating time in the sprint for the action points. Since we never explicitly allocated the time for the action points in the sprint we never were able to pick it up on first place. This resulted in stacking up the action points that need to be done. Certainly this can be a demotivator as in every retrospective you end up complaining about the same thing. So we agreed on keeping some time spare for the action points.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">However the above approach also didn't work well. As most of the time stories, bugs, took over the priority. Also some points needed to be kept in mind throughout sprint execution based on distributed pairing,etc. </span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">Like this we tried various approaches like discussing the action points one of the days after the standup. Well this approach did work partially. However discussing over 8-10 action points was too time consuming plus was difficult to concentrate on all of them at once.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">So here is the actual problem we needed someone to remind us about the action points daily, but we didn't want to spend a lot of time discussing the action points. We wanted to start acting on them. Hence I developed the a application based on randomness.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">Goal : Remind us about one action points everyday.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">So here is what application does , Every time you start your machine , the application automatically starts up and will </span></span></span><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;"><strong>randomly </strong></span></span></span><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">show you one action point.</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">Following two points are very essential for the application</span></span></span></p>
<ul>
<li><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;"><strong>Randomness </strong>: 	The reason I choose random is because  if everyday when I start my 	machine I will be reminded about one of the points to be done. 	Effectively all the 6 team mates will have one action item to think 	about. Also at a time you can only work on one action point. If you 	are shown list of 8 action points chances are you are going to 	ignore the list.</span></span></span></li>
<li><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;"><strong>Start of 	Machine</strong> : This is the only time when my geeky brain still hasn't 	taken the plunge towards coding. I have sometime to think and act 	on.</span></span></span></li>
</ul>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">FlashCard is a simple application that will startup when the machine starts up. If you are connected to the internet it will read out the action point for you. Its a air application I have been using it on Windows. You can download it from  <a href="http://www.esnips.com/doc/3627e875-7cf3-4428-9a3b-ad3874ae2117/FlashCard"><a href="https://github.com/xebia/FlashCard">https://github.com/xebia/FlashCard</a></a> . Apart from the action points I have been adding a lot of todo also for me. Click on the <a href="http://xebee.xebia.in/wp-content/uploads/2011/05/Flash_Card.swf">Flash_Card</a> to see how to use</span></span></span></p>
<p><span style="color: #000000;"><span style="font-family: arial;"><span style="font-size: small;">The idea of randomness really works for me as at any point in time <strong>you have to think of only one particular task to do</strong>.</span></span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/05/03/action-points-theory-of-randomness/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Comparing AmCharts with Flex Charts</title>
		<link>http://xebee.xebia.in/2011/04/30/comparing-amcharts-with-flex-charts/</link>
		<comments>http://xebee.xebia.in/2011/04/30/comparing-amcharts-with-flex-charts/#comments</comments>
		<pubDate>Sat, 30 Apr 2011 18:59:33 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Charting]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[amcharts]]></category>
		<category><![CDATA[charts]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8757</guid>
		<description><![CDATA[In this blog, i will share my experiences with AmCharts (Third party API for Flex Charting). The requirement was to show a dataset in two different views, first was a tabular view and second was the chart view. For tabular view we simply used the Flex datagrid. For showing the same dataset in charts, we [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog, i will share my experiences with <a href="http://flex.amcharts.com/">AmCharts</a> (Third party API for Flex Charting).</p>
<p>The requirement was to show a dataset in two different views, first was a tabular view and second was the chart view. For tabular view we simply used the Flex datagrid. For showing the same dataset in charts, we first evaluated Flex charts included in the Flex SDK. (Here onwards, 'Flex Charts' would refer to the Flex Charting available in Flex SDK) It solved our purpose of showing the data, but somehow it was not appealing from a UI perspective. We all know that Flex Charts can be customized to any extent, but due to a time bound release, we were not able to implement it. <span id="more-8757"></span></p>
<p>While googling, i found many third party API for Flex Charts. But either they were complicated to use, or did not have attractive UI. I came across AmCharts, easy to use, great UI effects, customizable and easily came in client's budget.</p>
<p>To use AmCharts was pretty much simple. Below is the break down of the basic entities:</p>
<ul>
<li> Type of Chart: Our requirement was to show a column chart, so we used <a href="http://flex.amcharts.com/class_ref&lt;/li&gt; &lt;p&gt;erence/com/amcharts/AmSerialChart.html">AmSerialChart</a>. It contains the property 'dataProvider'. You can specify 'categoryField' here.</li>
<li>CategoryAxis: This is the horizontal axis.</li>
<li>ValueAxis: This is the verical axis.</li>
<li>Graphs: An array containing items of type <a href="http://flex.amcharts.com/class_reference/com/amcharts/chartClasses/AmGraph.html">AmGraph</a>, which is the series for the charts. It contains the 'valueField' property.</li>
</ul>
<p>If you have used Flex Charts, then you can see that it is very similar to Flex Charts, but AmCharts do not extend Flex Charts. Instead they are built from scratch by extending the UIComponent class.</p>
<p>There were certain factors which made us to go with AmCharts.</p>
<p>a) <strong>3D Look &amp; Feel</strong>: It's good to have 3D looks with charts. Flex charts (included in Flex SDK) do not have 3D looks. There are certain ways which you can use to get the feel but no doubt they are time consuming. But with AmCharts, you get these all ready.</p>
<p>b) <strong>Effects</strong>: Charts with showing up with some effects is something which every customer would want. With AmCharts, you get these effects. Also, you can customize these effects. Flex Charts also provides you with effects, but the quality of effects is better and that too when you don't have explicitly write code for them.</p>
<p>c) <strong>Easy Integration</strong>: Though Flex Charts are the best under this category, but integrating AmCharts was not at all a difficult job. But yes, while googling i found many third party APIs which were difficult to use and integrate.</p>
<p>d) <strong>Cost</strong>: Seeing the quality and the time it saves, <a href="http://www.amcharts.com/buy">cost</a> of AmCharts are pretty reasonable.</p>
<p>We also faced a problem with AmCharts. Our requirement was to show axis labels (title of the axis). Unfortunately there is no direct way of doing it. So the only workaround was to show Flex default Label across the Category Axis and the Value Axis. So if you are stuck with it, don't waste your time by googling on it. Just go with the above solution.</p>
<p>So, if you also want to have good UI that too in a short span of time, do give a try to AmCharts.</li>
<p>Useful links:<br />
<a href="http://flex.amcharts.com/files/getfile.php?filename=amcharts_flex_components_1.7.1.0.zip">Download</a><br />
<a href="http://flex.amcharts.com/docs">Documentation</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/30/comparing-amcharts-with-flex-charts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Take Aways from Dr. Venkat&#8217;s Session on Test First Development</title>
		<link>http://xebee.xebia.in/2011/04/26/take-aways-from-dr-venkats-session-on-test-first-development/</link>
		<comments>http://xebee.xebia.in/2011/04/26/take-aways-from-dr-venkats-session-on-test-first-development/#comments</comments>
		<pubDate>Mon, 25 Apr 2011 20:35:28 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[Extreme Programming]]></category>
		<category><![CDATA[Pair Programming]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8739</guid>
		<description><![CDATA[This Sunday (24th April) Xebia organized a session on Test First Development by Dr. Venkat. He is a well known personality in Agile and Extreme Programming field. He has authored several books and has conducted numerous workshops on several areas of Agile. The session consisted of three parts, first a question answer round, then an [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">This Sunday (24th April) Xebia organized a session on Test First Development by Dr. Venkat. He is a well known personality in Agile and Extreme Programming field. He has authored several books and has conducted numerous workshops on several areas of Agile.</p>
<p style="text-align: justify;">The session consisted of three parts, first a question answer round, then an interactive TDD workshop and then an open discussion.</p>
<p style="text-align: justify;">Several topics were discussed throughout the day and Dr. Venkat as well as the audience shared their thoughts on them. To begin with, the discussion started with the importance of creating an environment to make people do the right thing than to force them to do it. Dr. Venkat gave huge emphasis on creating a healthy environment which can motivate people. He said that forcing people to do things without letting them know "why" are we doing this, never works in longer run. People will start doing it, then slowly lose enthusiasm as they do not know the reason behind it, and after some time, they would not do it anymore. However, when we create an environment where it looks very natural to do certain things, really helps. He cited examples from his life, where he used it and it worked. The right environment can be created through leading by example and assertive communication, to name a few.<span id="more-8739"></span></p>
<p style="text-align: justify;">Then, the topic of scaling up an organization was discussed.  The problem mentioned was that, when the organization needs to scale up (grow in size by hiring more people) rapidly, it is very tough to align the new joiners with the organizations principles and ethics. When we need to grow at a great pace, we might not get people who can easily fit into the organization and we might end up hiring some unfits for the organization. Even after providing ample training to the people, sometimes they simply do not fit in. Dr. Venkat proposed two solutions to this problem by citing two different examples. He talked about organizations who simply refuse to grow until they find the best suitable people for their organization. But, they grow at very slow rate. However, there are different organizations also, which hire people who need some training/learning etc before they fit it, and, they ask these people to work in different departments of the organization and to learn and adapt how things work. He cited companies where new joiners are on probation for two years before becoming a permanent employee. So, there are pros and cons of both things and the organization will have to decide which way it wants to go.</p>
<p style="text-align: justify;">Then he started the workshop on Test First Development. The project was to create a TicTacToe game. Before starting the workshop, he talked about the strategic design and the tactical design of a system. He said that the strategic design is the high level design of any system telling about the major components doing certain things and the interaction between them. However, the strategic design does not go into the details of the implementation. On the other hand, the tactical design would be to know how exactly the component is going to work. The tactical  design contains each and every minute detail of that component. Comparing it with a real world example, he told that strategic design could be locating a restaurant in Delhi, and the strategic design can say that it is located in the South-West of Delhi. However, the tactical design will tell about each and every road, street, corner, turn and landmarks describing exactly how to reach there.</p>
<p style="text-align: justify;">Talking about test driven development, he said the strategic design can be done on a whiteboard or a piece of paper. However, the tactical design is done while developing the application through tests. He said that the TDD is of no use if you can not think of the evolving design sideways. And there came the question on design patterns. On which, he said that generally the patterns make the design complex. So, never try to insert a design into the application. Rather create a simple design first and try to see any design pattern evolving in it, insert a design pattern only if you can see it while developing it. Never try to force a design pattern into the code.</p>
<p style="text-align: justify;">There were questions about asserting void methods for which he proposed to create an internal method just for test purposes. When people objected on it by citing examples from oops principles. People also objected on the thought of changing code just for testing. To answer this question, he gave a magnificent example by citing a movie "A Few Good Men". He told that during an argument inside the court in the movie, someone quoted a rule. And then, Tom Cruise came with the rule book in his hand asking the other person to show him rules for each and everything that he did ( "You eat 3 times a day, can you show it in the rule book. Oh God, How can you eat 3 times a day when its not written in the rule book"). This was a great example and the best take away from the day. Dr. Venkat told to look around, experience thing, see people doing things and see what works and what does not instead of sticking to a rule book.</p>
<p style="text-align: justify;">The main take away of the Test First Development workshop was to always keep the mindset of developing what is needed now. Even though the audience was not a beginner one, most of them were old time TDD practitioners. Even though, the main bottleneck during workshop was found to be people thinking beyond what was needed.</p>
<p style="text-align: justify;">After the TDD workshop ended, the open discussion begun. The discussion started with mocking. People said that the Mocking code consumes a lot of code and thus decreases the readability. So, after the discussion finished, it was found that mock was not the problem, the problem was the design where Single Responsibility principle was not applied to its best.</p>
<p style="text-align: justify;">After that, the question came that the rule book says that every instance variable should be private with setters and getters. But it might not be needed and the instance variables can be simply made public. It can have to benefits, one, get rid of the extra code and make the classes shorter and more readable, two, the junit coverage increases as testing setters and getters is just foolish. He then opened up his laptop and gave a live demo of Groovy in which if a setter or getter is present, the code uses it, other wise, the variable is accessed directly. So, by citing this example, he told, that the new languages are thinking on the same lines of thoughts of developers.</p>
<p style="text-align: justify;">Then there were questions on the behavioral aspects of people which Agile can not handle on its own. The questions asked were, that, if someone is stuck in his task, and in every standup he comes up and says that he will do it today. But, he is never finished. And, the person is too egoist to ask for help. The other problems were related to pair programming where it was quoted that people often refuse to listen to the pair while pairing. Sometimes, the pair sleeps, sometimes the pair is not willing to let his partner touch the keyboard. Somebody shouts, somebody is too quiet. To this, he said that, tolerance and maturity is necessary to develop while doing Agile. But, this comes with experience, and is not easy to attain. He cited an example saying that in one of the pair programming workshops he saw a person shouting with whoever he paired. However, once he paired with a woman, who was very weak, and used to speak in a very low voice, but, was the most intelligent person of the group. Surprisingly, he told that the person remained quiet throughout the day with this lady. This was because, the lady objected to his points citing intelligent examples and asking intelligent questions in a very polite manner. So, she beat him with intelligence, not with power. But, in the end, he said, sometimes its almost impossible to correct things and then you can say to yourself that its just a job. In my home, I can do and will do things exactly the way I like, however, in a job, this might not be the case.</p>
<p style="text-align: justify;">With this, the session with Dr. Venkat came to an end. We thank him for giving us insight on so many complex and unsolved things. He is a very down to earth person with great knowledge and passion. I hope we will soon listen to him again.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/26/take-aways-from-dr-venkats-session-on-test-first-development/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Rendezvous with Dr. Venkat at Xebia</title>
		<link>http://xebee.xebia.in/2011/04/25/rendezvous-with-mr-venkat-in-xebia/</link>
		<comments>http://xebee.xebia.in/2011/04/25/rendezvous-with-mr-venkat-in-xebia/#comments</comments>
		<pubDate>Sun, 24 Apr 2011 19:50:27 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[Extreme Programming]]></category>
		<category><![CDATA[Pair Programming]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8663</guid>
		<description><![CDATA[Learning is a continuous process, and even though we practice Test First Development and Agile religiously,  there is no dearth of things to learn about them. So, keeping this in mind, Xebia organized a session by Dr Venkat Subramanium on Test First Development this Sunday(24th April) at Xebia India Office. Dr Venkat Subramaniam is the [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Learning is a continuous process, and even though we practice Test First Development and Agile religiously,  there is no dearth of things to learn about them. So, keeping this in mind, <strong>Xebia</strong> organized a session by <strong> Dr Venkat Subramanium on Test First Development </strong>this Sunday(24th April) at <strong>Xebia India Office</strong>.</p>
<p style="text-align: justify;"><strong><a href="http://www.google.co.in/search?hl=en&amp;client=opera&amp;hs=Npc&amp;rls=en&amp;channel=suggest&amp;sa=X&amp;ei=mcWKTZeCO8mrrAf48onbDg&amp;ved=0CBkQBSgA&amp;q=Dr+Venkat+Subramaniam&amp;spell=1" target="_blank">Dr Venkat Subramaniam</a></strong> <strong>is the </strong><strong>founder of Agile Developer and we, as Xebians primarily know him as the author of  "Practices of an <em>Agile</em> Developer," the first book that every Xebian gets after he or she joins the organization</strong></p>
<p style="text-align: justify;"><strong><span style="color: #000000;"><em>When you get an opportunity of meeting such a personality, whose books you read, practices you follow, its more of an opportunity for thought cleansing rather than learning techniques and processes. And this is what we experienced in the Test First Development session by Mr Subramaniam, where we discussed not only TDD, but the complete Extreme Programming in itself, along with various complex areas of Agile.</em></span></strong></p>
<p style="text-align: justify;"><span style="color: #000000;">Mr Subramanium enlightened everyone in the session</span><span style="color: #000000;"> by providing an unthinkable insight towards the various aspects of Agile.  He took all questions with great enthusiasm, be it regarding technology, process,  agile or other concepts like TDD, general programming practices, refactoring, designing,  importance of courage and maturity in a programmer's life and much more like :<span id="more-8663"></span></span></p>
<blockquote style="text-align: justify;">
<ul>
<li><strong>What to do and how to go about it in a tech world</strong></li>
<li><strong>How creating an environment is more effective than a training itself</strong></li>
<li><strong>Quantity Vs Quality while scaling up</strong></li>
<li><strong>Money and Reputation in a programmer's life</strong></li>
<li><strong>Need of "Taking a Stand" whenever required</strong></li>
<li><strong>Integration and Acceptance testing</strong></li>
</ul>
</blockquote>
<p style="text-align: justify;"><span style="color: #000000;">Thereafter, we had a highly interactive </span>TDD <span style="color: #000000;">workshop session where with an example of  a basic TicTacToe game, he demonstrated the best practices  of development using positive, negative and exception tests and describing what role they play in keeping your design good thereby also introducing a canary effect to your early stages of coding.</span></p>
<p style="text-align: justify;"><span style="color: #000000;">We saw in front of us how to develop and maintain the inertia using a basic notepad task list which can keep us motivated throughout the development.<br />
</span></p>
<p style="text-align: justify;"><span style="color: #000000;">The Principles like <strong>YAGNI </strong>(You Aren't Gonna Need It), <strong>DRY </strong>(Don't Repeat Yourself) and <strong>Single Responsibility</strong> were never felt that close with the practical scenarios that were mentioned in the session. The TDD workshop was very interactive as the audience was familiar with TDD and it soon became an advanced session rather than a beginner one. The audience asked many practical problems which they encountered during practicing TDD and Mr Subramaniam clarified all those doubts by citing examples from the practical world. He emphasized on learning from experience and applying it, rather than following each and every line of the rule book.<br />
</span></p>
<p style="text-align: justify;"><span style="color: #000000;">Then we continued with an open discussion again round the table and unclouded our thoughts with his knowledge about <strong>unit testing, mocking while testing, alternatives to avoid difficult situations in coding, how we can use the strengths of groovy and java side by side ..and much more. </strong></span></p>
<p style="text-align: justify;">The audience really liked the thoughts of Mr Subramaniam, which was evident from continuous inflow of questions from them. The questions were really diversified. The group discussed on, the importance of junit coverage, the readability of mocks, the behavioral problems encountered while pair programming, refactoring legacy code ("which he terms as KARMA of a developer"), the testability of code, professionalism, interpersonal skills as well as the evolution of new languages like groovy which he , by citing an example, explained that the new generation languages are working the way a developer thinks. The open ended session went on with outstanding discussions. Then finally, the session ended and we said a note of thanks to Mr Subramaniam for enlightening us with knowledge.</p>
<p style="text-align: justify;">After attending the session<strong>,</strong> we were able to vindicate our minds through his experience in project development and Agile. <span style="color: #000000;">It was a great opportunity to meet such a knowledgeable person, a great thinker and a magnificent orator. We hope to again get a chance to meet personalities like him.<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/25/rendezvous-with-mr-venkat-in-xebia/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>iPhone Memory leaks – An Introduction</title>
		<link>http://xebee.xebia.in/2011/04/18/memory-leaks-ios/</link>
		<comments>http://xebee.xebia.in/2011/04/18/memory-leaks-ios/#comments</comments>
		<pubDate>Mon, 18 Apr 2011 17:09:08 +0000</pubDate>
		<dc:creator>Palak Suneja</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[memory leak]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8467</guid>
		<description><![CDATA[I recently started working in iPhone (iOS) development. Before that I was having a happy life while working on Java-Flex technology. It is a big shift from wider to smaller space if you compare Java with Objective-C. Java guy doesn’t need to know much about the memory-management because he has a very good friend in [...]]]></description>
			<content:encoded><![CDATA[<p>I recently started working in iPhone (iOS) development. Before that I was having a happy life while working on Java-Flex technology. It is a big shift from wider to smaller space if you compare Java with Objective-C.</p>
<p>Java guy doesn’t need to know much about the memory-management because he has a very good friend in form of Mr. Garbage-Collector who is always present to take care about memory worries. Now when you move to iOS dev, you are surrounded by the complex world of Retain-Release cycle. Yes you guessed it right, I am talking about Manual Memory Management (MMM). The bigger consequences of not implementing it right way or taking it into account results in a worthless app and embarrassing moment. For instance, you are giving a demo of your app to the customer, which you wrote working hard and wrote a lot of unit test cases, but to your shock it suddenly CRASHES in the demo.<br />
<span id="more-8467"></span></p>
<p>[<strong><em>Note</em></strong><em>: </em><em>In MacOSXv10.5 and later, you can use automatic memory management by using Garbage Collection but garbage collection is not available on <strong>iOS</strong>.]</em></p>
<p>Application crashes mainly happen due to memory-leaks which is not very common scenario for a Java developer.</p>
<p>So it's important to take some memory management lessons while shifting from Java to Objective-C programmer.</p>
<p>Lets move to learn the basic concept of MMM (Retail-Release) in Objective C. The fundamental rule is to “<em>take care the objects you create</em>”. When you use <em>new</em>, <em>alloc</em> operators or <em>copy</em> for creating object or you use <em>retain</em> then you should use <em>release</em> or <em>autorelease</em> call to that object. In Objective-C, memory-management works on simple reference count mechanism, which says if object's retain count is ZERO, the object is destroyed (means memory is freed). Each object has a property called retain-count which tracks the number of references for that object. When you use <em>alloc</em>, <em>new</em>, <em>copy</em>, <em>retain</em>, the retain count for that object is increased by ONE. When you use "release" its retain-count gets decremented by ONE. The focus here should be to maintain a Zero balance of reference-count for an object.</p>
<p>Let's take a look at a sample <strong>Objective C </strong> code</p>
<p><span style="color: #800080;"><em>MyClass *mClass = [[MyClass alloc] init];</em></span></p>
<p><span style="color: #800080;"><em>…</em></span></p>
<p><span style="color: #800080;"><em>(use this mClass anywhere but remember to free its memory when done)</em></span></p>
<p><span style="color: #800080;"><strong><em>[mClass  release];</em></strong></span><br />
<em> </em></p>
<p>In above sample code, <em>new</em> operator is used to create a new dynamic object at heap-space and <em>release</em> is used to deallocating the memory.<br />
Now a java developer tends to forget the release part of code so for them here comes the savoir from the Apple it is called <em>Analyze</em>. It is a static code analyzer tool that helps developer to find Memory leaks in your code before the code is run. Although <em>Apple </em>has lot of powerful performance and memory monitoring tools for e.g. <em>Instruments</em>, but we will discuss about a simple Analyze tool, which is very easy to use and solves your big problem (for Java developer) very easily.</p>
<p>I will give you a simple example that will show you how intuitive are the tool in letting you find the memory leaks.</p>
<p>Consider the code above that you have written in Xcode (for me version 4) and as a java developer you forgets to release the memory (very common in initial days).</p>
<p><a rel="attachment wp-att-8506" href="http://xebee.xebia.in/2011/04/18/memory-leaks-ios/xcode1-3/"><img class="aligncenter size-full wp-image-8506" title="xcode" src="http://xebee.xebia.in/wp-content/uploads/2011/04/xcode12.png" alt="xcode" width="669" height="466" /></a></p>
<p>Now in your Xcode (version 3.2 or higher) Go to <strong><em>Product-&gt;Analyze</em></strong> then you will see something like this</p>
<p><a rel="attachment wp-att-8507" href="http://xebee.xebia.in/2011/04/18/memory-leaks-ios/xcode2-3/"><img class="aligncenter size-full wp-image-8507" title="xcode" src="http://xebee.xebia.in/wp-content/uploads/2011/04/xcode22.png" alt="Xcode Analyze" width="669" height="466" /></a></p>
<p>This gives you a clear picture that something you have forget please rectify, so now we add the release code and it is DONE.</p>
<p><a rel="attachment wp-att-8508" href="http://xebee.xebia.in/2011/04/18/memory-leaks-ios/xcode3-3/"><img class="aligncenter size-full wp-image-8508" title="xcode" src="http://xebee.xebia.in/wp-content/uploads/2011/04/xcode32.png" alt="xcode" width="669" height="466" /></a></p>
<p><strong><em>Note</em></strong><em>: This a basic tutorial for checking memory leaks. Memory leaks can be surfaced for other reasons that can be profiled using Product-&gt;Profile tool.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/18/memory-leaks-ios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building Editable GridView for iPhone apps</title>
		<link>http://xebee.xebia.in/2011/04/14/building-editable-gridview-for-iphone-apps/</link>
		<comments>http://xebee.xebia.in/2011/04/14/building-editable-gridview-for-iphone-apps/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 18:05:22 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Apps]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Custom Grid View]]></category>
		<category><![CDATA[GridView]]></category>
		<category><![CDATA[iphone designing]]></category>
		<category><![CDATA[iPhone4.3]]></category>
		<category><![CDATA[mobile application development]]></category>
		<category><![CDATA[UITableView]]></category>
		<category><![CDATA[UITableViewCell]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8310</guid>
		<description><![CDATA[Grid Views are powerful way of presenting data to users that won't be as appealing if presented in tabular form. For instance, the default home screen of iPhone looks elegant when presented in grid view. Similar case can occur in your application as well. As for iPhone, sdk doesn't provide any grid view implementation similar [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-8376" href="http://xebee.xebia.in/2011/04/14/building-editable-gridview-for-iphone-apps/screen-shot-2011-04-13-at-11-19-34-pm/"><img class="size-medium wp-image-8376  alignright" style="margin-left: 0px; margin-right: 0px;" title="Editable Grid View-Kalorific" src="http://xebee.xebia.in/wp-content/uploads/2011/04/Screen-shot-2011-04-13-at-11.19.34-PM-232x300.png" alt="Editable Grid View-Kalorific" width="150" height="200" /></a></p>
<p>Grid Views are powerful way of presenting data to users that won't be as appealing if presented in tabular form. For instance, the default home screen of iPhone looks elegant when presented in grid view. Similar case can occur in your application as well. As for iPhone, sdk doesn't provide any grid view implementation similar to that provided by Android(Non-Editable).  So I thought of building an <strong>editable grid view</strong> as shown on right side .<br />
<span id="more-8310"></span><br />
Custom GridView can be build in two ways, programmatically adding components to default cell or by creating custom UITableViewCell. We will be creating custom cells containing 3 custom buttons having 3 labels respectively. This can be done easily by using interface builder. The next step is to supply this custom cell to the tableview and filling it with required data. More detailed help regarding custom cells can be found in this <a href="http://developer.apple.com/library/ios/#samplecode/AdvancedTableViewCells/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40009111">sample code</a> by apple.</p>
<p>Further we will use</p>
<pre class="javascript">self.<span style="color: #006600;">tableView</span>.<span style="color: #006600;">separatorColor</span>=<span style="color: #66cc66;">&#91;</span>UIColor clearColor<span style="color: #66cc66;">&#93;</span>;
self.<span style="color: #006600;">tableView</span>.<span style="color: #006600;">backgroundColor</span>=<span style="color: #66cc66;">&#91;</span>UIColor clearColor<span style="color: #66cc66;">&#93;</span>;
self.<span style="color: #006600;">tableView</span>.<span style="color: #006600;">separatorStyle</span>=UITableViewCellSeparatorStyleNone;</pre>
<p>in viewDidLoad and</p>
<pre class="javascript">cell.<span style="color: #006600;">backgroundColor</span>=<span style="color: #66cc66;">&#91;</span>UIColor clearColor<span style="color: #66cc66;">&#93;</span>;</pre>
<p>in cellForRowAtIndexPath to clear background colors associated with Table and its cells.</p>
<p><a rel="attachment wp-att-8359" href="http://xebee.xebia.in/2011/04/14/building-editable-gridview-for-iphone-apps/screen-shot-2011-04-13-at-10-49-09-pm/"><img class="size-medium wp-image-8359  alignright" title="Edit mode of editable grid view-Kalorific" src="http://xebee.xebia.in/wp-content/uploads/2011/04/Screen-shot-2011-04-13-at-10.49.09-PM-235x300.png" alt="Edit mode of editable grid view-Kalorific" width="150" height="200" /></a></p>
<p>Till now you would have been able to setup simple grid view, so now it's time to move on to editing the grid view. But before doing that, one should ask why we want an editable grid view? <strong>The answer is usability</strong>. In current implementations the user has to navigate to different view for editing items associated with grid. But he/she would always like to have all the controls specific to an item on one screen so that he/she would not have to navigate for editing(deleting/adding). Having said this we provide him/her with a default edit button on navigation bar and will build a view similar to the one given on the right side when he/she taps the edit button.</p>
<p>The following steps are needed to convert grid view to editable grid view.</p>
<ul>
<li>When user taps on edit button
<pre class="javascript">-<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">void</span><span style="color: #66cc66;">&#41;</span>setEditing:<span style="color: #66cc66;">&#40;</span>BOOL<span style="color: #66cc66;">&#41;</span>editing animated:<span style="color: #66cc66;">&#40;</span>BOOL<span style="color: #66cc66;">&#41;</span>animated</pre>
<p>is called. Here we delete all the previous sections present and then insert new sections to transit between grid mode and editing mode. Inserting new sections(after deleting all previous sections) invokes UITableView <strong>Data Source</strong> methods which are handled as discussed below.</li>
<li>We use
<pre class="javascript">@property<span style="color: #66cc66;">&#40;</span>nonatomic,getter=isEditing<span style="color: #66cc66;">&#41;</span> BOOL editing.</pre>
<p>for specifying number of rows or sections when in editing and grid mode because in both cases the rows or sections will be different. For instance in our case in grid mode number of rows will be 3 and in editing mode number of rows will be 9.</li>
<li>We use two different UITableViewCells(Custom and Default), first for presenting grid view and second for presenting items in editable mode. We use different table <strong>cell identifiers</strong> for custom and default cells to resolve any conflicts that may occur due to reusable cells returned by dequeueReusableCellWithIdentifier.
<pre class="brush: jscript; title: ; notranslate">&lt;br /&gt;
    //in editable mode default cells are returned&lt;br /&gt;
    if (tableView.editing) {&lt;br /&gt;
        static NSString *CellIdentifier = @&amp;amp;quot;Cell&amp;amp;quot;;&lt;br /&gt;
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];&lt;br /&gt;
        if (cell == nil) {&lt;br /&gt;
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1      reuseIdentifier:CellIdentifier] autorelease];&lt;br /&gt;
                   }&lt;br /&gt;
        return cell;&lt;br /&gt;
      }&lt;br /&gt;
    //in grid view custom cells are returned&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    static NSString *CellIdentifier = @&amp;amp;quot;CustomCell&amp;amp;quot;;&lt;br /&gt;
    CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];&lt;br /&gt;
    if (cell == nil)&lt;br /&gt;
    {&lt;br /&gt;
        [[NSBundle mainBundle] loadNibNamed:@&amp;amp;quot;CustomTableViewCell&amp;amp;quot; owner:self options:nil];&lt;br /&gt;
        cell = customCell;&lt;br /&gt;
	}&lt;br /&gt;
return cell;&lt;br /&gt;
}&lt;br /&gt;
</pre>
</li>
<li>When the user taps the done button above steps are repeated but with grid view data.</li>
</ul>
<p>This type of grid view is light and easy to create, giving the developer more power to customize the grids that he wants to create. The major drawback associated with it is of responding to orientation changes because images are stretched thus distorting the look and feel of the grid. I will try to find an elegant way for handling orientation changes and upload the new code.As for now you can find the code <a href="https://github.com/xebia/xebiaindiamobile/tree/master/EditableGridView">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/14/building-editable-gridview-for-iphone-apps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Local Notifications in iPhone</title>
		<link>http://xebee.xebia.in/2011/04/13/local-notifications-in-iphone/</link>
		<comments>http://xebee.xebia.in/2011/04/13/local-notifications-in-iphone/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 08:15:01 +0000</pubDate>
		<dc:creator>Vaibhav Sehgal</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[fireDate]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[killing notifications]]></category>
		<category><![CDATA[local notifications]]></category>
		<category><![CDATA[Next Fire Date]]></category>
		<category><![CDATA[receive notification]]></category>
		<category><![CDATA[repeatInterval]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8278</guid>
		<description><![CDATA[Suppose we want to build an iPhone application that alerts the user at a particular point in time or at repeated intervals of time with some custom message, or that the application runs in the background and performs some task, and alerts the user when the task is complete. This can be accomplished in iPhone [...]]]></description>
			<content:encoded><![CDATA[<p>Suppose we want to build an iPhone application that alerts the user at a particular point in time or at repeated intervals of time with some custom message, or that the application runs in the background and performs some task, and alerts the user when the task is complete. This can be accomplished in iPhone using <strong>local notifications,</strong> which were introduced in iOS 4.0. Once a local notification is scheduled by an application, iOS takes care of it and presents it at the appropriate time.</p>
<p>This blog aims to show how to set local notifications in an iPhone application and then moves on to specific use cases where they have to be manipulated. We also talk about which methods are called when a notification is received, depending on the state of the application.<br />
<span id="more-8278"></span><br />
The following code shows how to set a local notification that will alert the user at 7:00 a.m. everyday.</p>
<pre class="brush: jscript; title: ; notranslate">

// Create a fire date for the notification by using calendar components

NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar] ;

NSDateComponents *componentsForReferenceDate =

[calendar components:(NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit ) fromDate:[NSDate date]];

[componentsForReferenceDate setDay:1] ;
[componentsForReferenceDate setMonth:1] ;
[componentsForReferenceDate setYear:2011] ;

NSDate *referenceDate = [calendar dateFromComponents:componentsForReferenceDate] ;

// set components for time 7:00 a.m.

NSDateComponents *componentsForFireDate =

[calendar components:(NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit ) fromDate: referenceDate];

[componentsForFireDate setHour: 7] ;
[componentsForFireDate setMinute:0] ;
[componentsForFireDate setSecond:0] ;

NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];

// Create the notification

UILocalNotification *notification = [[UILocalNotification alloc]  init] ;

notification.fireDate = fireDateOfNotification ;
notification.timeZone = [NSTimeZone localTimeZone] ;
notification.alertBody = [NSString stringWithFormat: @&quot;Wake up!&quot;] ;
notification.userInfo= [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@&quot;Some information&quot;] forKey:@&quot;information&quot;];
notification.repeatInterval= NSDayCalendarUnit ;
notification.soundName=UILocalNotificationDefaultSoundName;

[[UIApplication sharedApplication] scheduleLocalNotification:notification] ;

[notification release];
</pre>
<p>The point to be noted in this example is that the <strong>fireDate</strong> of the notification is 1/1/2011 at 7 a.m. . This means that the notification will first fire at 7 a.m. on January 1 . Moreover, the <strong>repeatInterval</strong> property of the notification is set to <strong>NSDayCalendarUnit</strong> (i.e. the notification will repeat after a time interval of one day). Thus the notification will also fire at 7 a.m. on January 2,January 3 and so on for each day. However, if we check the fireDate property of the notification on January 2, then it will still be 7 a.m. on 1/1/2011. However on January 2,  the "<strong>next fire date</strong>" will be 7 a.m. , 2/1/2011.  Unfortunately we cannot access this "next fire date" property.</p>
<p>A classic example of a situation where this might have been of use, is say, when notifications which repeat daily (say two notifications to remind the user to get food items from the market) have been set with fireDate as January 1, and the user launches the application on January 2 and changes some parameter in the application (say, he indicates that today is a holiday and he can't get food items from the market), we need to delete the notifications for the current day (i.e. 2/1/2011). The ideal case would have been to isolate all notifications which would fire on January 2 and delete them only. This would mean that the notifications would still fire on January 3 .In this case we cannot use the fireDate property to isolate notifications that have to fire on January 2, since their fireDate is still set to 1/1/2011.</p>
<p>To accomplish this task, we can use the userInfo property of UILocalNotification. We can set a key and corresponding value in the userInfo Dictionary of the notifications that we set.</p>
<pre class="brush: jscript; title: ; notranslate">
notification.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@&quot;Get Food&quot;], @&quot;foodItem&quot;, nil] ;
</pre>
<p>Then, we would first get all scheduled notifications by :</p>
<pre class="brush: jscript; title: ; notranslate">
[[UIApplication sharedApplication] scheduledLocalNotifications] ;
</pre>
<p>Now we could loop through this list of scheduled notifications and look for a match according to key. We can thus isolate the notifications and delete them.</p>
<pre class="brush: jscript; title: ; notranslate">
NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ;

for (UILocalNotification *localNotification in arrayOfLocalNotifications) {

    if ([[localNotification.userInfo valueForKey:@&quot;foodItem&quot;] isEqualToString:@&quot;Get Food&quot;]) {
        [[UIApplication sharedApplication] cancelLocalNotification:localNotification] ; // delete the notification from the system
    }
}
</pre>
<p>Further, the SDK also gives us methods to know whether a notification was received :</p>
<ul>
<li>When the user presses the action button on a notification that is received, if the application is running in the <strong>foreground</strong>, or in the <strong>background</strong>, the <strong>application:didReceiveLocalNotification</strong>: method of the application delegate is called.</li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
       //Do something with the notification or its data.
}
</pre>
<ul>
<li>However, if the <strong>application has been killed</strong> and then the user presses the action button on the  notification that is received, the <strong>application:didFinishLaunchingWithOptions</strong>: is called . Here we can access the notification by using the <strong>UIApplicationLaunchOptionsLocalNotificationKey</strong> key.</li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UILocalNotification *localNotification = [launchOptions valueForKey:@&quot;UIApplicationLaunchOptionsLocalNotificationKey&quot;] ;
    // Do something with the notification
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/13/local-notifications-in-iphone/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Customer: &#8220;Although I asked for it&#8230;.. that&#8217;s not what I desired!!&#8221;</title>
		<link>http://xebee.xebia.in/2011/04/08/whyagile/</link>
		<comments>http://xebee.xebia.in/2011/04/08/whyagile/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 15:51:59 +0000</pubDate>
		<dc:creator>Karan Nangru</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Project Development Methodologies]]></category>
		<category><![CDATA[Waterfall]]></category>
		<category><![CDATA[agile pros]]></category>
		<category><![CDATA[follow agile]]></category>
		<category><![CDATA[project development methodology]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[waterfall]]></category>
		<category><![CDATA[why agile]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8261</guid>
		<description><![CDATA[If you feel the statement above(in any grammatical form) was your plight during your past waterfall projects, then its time you switched your project methodology from waterfall to Agile!! Lets break the above statement into two halves, waterfallishly- "Although I asked for it" What does this fragment imply? Probably that you got what you had [...]]]></description>
			<content:encoded><![CDATA[<p>If you feel the statement above(in any grammatical form) was your plight during your past waterfall projects, then its time you switched your project methodology from waterfall to Agile!!</p>
<p><span id="more-8261"></span></p>
<p>Lets break the above statement into two halves, <em>waterfallishly</em>-</p>
<p><strong>"Although I asked for it"</strong><br />
What does this fragment imply? Probably that you got what you had asked for. Thereby meaning that the project was in accordance with your acceptance signoff,<br />
thereby meaning that the project functionality was in accordance to the FRD(functional requirement document). Thereby meaning that the business analyst's effort was justified.<br />
Let us also assume that the project source code strictly adhered to the TDD(technical design document), and that the project passed all the testing phases( except UAT... that's when you shout usually).<br />
What good does the above mentioned effort do to the project if your stance signifies the second half of the title :-</p>
<p><strong>".... thats not what I desired!!"</strong><br />
this statement rather drains down all the above mentioned effort.</p>
<p>Lets draft the irony in the scenario-</p>
<p>'<em>You come up with a project, sign the contract after validating all the prerequisite waterfallish documents,<br />
the end product developed is inline with your sign off, still you shout 'That's not what I had asked for!!</em>'</p>
<p>Ought to mention that such scenarios are very common in waterfallish projects. The reason for that is not that you were hash driven during the signoff, but rather something very vernacular. When you start off a project, you just have in mind a gist of what you want. And in most waterfallish cases, what you get is just a minimal percentage of the real expectation or the real goal.<br />
I ascribe the cause for the above problem to the fact that initially your vision is hazy.</p>
<p>Following traditional waterfallish process, the project undertakers try to extract as much details as possible at this point of time. Be it you get the best business analysts and the best technical team, the final photograph clicked in a hazy environment will always be hazy. While building the functional requirement documents and the technical design documents, the end product is drafted based on some static wire frames which are indeed based on your hazy thoughts. So what you get is just a part of the portion that you were able to feed from those naive thoughts.  Ought to mention that business analysts do try to edit/polish the photograph, make as many cosmetic changes as they can(using your make up kit) to make the final picture better than the initial hazy picture clicked of your imagination, but is that sufficient? The answer is usually No.</p>
<p>This is where I would like to cogitate the agile manifesto:-</p>
<ul>
<li><em>Working software over comprehensive documentation </em></li>
<li><em>Individuals and interactions over processes and tools</em></li>
<li><em>Customer collaboration over contract negotiation</em></li>
<li><em>Responding to change over following a plan</em></li>
</ul>
<p>If you are shown a working prototype of your imaginative expectation, then it would be any day better than that comprehensive documentation. By documenting the exact expectation beforehand you are abstained from not circumscribing your high level thoughts to the documentation. When you have a working software in hand, you are free to play around with it as consumer of the software, propose the same to your stakeholders and expect much more meaningful feedback than what you get by just showing on paper how the real software would be. In fact in most cases, you are able to realize if a specific feature of the software really has the originally estimated business value. This way, you are getting more value for your money. <em>You don't just buy a car by only looking at its news paper advertisement, do you? You first go and test drive the car. </em>And for those buying a car without test driving it, often end up dissatisfied(did I just bespeak waterfall).</p>
<p>Rather than just abiding by the development phase processes, you build the product iteratively. At the end of each iteration, by having a working software your expectation is always inline with the your imagination(if it is not, then you shout at the end of the iteration, rather further later). I don't need to mention how valuable your early feedback is to the development team. Your expectation mature from iteration to iteration. It is like you are clicking the picture every iteration, so and so is the haze diminishing!!</p>
<p>In waterfall, the later a bug is encountered, the more heavily it costs the team, indirectly to you. But the later you desire a feature in functionality, the more likely you receive an out of scope response. Then the negotiations(I call them quarrels) with the development manager are no new. Later, the development team res estimates the changes and you need to pay for it. The time schedule is just hampered there. Waterfall calls it <em><strong>'change control'</strong></em>.</p>
<p>I believe there is nothing like change control. <em>Changes are not controlled, they are managed.</em> And by your regular feedback each iteration, the team manages the change in a much more lean way than what they do in the so called change control. And, the time and money that you spend should be lesser than what you spend due to change control. <em>This collaborative work is indeed more valuable than a contract negotiation!!</em></p>
<p>P.S.<br />
Don't jump on to agile if you are sailing smoothly in waterfall, why disturb the calmness..... if so, may be you can try it if you feel you are sailing on petrol, rather than diesel (diesel is much cheaper in India, compared to petrol!!)</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/08/whyagile/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Junit Tests &#8211; The Myths Around Coverage</title>
		<link>http://xebee.xebia.in/2011/04/06/junit-tests-the-myths-around-it/</link>
		<comments>http://xebee.xebia.in/2011/04/06/junit-tests-the-myths-around-it/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 20:03:20 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Extreme Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8253</guid>
		<description><![CDATA[Nowadays when Agile is on its peak and Junit tests hijack the technical discussions. Its very easy to find people obsessed with Junits. You can really sense the excitement in people when they talk about Junits. I consider this as one of the major achievements of the Agile promoters. They have been really successful in [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Nowadays when Agile is on its peak and Junit tests hijack the technical discussions. Its very easy to find people obsessed with Junits. You can really sense the excitement in people when they talk about Junits.</p>
<p style="text-align: justify;">I consider this as one of the major achievements of the Agile promoters. They have been really successful in transfusing Junits in the blood of developers, managers and even clients. Generally, I see questions in demo regarding the code coverage. And then, I see the team writing Junits, one after the other, to set the Junit coverage above the expectations of the client.</p>
<p style="text-align: justify;">However, most of the people, who are into this highly geeky practice of writing Junit tests, really write Junits which are even worth a penny?</p>
<p style="text-align: justify;"><span id="more-8253"></span>If we do a voting for the reasons of writing Junits, and developers are allowed to vote without their manager or client watching them, I am pretty sure that “Increasing Code Coverage” is what will emerge as the clear winner. And I do not blame developers for it.</p>
<p style="text-align: justify;">The manager or the client, who pushed them to write Junits is the real culprit. Regarding the manager, I will say, that he rarely sees the code, or never sees it. But, he wants a good coverage to show to the client. Its business.</p>
<p style="text-align: justify;">All, the client generally knows about the code is the statistics generated by various tools. So, the only thing he bothers about, is the code coverage. And I do not blame the clients for this expectation. Because this is what the Agile coach told them. This is what he knows. “All the code should be covered with Junit tests”. And then you will gain eternity. Huh.</p>
<p style="text-align: justify;">Just a thought, if everyone will keep talking about the code coverage and Junit tests, then who will talk about the code. Basically, the focus has shifted to write Junit tests which tests the code, rather than the actual code.</p>
<p style="text-align: justify;">The developer keeps on writing code, ifs, elses, switches, methods after methods. The class size grows upto 1000-2000 lines long. But, the code is covered with Junit tests. And when you will see the Junit tests, it will scare you.</p>
<p style="text-align: justify;">The Junit tests for large classes are 100-200 lines long. Whenever someone will write some code, he will add another two lines in Junit test also, So that the test can pass and the code executes. No matter what the Junit test is testing. Sometimes, Junit tests become so hard to modify, that people comment out the assertion, so that the test can pass and they can commit the code into repository.<br />
Will we get any benefit from this type of Junit tests or coverage which these Junits show? NO.</p>
<p style="text-align: justify;">We need Junit tests to make sure the code is doing what we expect it to do. But if the Junit itself has become too complex, how can we use it for any such purpose. Its no more simple and understandable.</p>
<p style="text-align: justify;">Moreover, these complex and long Junit tests sometimes become bottleneck in development. You changed something and you need to fix the complex Junit test covering it. The time taken in making Junit tests pass is sometimes much more than what would have been taken to write a Junit test from scratch. And since you or your peer has spent days writing the Junit, you do not want to delete it. Because its so close to your heart. You invested so much time in writing it. Bullshit.</p>
<p style="text-align: justify;">My suggestion is, the time you see a Junit test which you can not understand, delete it and rewrite it. In most of these cases, the class, the Junit test was covering would need refactoring. See whether the class is doing too much. If its doing a hell lot of job, break it into simple pieces. And write simple and logical Junits for them. If you have existing Junit test cases, it will help as a safety net while refactoring. The tests will ensure that the refactored code does not breaks the functionality ( if the existing Junit tests were not rotten).</p>
<p style="text-align: justify;">But what if you need to refactor classes which have no existing Junits?? People will say, that, never ever refactor a code which is not covered by Junit tests. Because Junit tests is a safety net around which you refactor. So, does this means that you should write Junit tests first for the complex classes and then refactor?</p>
<p style="text-align: justify;">NO. Simply NO. Until and unless there is nothing else to do in the project or you really want to make your life hell. In short, until you have lots of time.</p>
<p style="text-align: justify;">Writing junits for pre existing complex classes will not be that easy. It will take hell lot of a time. Also, the tests will not make any sense, as they will be too complex to understand and maintain. The Junits lose their sanity after the class being tested breaches a complexity level. And if you have really less time, then try to write Junit tests for classes which get changed really frequently. Junit test around a class you know is never going to change is useless. Always have tests around classes which change frequently.</p>
<p style="text-align: justify;">So, just try to do some initial safe and easy refactoring first. So that you can add some basic junits. And then use these junits to refactor the code mercilessly to its simplest form. The refactored code, broken into simple understandable pieces will have the logical junits which will make sense.</p>
<p style="text-align: justify;">If you have a tool which shows the statistics about the project in timeline, the complexity should decrease gradually, when you refactor, along with increase in the code coverage.</p>
<p style="text-align: justify;">So, shed the obsession with Junit tests. Start writing “Clean Junit Tests”.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/04/06/junit-tests-the-myths-around-it/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Test OAuth protected REST services using soapUI</title>
		<link>http://xebee.xebia.in/2011/03/31/test-oauth-protected-rest-services-using-soapui/</link>
		<comments>http://xebee.xebia.in/2011/03/31/test-oauth-protected-rest-services-using-soapui/#comments</comments>
		<pubDate>Thu, 31 Mar 2011 17:29:14 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[soapUI]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8200</guid>
		<description><![CDATA[soapUI is one of the best tools for testing the REST services. It can very efficiently help to check and ensure that the services return just what is expected. Due to these promising reasons we tried to use soapUI for testing the REST based services of our application. But we found a serious road block. [...]]]></description>
			<content:encoded><![CDATA[<p>soapUI is one of the best tools for testing the REST services. It can very efficiently help to check and ensure that the services return just what is expected. Due to these promising reasons we tried to use soapUI for testing the REST based services of our application. But we found a serious road block. The REST services in our application is secured by OAuth 1.0, and as of now soapUI has out of the box support for basic authentication only.</p>
<p><span id="more-8200"></span><br />
OAuth enables users to share their data lying with their providers with third party consumers. This is a complex use case and involves complex authentication cycles before the actual data can be accessed by consumers from the providers. Since soapUI does not provide out of box support for the authentication logic for OAuth as it does for basic authentication, we were left with two options, either create the support for OAuth authentication or use some other tool. To get around this issue we decided to add support for OAuth authorization in soapUI using the option of adding Groovy library in saopUI. I have used Soap UI 3.5.1 for evaluation.</p>
<p>In this blog I will explain the Groovy script required to send request to the API after the access token is already generated. The previous steps involved in the generation of access token will be dealt in my next blog post.</p>
<p>For OAuth 1.0, when you want to access the resource secured by OAuth the HTTP request should have following parameters for the request to get authenticated</p>
<ol>
<li>oauth_consumer_key</li>
<li>oauth_signature_method</li>
<li>oauth_token</li>
<li>oauth_version</li>
<li>oauth_timestamp</li>
<li>oauth_nonce</li>
<li>oauth_signature</li>
</ol>
<p>Please note that the first four parameters are static for a particular consumer and access token. But the last three parameters are dynamic and need to be generated before every call to the resource. We will deal each parameter one by one and see how these can be dynamically generated by using Groovy script.</p>
<p><strong>oauth_timestamp</strong></p>
<p>Please note that the time is to be in seconds<strong>.</strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<pre class="brush: java; title: ; notranslate">
int time = (System.currentTimeMillis()/1000);
String timeString = String.valueOf(time);
groovyUtils.setPropertyValue(&quot;Properties&quot;, &quot;timeString&quot;, timeString);
</pre>
<p><strong>oauth_nonce</strong></p>
<pre class="brush: java; title: ; notranslate">
long timeStampResult =Long.valueOf(timeString);
String nonce =String.valueOf(timeStampResult + new Random().nextInt());
groovyUtils.setPropertyValue(&quot;Properties&quot;, &quot;nonce&quot;, nonce);
</pre>
<p><strong>oauth_signature</strong></p>
<p>The generation of signature is the trickiest part. I will break the script in smaller parts and give a brief idea about the 'why' before I explain the how. This would help understand the script better. People already aware about the signature generation can jump to script.</p>
<p>For creating the signature you will need (i) base string, (ii) the consumer key and (iii) the access_token secret</p>
<ul>
<li>
<h4>The Base String</h4>
<p>This is a sample base string which is formatted for better readability.</p>
<pre class="brush: xml; title: ; notranslate">
GET&amp;amp;http%3A%2F%2Flocalhost%3A8080%2Fabc.com6%2Frest%2Fusers%2Fget&amp;amp;%3D
%26oauth_callback%3Doob
%26oauth_consumer_key%3DconsumerKey
%26oauth_nonce%3D175942032
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1301554858
%26oauth_token%3Df285bed1-c57c-42db-8438-3ec33fd6c4be
%26oauth_version%3D1.0
%26user_name%3Ddemouser
</pre>
<p>On close inspection it is easy to understand that the base string consists of</p>
<ul>
<li>HTTP method.</li>
<li>Full path to resource.</li>
<li>All OAuth related parameters.</li>
<li>All parameters required for accessing the resource.</li>
</ul>
<p>Please note that in the URL the parameters appear in the ascending order of the names of the parameters. And after creating a string from the above parameters the string is encoded as per the URL encoding rules.</p>
<p>Let us see the groovy script that gets the OAuth parameters from project level properties, and the API specific properties from the test case properties</p>
<p><strong>OAuth Specific parameters</strong></p>
<pre class="brush: xml; title: ; notranslate">
def oauth_version = context.expand( '${#Project#oauth_version}' )
def oauth_consumer_key = context.expand( '${#Project#oauth_consumer_key}' )
def oauth_callback = context.expand( '${#Project#oauth_callback}' )
def oauth_signature_method = context.expand( '${#Project#oauth_signature_method}' )
def oauth_token = context.expand( '${#Project#oauth_token}' )
def token_secret = context.expand( '${#Project#token_secret}' )
</pre>
<p><strong>API specific parameters</strong></p>
<pre class="brush: xml; title: ; notranslate">
def user_name = context.expand(  '${Properties#user_name}' )
</pre>
<p>Please note that if you want to make the script generic then in that case  the api specific properties and their values will have to be passed dynamically to the script.Once all the parameters are available they will have to be sorted in the alphabetic order of names of parameters, for that we will take following steps</p>
<p>(i) <strong>Put the parameters in a Map</strong></p>
<pre class="brush: java; title: ; notranslate">
Map parameterMap = new HashMap();
parameterMap.put(&quot;oauth_version&quot;, oauth_version);
parameterMap.put(&quot;oauth_consumer_key&quot;, oauth_consumer_key);
............
parameterMap.put(&quot;oauth_timestamp&quot;, timeString);
parameterMap.put(&quot;user_name&quot; , user_name);
</pre>
<p>(ii)<strong>Sort the parameter</strong></p>
<pre class="brush: java; title: ; notranslate">
Map sorted = new LinkedHashMap();
List keys = new ArrayList(map.keySet());
Collections.sort(keys);
for (String key : keys){
      sorted.put(key, map.get(key));
}
</pre>
<p>Once the parameter are sorted, a string has to be generated in the query string format, to be appended to the encoded string generated from end point</p>
<p><strong>Create a encoded parameter string</strong></p>
<pre class="brush: java; title: ; notranslate">
StringBuffer encodedString = new StringBuffer(map.size() * 20);
    for (String key : map.keySet())
    {
        if(encodedString.length() &gt; 0){
               encodedString.append('&amp;');
        }
       encodedString.append(percentEncode(key)).append('=').append(percentEncode(map.get(key)));
    }
    def encodedParamString = encodedString.toString();
</pre>
<p>The url to the REST resource has to be encoded.</p>
<p><strong>Encode the endpoint url string </strong></p>
<pre class="brush: java; title: ; notranslate">
     String encodedURL = URLUtils.percentEncode(endpoint);
</pre>
<p>Now create the base string using the encoded url, encoded string generated from parameters and the HTTP method.</p>
<pre class="brush: java; title: ; notranslate">
     def basicString= String.format( &quot;%s&amp;%s&amp;%s&quot;, &quot;GET&quot;, encodedURL, encodedParamString );
</pre>
<p><strong>Generate cryptographic function and signature</strong></p>
<pre class="brush: java; title: ; notranslate">
     SecretKeySpec key = new SecretKeySpec((&quot;consumerKey&amp;&quot;+token_secret).getBytes(&quot;UTF-8&quot;), &quot;HmacSHA1&quot;);
     Mac mac = Mac.getInstance(&quot;HmacSHA1&quot;);
     mac.init(key);
     byte[] bytes = mac.doFinal(basicString.getBytes(&quot;UTF-8&quot;));
    def signature = new String(Base64.encodeBase64(bytes)).replace(&quot;\r\n&quot;, &quot;&quot;);
    groovyUtils.setPropertyValue(&quot;Properties&quot;, &quot;signature&quot;, signature);
</pre>
<p>Now transfer these properties set in the testcase properties to the request parameters. That's all one needs to do to call rest based services protected by OAuth 1.0.</li>
</ul>
<p>Reference:<br />
<a href="http://vimeo.com/api/docs/oauth">http://vimeo.com/api/docs/oauth</a></p>
<p><a title="Java client for OAuth" href="https://github.com/fernandezpablo85/scribe-java">https://github.com/fernandezpablo85/scribe-java</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/03/31/test-oauth-protected-rest-services-using-soapui/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flex: Creating Complex Charts using Multiple Categories</title>
		<link>http://xebee.xebia.in/2011/03/29/flex-creating-complex-charts-using-multiple-categories/</link>
		<comments>http://xebee.xebia.in/2011/03/29/flex-creating-complex-charts-using-multiple-categories/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 04:51:25 +0000</pubDate>
		<dc:creator>Nitin Khattar</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Charting]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8143</guid>
		<description><![CDATA[In my last Blog on Flex Charting components, we talked about how to create Composite charts in Flex using multiple chart series, multiple data series and multiple axes. We also discussed the common problem faced while clubbing different chart series within a single chart. Then we explored the concept of ColumnSet in Column Charts &#38; [...]]]></description>
			<content:encoded><![CDATA[<p>In my last <a href=" http://xebee.xebia.in/2011/03/24/flex-composite-charts-with-multiple-series-axes/" target="_blank">Blog</a> on Flex Charting components, we talked about how to create <strong>Composite charts</strong> in Flex using <em>multiple chart series, multiple data series and multiple axes</em>. We also discussed the common problem faced while clubbing different chart series within a single chart. Then we explored the concept of <strong>ColumnSet</strong> in Column Charts &amp; similarly <strong>BarSet</strong> in Bar Charts. Also we learned about the significance of having multiple axes (vertical or horizontal) in a chart and how we can visualize indirectly related data with each other.</p>
<p>So now let’s raise the complexity to the next level and discuss how to create Complex Charts in Flex, and also showcase an example on creating such charts, this time using multiple categories.<span id="more-8143"></span></p>
<p>Creating Complex charts accounts for some <strong>important considerations</strong> that one should keep in mind:</p>
<ol>
<li><strong>Format</strong> (or Syntax) of the Data Collection (Arrays,      XML, Objects, etc.)</li>
<li><strong>Parsing </strong>the data collection into suitable Chart      Data collection</li>
<li><strong>Configuring</strong> Specific Chart Type with its specific      properties &amp; behavior</li>
</ol>
<p>The <strong>first &amp; second </strong>points deal with the way we store the data collection in the form of XMLs or Remote Objects; and the way we parse it before sending to the chart. This might look like a minor detail to fuss over, but trust me, it’s important to tackle this beforehand; otherwise the chart would represent the same in a wholly unexpected graphical format.</p>
<p>The <strong>third </strong>point is undoubtedly the most important of above all. This deals with configuring the required chart type with its distinct properties &amp; controls and that too in the right manner. The properties may include vertical axis, horizontal axis, series, chart type, etc.</p>
<p>Ok, let’s start exploring this concept with the help of an example:</p>
<p><strong>Example – Column Chart with multiple categories &amp; chart series</strong></p>
<p>Let’s use the problem statement as used in the previous <a href="http://xebee.xebia.in/2011/03/24/flex-composite-charts-with-multiple-series-axes/#compositeChartEg1" target="_blank">blog</a> and redefine it a bit:</p>
<p>As a sales manager, I want to visualize the Data for the Sales (Bottle &amp; Canned) of different types of Soft Drinks (Coke, Pepsi &amp; Sprite) in different metropolitan Cities (Delhi, Mumbai &amp; Bangalore) in the form of a Column Chart where Soft Drink is the primary category, City is the secondary category, and Bottled Sales &amp; Canned Sales are the two series. In a nutshell, we are looking at <strong>City Sales (Bottled &amp; Canned), Product wise</strong>.</p>
<p>From the above mentioned statement, we could easily make out some basic facts that ‘product’ as soft drink will serve as the horizontal axis, ‘bottled / canned sales’ will serve as the vertical axis. But the question is <span style="color: #ff0000;">Where to accommodate an extra category, i.e. ‘<strong>city</strong>’?</span></p>
<p>The chart should appear like this:</p>
<div style="width: 100%; align: center;"><img class="aligncenter size-full wp-image-8155" title="MultipleCategoryChart" src="http://xebee.xebia.in/wp-content/uploads/2011/03/MultipleCategoryChart.bmp" alt="Complex Chart with Multiple=" /></div>
<p>What we know so far is that we can have <strong>only one category axis</strong> as the horizontal axis of a chart and can have multiple chart series which can be grouped accordingly but having another Category Axis is altogether a new and a bit unclear requirement.</p>
<p>But, again the answer to this question is <strong>ColumnSet</strong>.  If you remember, Definition of Column Set as per the Flex Charting API has something to add in this respect:</p>
<p>“<em>ColumnSet is a grouping set that can be used to stack or cluster column series in any arbitrary chart. A ColumnSet encapsulates the same grouping behavior used in a ColumnChart, but can be used to assemble custom charts based on CartesianChart. ColumnSets can be used to cluster any chart element type that implements the IColumn<strong> </strong>interface. It can stack any chart element type that implements the IColumn and IStackable interfaces. </em><strong><em>Since ColumnSet itself implements the IColumn interface, you can use ColumnSets to cluster other ColumnSets to build more advanced custom charts.</em></strong><em>”</em></p>
<p>Summarizing the ‘Golden Rule’ above, we need to <strong>make a collection of such Column sets for every distinct City grouped within a Parent Column Set for the product</strong>. Each City Column Set will be of type ‘<strong>Stacked’</strong> and Product Column Set will be of type ‘<strong>Clustered’</strong>.<br />
And we will get our chart created in the desired manner.</p>
<div style="width: 100%; align: center;"><img class="aligncenter size-full wp-image-8156" title="MultipleCategoryColumnSet" src="http://xebee.xebia.in/wp-content/uploads/2011/03/MultipleCategoryColumnSet.png" alt="Multiple Category Column Set Representation" width="546" height="402" /></div>
<p>So let’s solve this problem taking into consideration the above mentioned approach for creating complex charts:</p>
<ul>
<li>Data Collection Format – I am using a simple xml as the data collection</li>
</ul>
<pre class="brush: xml; title: ; notranslate">
&lt;chart&gt;
   &lt;chartData product=&quot;Coke&quot; city=&quot;Delhi&quot; bottledSales=&quot;500&quot; cannedSales=&quot;400&quot;/&gt;
   &lt;chartData product=&quot;Coke&quot; city=&quot;Mumbai&quot; bottledSales=&quot;800&quot; cannedSales=&quot;600&quot;/&gt;
   &lt;chartData product=&quot;Coke&quot; city=&quot;Banglore&quot; bottledSales=&quot;1200&quot; cannedSales=&quot;700&quot;/&gt;
   &lt;chartData product=&quot;Pepsi&quot; city=&quot;Delhi&quot; bottledSales=&quot;700&quot; cannedSales=&quot;1000&quot;/&gt;
   &lt;chartData product=&quot;Pepsi&quot; city=&quot;Mumbai&quot; bottledSales=&quot;500&quot; cannedSales=&quot;800&quot;/&gt;
   &lt;chartData product=&quot;Pepsi&quot; city=&quot;Banglore&quot; bottledSales=&quot;800&quot; cannedSales=&quot;300&quot;/&gt;
   &lt;chartData product=&quot;Sprite&quot; city=&quot;Delhi&quot; bottledSales=&quot;1200&quot; cannedSales=&quot;800&quot;/&gt;
   &lt;chartData product=&quot;Sprite&quot; city=&quot;Mumbai&quot; bottledSales=&quot;500&quot; cannedSales=&quot;1000&quot;/&gt;
   &lt;chartData product=&quot;Sprite&quot; city=&quot;Banglore&quot; bottledSales=&quot;1200&quot; cannedSales=&quot;500&quot;/&gt;
&lt;/chart&gt;
</pre>
<ul>
<li><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal;">Correctly Parsing the Data collection into      Suitable Chart Data –</span></li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
public function set chartData(chart:Object):void
{
   var chartDataCollection:ArrayCollection = new ArrayCollection(chart.chartData);
   var chartDataCollection:ArrayCollection = event.result.chart.chartData;
   for each(var chartDataObject:Object in chartDataCollection)
   {
     if(!categoryOneDataprovider.contains(chartDataObject[ChartEnum.CATEGORY_ONE]))
        {categoryOneDataprovider.addItem(chartDataObject[ChartEnum.CATEGORY_ONE]);}
     if(!categoryTwoCollection.contains(chartDataObject[ChartEnum.CATEGORY_TWO]))
        {categoryTwoCollection.addItem(chartDataObject[ChartEnum.CATEGORY_TWO]);}
   }
   for each(var categoryTwoDataValue:String in categoryTwoCollection)
   {
     var categoryTwoDataCollection:ArrayCollection = new ArrayCollection();
     for each(var chartDataVO:Object in chartDataCollection)
     {
         if(chartDataVO[ChartEnum.CATEGORY_TWO] == categoryTwoDataValue)
           {categoryTwoDataCollection.addItem(chartDataVO);}
     }
     categoryTwoDataProvider.addItem(categoryTwoDataCollection);
   }
}
</pre>
<ul>
<li>Configuring Column Chart with its specific controls &amp; properties like categories, series &amp; axes –</li>
</ul>
<p><strong> Using Actionscript </strong>:-</p>
<pre class="brush: jscript; title: ; notranslate">
var complexColumnChart:ColumnChart = new ColumnChart();
var chartHorizontalAxis:CategoryAxis = new CategoryAxis();
chartHorizontalAxis.dataProvider = complexChartsPM.categoryOneDataprovider;
chartHorizontalAxis.title = ChartEnum.CATEGORY_ONE.toUpperCase();

var chartVerticalAxis:LinearAxis = new LinearAxis();
chartVerticalAxis.title = ChartEnum.SERIES_ONE.toUpperCase() +
&quot;\\&quot; + ChartEnum.SERIES_TWO.toUpperCase();

var chartColSet:ColumnSet = new ColumnSet();
chartColSet.type = &quot;clustered&quot;;
var categoryTwoColSets:ArrayCollection = new ArrayCollection();

for each(var categoryTwoDataColl:ArrayCollection
             in complexChartsPM.categoryTwoDataProvider)
{
   var categoryTwoColSet:ColumnSet = new ColumnSet();
   categoryTwoColSet.type = &quot;stacked&quot;;
   categoryTwoColSet.dataProvider = categoryTwoDataColl;
   var categoryTwoDataSeries:ArrayCollection = new ArrayCollection();
   for each(var seriesLabel:String in ChartEnum.SERIES)
   {
      var colSetColumnSeries:ColumnSeries = new ColumnSeries();
      colSetColumnSeries.yField = seriesLabel;
      colSetColumnSeries.displayName =
      categoryTwoDataColl.getItemAt(0)[ChartEnum.CATEGORY_TWO
      + &quot; &quot; + seriesLabel.toUpperCase();
      categoryTwoDataSeries.addItem(colSetColumnSeries);
   }
   categoryTwoColSet.series = categoryTwoDataSeries.source;
   categoryTwoColSets.addItem(categoryTwoColSet);
}
chartColSet.series = categoryTwoColSets.source;
complexColumnChart.horizontalAxis = chartHorizontalAxis;
complexColumnChart.verticalAxis = chartVerticalAxis;
complexColumnChart.series.push(chartColSet);
</pre>
<p><strong>Why ActionScript preferred over MXML?</strong></p>
<p>The same logic as above could be built using MXML but it poses a limitation that we could not create column sets for distinct cities <strong>dynamically</strong> using the ArrayCollection containing dataprovider for each city. This could be made possible in MXML only through use of Repeater or DataGroup. But both of them give some unexpected errors.</p>
<p>Using Repeater gives a Compile-Time Error:</p>
<p><span style="color: #ff0000;"> Repeaters require a Halo container based parent</span></p>
<p>Using DataGroup gives a Runtime Error:</p>
<p><span style="color: #ff0000;"> TypeError: Error #1034: Type Coercion failed: cannot convert spark.components::DataGroup@3805c29 to mx.charts.chartClasses.IChartElement.</span></p>
<p>Therefore, to avoid this, we need to create distinct column sets for each city with a reference to its respective dataprovider, <strong>at the compile time</strong>.</p>
<pre class="brush: xml; title: ; notranslate">
…
&lt;mx:series&gt;
 &lt;mx:ColumnSet type=&quot;clustered&quot; id=&quot;productColSet&quot;&gt;
	&lt;mx:ColumnSet id=&quot;city1ColSet&quot; type=&quot;stacked&quot; dataProvider=&quot;{delhi}&quot;&gt;
	   &lt;mx:ColumnSeries displayName=&quot;Delhi bottledSales&quot; yField=&quot;bottledSales&quot;/&gt;
	   &lt;mx:ColumnSeries displayName=&quot;Delhi cannedSales&quot; yField=&quot;cannedSales&quot;/&gt;
	&lt;/mx:ColumnSet&gt;
	&lt;mx:ColumnSet id=&quot;city2ColSet&quot; type=&quot;stacked&quot; dataProvider=&quot;{mumbai}&quot;&gt;
           &lt;mx:ColumnSeries displayName=&quot;Mumbai bottledSales&quot; yField=&quot;bottledSales&quot;/&gt;
           &lt;mx:ColumnSeries displayName=&quot;Mumbai cannedSales&quot; yField=&quot;cannedSales&quot;/&gt;
	&lt;/mx:ColumnSet&gt;&lt;br /&gt;
	&lt;mx:ColumnSet id=&quot;city3ColSet&quot; type=&quot;stacked&quot; dataProvider=&quot;{banglore}&quot;&gt;
           &lt;mx:ColumnSeries displayName=&quot;Banglore bottledSales&quot; yField=&quot;bottledSales&quot;/&gt;
           &lt;mx:ColumnSeries displayName=&quot;Banglore cannedSales&quot; yField=&quot;cannedSales&quot;/&gt;
	&lt;/mx:ColumnSet&gt;
&lt;/mx:ColumnSet&gt;
&lt;mx:series/&gt;
...
</pre>
<p>The <strong>Output SWF</strong> file generated (Using either ActionScript or MXML) is as follows:</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_MultipleCategoryChart1_267119237"
			class="flashmovie"
			width="600"
			height="450">
	<param name="movie" value="http://xebee.xebia.in/wp-content/uploads/2011/03/MultipleCategoryChart1.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://xebee.xebia.in/wp-content/uploads/2011/03/MultipleCategoryChart1.swf"
			name="fm_MultipleCategoryChart1_267119237"
			width="600"
			height="450">
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p><a href="http://xebee.xebia.in/wp-content/uploads/2011/03/MultipleCategoryChart.zip" target="_self">Download Source Code</a></p>
<p>In this way I learned how to create Flex Complex Charts with multiple categories and multiple chart series.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/03/29/flex-creating-complex-charts-using-multiple-categories/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Flex: Composite Charts with Multiple Series &amp; Axes</title>
		<link>http://xebee.xebia.in/2011/03/24/flex-composite-charts-with-multiple-series-axes/</link>
		<comments>http://xebee.xebia.in/2011/03/24/flex-composite-charts-with-multiple-series-axes/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 03:56:55 +0000</pubDate>
		<dc:creator>Nitin Khattar</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Charting]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7981</guid>
		<description><![CDATA[Recently in my project, I came across a requirement to introduce Flex Charting components in the application as a means of Data Visualization. The application deals with Business Analysis of tons of raw data in tabular format with various categories &#38; sub-categories, alphabetical &#38; numeric data. That’s why for an end-user Data Visualization is a [...]]]></description>
			<content:encoded><![CDATA[<p>Recently in my project, I came across a requirement to introduce Flex Charting components in the application as a means of <strong>Data Visualization</strong>. The application deals with Business Analysis of tons of raw data in tabular format with various categories &amp; sub-categories, alphabetical &amp; numeric data. That’s why for an end-user Data Visualization is a must feature.</p>
<p>Flex provides a wide range of charting controls with varied types &amp; configurable properties. Flex supports the most common types of two-dimensional charts (such as bar, column, and pie charts) and gives you a great deal of control over the appearance of charts.</p>
<p>Creating Simple Charts turned out to be an easy task with the help of <strong><a href="http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7bdf.html" target="_blank">Adobe Help Reference</a></strong> and <strong><a href="http://blog.flexexamples.com/category/charting/" target="_blank">Flex Blog examples</a></strong>, but creating composite charts was not that easy as it appeared to me. So in this blog, I will elaborate on how to create composite charts and will showcase few examples on creating composite charts using multiple chart series and multiple axes.</p>
<p><span id="more-7981"></span></p>
<p>Creating <strong>Composite chart</strong> accounts for an important consideration that one should keep in mind:</p>
<ul>
<li>Configuring specific chart type with its specific properties &amp; behavior and then clubbing each of them in a composite way such that it suits for each chart type or series in a perfect manner.</li>
</ul>
<p>Ok, let’s start exploring this concept with few examples:<br />
<a name="compositeChartEg1"></a><br />
<strong>Example 1 - Composite Chart (Column &amp; Line) with multiple column series</strong></p>
<p>Let’s consider a problem statement:</p>
<p>As a sales manager, I want to visualize the Data for the Sales (Bottle &amp; Canned) of few types of Soft Drink (Coke, Pepsi &amp; Sprite) in a City (Delhi) in the form of a Column Chart and a separate Line Chart depicting the Total Sales.</p>
<p>From the above mentioned statement we could easily make out some basic facts that ‘product’ as soft drink  will serve as the <strong>horizontal axis</strong>, ‘sales’ will serve as the <strong>vertical axis</strong>. Chart will consist of two <strong>column series</strong> (one for ‘bottled sales’ &amp; another for ‘canned sales’) and one<strong> line series</strong> for ‘total sales’.</p>
<p>The chart may appear like this:</p>
<div style="width: 100%; align: center;"><img class="aligncenter" title="Single ColumnSet" src="http://xebee.xebia.in/wp-content/uploads/2011/03/SingleColumnSet.jpg" alt="" width="388" height="296" /></div>
<p>Ok, I think the problem is quite straightforward and the basic fact is to make a <strong>Stacked</strong> Column Chart with two column series and one line Series. So, following is a common approach &amp; unluckily a <strong>common mistake</strong> that we all may commit ..</p>
<pre class="brush: java; title: ; notranslate">
...
[Bindable]
private var delhi:ArrayCollection = new ArrayCollection([
       {productName:&quot;Coke&quot;,bottledSales:200,cannedSales:500,total:700},
       {productName:&quot;Pepsi&quot;,bottledSales:400,cannedSales:700,total:1100},
       {productName:&quot;Sprite&quot;,bottledSales:300,cannedSales:600,total:900}
]);
...
&lt;mx:ColumnChart id=&quot;multipleAxisColumn&quot; showDataTips=&quot;true&quot; dataProvider=&quot;{delhi}&quot;
       type=&quot;stacked&quot;&gt;
       &lt;mx:horizontalAxis&gt;
             &lt;mx:CategoryAxis categoryField=&quot;productName&quot; title=&quot;Product&quot;/&gt;
       &lt;/mx:horizontalAxis&gt;
       &lt;mx:verticalAxis&gt;
	     &lt;mx:LinearAxis id=&quot;series1Axis&quot; title=&quot;Sales&quot;/&gt;
       &lt;/mx:verticalAxis&gt;
       &lt;mx:series&gt;
             &lt;mx:ColumnSeries yField=&quot;bottledSales&quot; displayName=&quot;Bottled Sales&quot; /&gt;
             &lt;mx:ColumnSeries yField=&quot;cannedSales&quot; displayName=&quot;Canned Sales&quot; /&gt;
	     &lt;mx:LineSeries yField=&quot;total&quot; displayName=&quot;Total Sales&quot;/&gt;
       &lt;/mx:series&gt;
&lt;/mx:ColumnChart&gt;
</pre>
<p>Oops….an exception occurs when we try to run the application</p>
<p><span style="color: #ff0000;">ReferenceError: Error #1056: Cannot create property offset on mx.charts.series.LineSeries.<br />
mx.charts::ColumnChart/applySeriesSet()<br />
[E:\dev\hero_private\frameworks\projects\datavisualization\src\mx\charts\ColumnChart.as:530]<br />
mx.charts.chartClasses::CartesianChart/http://www.adobe.com/2006/flex/mx/internal::updateSeries()<br />
[E:\dev\hero_private\frameworks\projects\datavisualization\src\mx\charts\chartClasses\CartesianChart.as:1042]…</span></p>
<p>As you can see when we try to run the above code, it gives a runtime error implying that the Chart Type ‘Stacked’ cannot be applied to Line Series. So, now the question is how to apply the stacked type to the column series separately, since there is <strong>no property named ‘Type’ in a Column Series</strong>??</p>
<p>Answer is to exploit the concept of <strong>ColumnSet</strong>. This is what Flex Charting API has to say about Column Set –</p>
<p>“<em><strong>ColumnSet </strong></em><em>is a grouping set that can be used to stack or cluster column series in any arbitrary chart. A ColumnSet encapsulates the same grouping behavior used in a ColumnChart, but can be used to assemble custom charts based on CartesianChart. ColumnSets can be used to cluster any chart element type that implements the <strong>IColumn interface</strong>. It can stack any chart element type that implements the IColumn and IStackable interfaces. Since <strong>ColumnSet itself implements the IColumn interface</strong>, you can use ColumnSets to cluster other ColumnSets to build more advanced custom charts.”</em></p>
<p>Summarizing the above statement, we can group the two column series in a column set and in this way we can apply same properties that a Column Chart persists like Chart Type which in our case is ‘stacked’. Similarly in Bar Charts, there is a concept of <strong>BarSet</strong>.</p>
<div style="width: 100%;"><img class="aligncenter" title="ColumnSet" src="http://xebee.xebia.in/wp-content/uploads/2011/03/ColumnSet-300x253.jpg" alt="Exhibiting Column Set" width="300" height="253" /></div>
<pre class="brush: java; title: ; notranslate">
&lt;mx:series&gt;
    &lt;mx:ColumnSet type=&quot;stacked&quot;&gt;
       &lt;mx:ColumnSeries yField=&quot;bottledSales&quot; displayName=&quot;Bottled Sales&quot; /&gt;
       &lt;mx:ColumnSeries yField=&quot;cannedSales&quot; displayName=&quot;Canned Sales&quot; /&gt;
    &lt;/mx:ColumnSet&gt;
    &lt;mx:LineSeries yField=&quot;total&quot; displayName=&quot;Total Sales&quot;/&gt;
&lt;/mx:series&gt;
</pre>
<p>The only change observed in the code is that now the two column series are wrapped into a column set and the <strong>type = “stacked”</strong> property is removed from the level of Column Chart &amp; is added to the Column Set, instead.</p>
<p>Now if we run our modified code, it runs successfully showing the desired results.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_SingleColumnSet_716354707"
			class="flashmovie"
			width="550"
			height="400">
	<param name="movie" value="http://xebee.xebia.in/wp-content/uploads/2011/03/SingleColumnSet.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://xebee.xebia.in/wp-content/uploads/2011/03/SingleColumnSet.swf"
			name="fm_SingleColumnSet_716354707"
			width="550"
			height="400">
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p><a href="http://xebee.xebia.in/wp-content/uploads/2011/03/SingleColumnSet.zip" target="_self">Download Source Code</a></p>
<p><strong>Example 2 – Composite Chart (Column &amp; Line) with multiple axes</strong></p>
<p><strong> </strong></p>
<p>Using the same problem as stated above, idea is to create the above mentioned composite chart with the Line Series now representing a separate &amp; distinct measure named ‘<strong>No. of Sales Persons Involved</strong>’ with a <strong>separate vertical axis</strong> for the same.</p>
<p>Now the key things that we can make out from this statement are that we have an extra series measure as ‘numSalesPerson’ with an additional vertical axis for it plus we are able to <strong>visualize some indirectly related data</strong> within the current chart. Also now the two vertical axes represent two distinct measures altogether (one representing ‘Sales in currency’ &amp; other ‘No. of Sales Persons’).</p>
<p>An important change to be considered is that instead of having a common vertical axis for the whole chart we will declare two vertical axes:</p>
<ol>
<li><strong>LeftVerticalAxis –</strong> to be used for plotting the entire Column set (which is wrapping the two column series, so there is no need of separate vertical axis for each of them) along with its Axis Renderer with the placement property as ‘<strong>left</strong>’.</li>
<li><strong>RightVerticalAxis – </strong>to be used for plotting the Line series along with its Axis Renderer with the placement property as ‘<strong>right</strong><strong>’</strong>.</li>
</ol>
<p>However, the logic for implementing the column chart remains the same as stated above.</p>
<pre class="brush: java; title: ; notranslate">
...
[Bindable]
private var delhi:ArrayCollection = new ArrayCollection([
{productName:&quot;Coke&quot;,bottledSales:200,cannedSales:500,total:700,numSalesPerson:200},
{productName:&quot;Pepsi&quot;,bottledSales:400,cannedSales:700,total:1100,numSalesPerson:100},
{productName:&quot;Sprite&quot;,bottledSales:300,cannedSales:600,total:900,numSalesPerson:180}
]);
...
&lt;mx:verticalAxisRenderers&gt;
	&lt;mx:AxisRenderer placement=&quot;left&quot; axis=&quot;{leftVerticalAxis}&quot;/&gt;
	&lt;mx:AxisRenderer placement=&quot;right&quot; axis=&quot;{rightVerticalAxis}&quot;/&gt;
&lt;/mx:verticalAxisRenderers&gt;
&lt;mx:series&gt;
        &lt;mx:ColumnSet type=&quot;stacked&quot;&gt;
                &lt;mx:verticalAxis&gt;
                     &lt;mx:LinearAxis id=&quot;leftVerticalAxis&quot;
                                    title=&quot;Canned/Bottled Sales&quot;/&gt;
                &lt;/mx:verticalAxis&gt;
                &lt;mx:ColumnSeries yField=&quot;bottledSales&quot; displayName=&quot;Bottled Sales&quot;
                                 verticalAxis=&quot;{leftVerticalAxis}&quot;/&gt;
                &lt;mx:ColumnSeries yField=&quot;cannedSales&quot; displayName=&quot;Canned Sales&quot;
                                 verticalAxis=&quot;{leftVerticalAxis}&quot;/&gt;
        &lt;/mx:ColumnSet&gt;
        &lt;mx:LineSeries yField=&quot;numSalesPerson&quot;
                       displayName=&quot;No. of Sales Persons  involved&quot;&gt;
	        &lt;mx:verticalAxis&gt;
                &lt;mx:LinearAxis id=&quot;rightVerticalAxis&quot; title=&quot;No. of Sales Persons&quot;/&gt;
	        &lt;/mx:verticalAxis&gt;
        &lt;/mx:LineSeries&gt;
&lt;/mx:series&gt;
</pre>
<p>The Output generated is as follows:</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_ColumnSetWithMultipleAxis_1450079363"
			class="flashmovie"
			width="600"
			height="400">
	<param name="movie" value="http://xebee.xebia.in/wp-content/uploads/2011/03/ColumnSetWithMultipleAxis.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://xebee.xebia.in/wp-content/uploads/2011/03/ColumnSetWithMultipleAxis.swf"
			name="fm_ColumnSetWithMultipleAxis_1450079363"
			width="600"
			height="400">
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p><a href="http://xebee.xebia.in/wp-content/uploads/2011/03/ColumnSetWithMultipleAxis.zip" target="_self">Download Source Code</a></p>
<p>Here in this example, we added an extra vertical axis with its corresponding axis renderer. On the similar lines, we can add <strong>Multiple Horizontal Axes</strong> along with their corresponding <strong>Horizontal Axis Renderers </strong>with axis placement as either ‘<strong>top</strong>’ or ‘<strong>bottom</strong>’.</p>
<p>In this way I learned how to create Flex Composite Charts with multiple series &amp; axes.  If you know about other ways to solve this problem, please feel free to drop me a line.</p>
<p>In my next blog we will raise the complexity to a next level and will learn how to make <strong>Complex</strong> Charts with <strong>Multiple Categories</strong>.<br />
(<span style="color: #000000;"><strong>Update</strong></span>: The blog is <a href="http://xebee.xebia.in/2011/03/29/flex-creating-complex-charts-using-multiple-categories/" target="_blank">live</a> now)</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/03/24/flex-composite-charts-with-multiple-series-axes/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Polling From JavaFx</title>
		<link>http://xebee.xebia.in/2011/03/22/polling-from-javafx/</link>
		<comments>http://xebee.xebia.in/2011/03/22/polling-from-javafx/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 12:04:52 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[JavaFX]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=8003</guid>
		<description><![CDATA[If you have chosen JavaFx as an interoperable language, might be over swings, then your most common use case will include following Sun's guidelines that says "while creating the components or changing a component's UI state you must do it inside the EDT (Event Dispatch Thread)". While your Swing application runs from the main thread, [...]]]></description>
			<content:encoded><![CDATA[<p>If you have chosen JavaFx as an interoperable language, might be over swings, then your most common use case will include following Sun's guidelines that says "while creating the components or changing a component's UI state you must do it inside the EDT (Event Dispatch Thread)".</p>
<p>While your Swing application runs from the main thread, you will have to take care of threading as otherwise your application will behave unresponsive while doing long computations.</p>
<p>In JavaFx, every application always always runs inside the Event Dispatch Thread. This means that though you no longer have to worry about repaint issues when changing the state of your stages, but  you still need to take care of long computations as they will be run inside the EDT.<span id="more-8003"></span></p>
<p><a rel="attachment wp-att-8005" href="http://xebee.xebia.in/2011/03/22/polling-from-javafx/withoutasynchandling/"><img class="size-full wp-image-8005 alignleft" title="withoutasynchandling" src="http://xebee.xebia.in/wp-content/uploads/2011/03/withoutasynchandling.png" alt="" width="310" height="207" /></a><span style="color: #ffffff;"> </span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;"> </span>The <em>javafx.async</em> of JavaFx 1.2 package can be used when you need to perform any  background  work like polling for some activity being done at the back end(say java) which you don't want to run on the main JavaFX thread.</p>
<p>For example,  you are doing some file IOs, or maybe  some serious number update and  if you do them on your main thread, the user would be blocked from performing anything on UI  as it will seem to be hanged.</p>
<p>Following is the way to implement this usecase in your JavaFx Application via two abstract classes namely <em><strong>JavaTaskBase</strong></em> and <em><strong>RunnableFuture</strong></em></p>
<p>First of all you need a Java class that implements Runnablefuture like:</p>
<pre class="brush: java; title: ; notranslate">
public class MyTaskCompletionTracker implements RunnableFuture {
private MyVarible myVar;
private MyVaribleStatusTracker myVarStatusLive;

public MyTaskCompletionTracker(MyVarible myVar, MyVaribleStatusTracker myVarstatus) {
    this.myVar = myVar;
    objectRef = ObjectsFactory.getJavaClassReference();
    myVarStatusLive = myVarstatus;
}

@Override public void run() throws Exception {
    while (true) {
        if (objectRef.getMyVaribleStatus(myVar) &lt;= 100){
            setMyVaribleStatus(MyVaribleStatus.DONE); break;
        }
        log.info(&amp;quot;MyVarible is still updating &amp;quot;);
        Thread.sleep(1000);
     }
 }

void setMyVaribleStatus(final MyVaribleStatus myVarStatus) {
javafx.lang.FX.deferAction(new Function0&lt;Void&gt;() {
    @Override public Void invoke() {
        myVarStatusLive.updateMyVaribleStatus(myVarStatus);
        return null;
     }
   });
 }
}
</pre>
<p>The start() method called on above class will cause run() method to start executing and updating the value of MyVar till it comes to 100.</p>
<p><span style="color: #000000;"><strong><em>FX.deferAction()</em></strong></span>causes the the passed function to be invoked <span style="color: #000000;">from the EDT</span></p>
<p>Our Second class would be "<strong>MyTaskCompletionManager</strong>" which is a JavaTaskBase. This class overrides the create() method and create/return the <span style="font-family: courier new,courier,monospace;">RunnableFuture </span>class implemented before.</p>
<pre class="brush: java; title: ; notranslate">
public class MyTaskCompletionManager extends JavaTaskBase {
private MyVarible myVar;
private Log log = LogFactory.getLog(this.getClass());
MyVariableStatusTracker MyVariableStatusTracker;

public MyTaskCompletionManager(MyVarible myVar, MyVariableStatusTracker jobstatus) {
    this.myVar = myVar;
    MyVariableStatusTracker = jobstatus;
}

@Override
public RunnableFuture create() {
    return new MyTaskCompletionTracker(myVar, MyVariableStatusTracker);
}
}
</pre>
<p>You can see another class named <strong>MyVariableStatusTracker</strong>, which can be optionally used to get the live update of things going on that separate thread (<strong><span style="font-family: courier new,courier,monospace;">FX.deferAction()</span></strong> has been used to invoke this).</p>
<pre class="brush: java; title: ; notranslate">
public interface MyVariableStatusTracker {
    void updateMyVaribleStatus(MyVaribleStatus status);
}
</pre>
<p><a rel="attachment wp-att-8033" href="http://xebee.xebia.in/2011/03/22/polling-from-javafx/pollingfromjavafx/"><img class="size-full wp-image-8033 alignleft" title="pollingFromJavaFx" src="http://xebee.xebia.in/wp-content/uploads/2011/03/pollingFromJavaFx.png" alt="" width="581" height="370" /></a></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;">..</span></p>
<p><span style="color: #ffffff;">.</span></p>
<p><span style="color: #ffffff;"><br />
</span></p>
<p>Using this way, you can poll from your back end 'n' number of updated values of your variables,  provided that you have invoked one call to Start per instance of your runnable class.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/03/22/polling-from-javafx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java and Ruby integration via SOAP</title>
		<link>http://xebee.xebia.in/2011/03/15/java-and-ruby-integration-via-soap/</link>
		<comments>http://xebee.xebia.in/2011/03/15/java-and-ruby-integration-via-soap/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 11:19:57 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[SOAP]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7989</guid>
		<description><![CDATA[In my last blog we talked about Ruby and Java integration via JRuby. Since JRuby runs on JVM, bytecode can be shared but in case you do not want a JVM level integration then SOAP is usually your next level of support. Imagine a scenario where you want to call a SOAP server written in [...]]]></description>
			<content:encoded><![CDATA[<p>In my last blog we talked about Ruby and Java integration via JRuby. Since JRuby runs on JVM, bytecode can be shared but in case you do not want a JVM level integration then SOAP is usually your next level of support.</p>
<p>Imagine a scenario where you want to call a SOAP server written in Java from Ruby, this is quite common as most enterprises have their middleware written in Java and new application can be written quickly in Ruby/Rails. Here is how you can go about integrating the two -</p>
<p><span id="more-7989"></span><br />
<span style="color: #0000ff;"><strong>The Java Server</strong></span></p>
<p>I am not going to cover this in detail here but for new deployments Apache CXF is quite popular. You can integrate it with Spring as given <a href="https://cwiki.apache.org/CXF20DOC/writing-a-service-with-spring.html">here</a>. The Maven dependencies are as follows -</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;properties&gt;
		&lt;cxf.version&gt;2.3.3&lt;/cxf.version&gt;
		&lt;spring.version&gt;3.0.4.RELEASE&lt;/spring.version&gt;
	&lt;/properties&gt;

	&lt;dependencies&gt;
		&lt;!-- CXF dependencies --&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
			&lt;version&gt;${cxf.version}&lt;/version&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
			&lt;version&gt;${cxf.version}&lt;/version&gt;
		&lt;/dependency&gt;
        &lt;!-- End CXF dependencies --&gt;

        &lt;!-- Spring dependencies --&gt;
        &lt;!-- add other dependencies --&gt;
	&lt;/dependencies&gt;
</pre>
<p>The Java code looks like -</p>
<pre class="brush: java; title: ; notranslate">
@WebService
public interface EmployeeService {

	Employee findEmployeeByID(@WebParam(name = &quot;employeeID&quot;)long empID);
	boolean storeEmployee(@WebParam(name = &quot;employee&quot;)Employee emp);

}
</pre>
<p>And the Implementation looks like -</p>
<pre class="brush: java; title: ; notranslate">
@Component(&quot;employeeService&quot;)
@WebService(endpointInterface = &quot;in.mysoapserver.services.EmployeeService&quot;)
public class EmployeeServiceImpl implements EmployeeService {

	@Override
	public Employee findEmployeeByID(long empID) {
		Employee employee = new Employee();
		employee.setEmpID(101);
		employee.setName(&quot;Rocky&quot;);
		employee.setAge(32);
		return employee;
	}

	@Override
	public boolean storeEmployee(Employee emp) {
		//Store Employee
		return true;
	}

}
</pre>
<p>After deploying the project in Tomcat you can get the WSDL from a link like - <strong>http://localhost:8080/mysoapserver/soap?wsdl</strong></p>
<p>Once you have the WSDL you should use SoapUI for some testing to check if the SOAP requests are working.</p>
<p><span style="color: #0000ff;"><strong>The Ruby Client</strong></span><br />
Now we are ready to create the SOAP client in Ruby. Please note the instructions below are same for Ruby or JRuby.</p>
<p>First install soap4r gem -<br />
<strong>gem install soap4r</strong></p>
<p>Download (and unpack) the soap4r binary .tar.gz also from <a href="http://dev.ctor.org/soap4r">here</a></p>
<p>Now, just to organize things create a folder say "ruby_soap_client" and copy the WSDL of the SOAP services we created there.</p>
<p>Got to the folder where the WSDL is copied and run -<br />
<strong>~/01rocky/02apps/soap4r-1.5.8/bin/wsdl2ruby.rb --type client --wsdl mysoapserver.wsdl</strong></p>
<p>* Change the path to wsdl2ruby.rb as per your setup.</p>
<p>This will create a set of Ruby scripts and also create an example client. Since we will make our own client you can safely delete the *Client.rb and *Driver.rb scripts.</p>
<p>Now let us create our own Ruby client -</p>
<pre class="brush: plain; title: ; notranslate">
require 'soap/wsdlDriver'
require 'EmployeeServiceImplService.rb'

wsdl = &quot;mysoapserver.wsdl&quot;

employee_service = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver

response = employee_service.findEmployeeByID(FindEmployeeByID.new(10))
puts response.return.name
puts response.return.age

response = employee_service.storeEmployee(StoreEmployee.new(Employee.new(30,102,&quot;Tushar&quot;)))
puts response.return
</pre>
<p>Lets examine each line in detail.<br />
Line 1 - Just loading the required libraries for soap4r<br />
Line 2 - The 3rd file that wsdl2ruby.rb script generated. We'll look at it in a minute.<br />
Line 4 - Just a variable for the wsdl file name. Change it according to your setup.<br />
Line 6 - We create a SOAP RPC driver using the wsdl we saved earlier.<br />
Line 8/12 - Next we make the SOAP call. But wait a minute, what is being passed as a parameter here?</p>
<p>The answer to this can be found if we look at the SOAP request we made from SoapUI -</p>
<pre class="brush: xml; title: ; notranslate">
&lt;soapenv:Envelope xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; xmlns:ser=&quot;http://services.mysoapserver.in/&quot;&gt;
   &lt;soapenv:Header/&gt;
   &lt;soapenv:Body&gt;
      &lt;ser:findEmployeeByID&gt;
         &lt;employeeID&gt;10&lt;/employeeID&gt;
      &lt;/ser:findEmployeeByID&gt;
   &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;
</pre>
<p>And for storeEmployee call -</p>
<pre class="brush: xml; title: ; notranslate">
&lt;soapenv:Envelope xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; xmlns:ser=&quot;http://services.mysoapserver.in/&quot;&gt;
   &lt;soapenv:Header/&gt;
   &lt;soapenv:Body&gt;
      &lt;ser:storeEmployee&gt;
         &lt;employee&gt;
            &lt;age&gt;30&lt;/age&gt;
            &lt;empID&gt;102&lt;/empID&gt;
            &lt;name&gt;Tushar&lt;/name&gt;
         &lt;/employee&gt;
      &lt;/ser:storeEmployee&gt;
   &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;
</pre>
<p>If we ignore the XML namespaces, our request is wrapped in a "findEmployeeByID" tag (for the findEmployeeByID call). Therefore, when we gave the wsdl2ruby.rb scpirt our WSDL reference, it created the equivalent Ruby classes for all wrappers, request and response types and stored it in a file which we referenced at Line 2.</p>
<p>So looking at the sample requests in SoapUI we can create wrapper and request objects and similarly parse the response received. Its as simple as that. In case you are stuck, you can look at all the classes created by the wsdl2ruby script by having a look at the generated file (EmployeeServiceImplService.rb in our case).</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/03/15/java-and-ruby-integration-via-soap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex: Validator versus TextInput&#8217;s restrict</title>
		<link>http://xebee.xebia.in/2011/02/28/flex-textinputs-custom-validator/</link>
		<comments>http://xebee.xebia.in/2011/02/28/flex-textinputs-custom-validator/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 18:46:12 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7934</guid>
		<description><![CDATA[I came across a requirement where i need to restrict user from entering numeric values. The first solution that came into my mind was to simply restrict the input textfield, by using TextInput's restrict method. During the sprint demo, a small suggestion came (from a usability perspective) - Instead of restricting user, can't i alert [...]]]></description>
			<content:encoded><![CDATA[<p>I came across a requirement where i need to restrict user from entering numeric values. The first solution that came into my mind was to simply restrict the input textfield, by using TextInput's restrict method.</p>
<p>During the sprint demo, a small suggestion came (from a usability perspective) - <em>Instead of restricting user, can't i alert him with some validation errors?</em>. It was a nice thought, as user can be shown with the reasons of this error, which is not possible if we simply 'restrict' the user. <span id="more-7934"></span></p>
<p>So after a small R&amp;D, i was able to write a validator for the same. <a href="http://xebee.xebia.in/wp-content/uploads/2011/03/ValidateAlphabets.zip">Attached</a> is the code. The end result was - The textfield will show validation errors if there are any numeric values found.</p>
<p>The main trick here was to override the 'doValidation()' method.</p>
<p>The highlights of this method are:</p>
<ul>
<li> Override this method in your custom validator class</li>
<li> Contains the logic for validation.</li>
<li> The result of validation is stored in _validationResults, which accepts objects of type ValidationResult.</li>
<li> ValidationResult contains the error message to be displayed in the tooltip.</li>
</ul>
<pre class="brush: plain; title: ; notranslate">
override protected function doValidation(value:Object):Array {
			var trimmedValue:String = StringUtil.trim(String(value));
			_validationResults = super.doValidation(trimmedValue);

			if(_validationResults.length &gt; 0 || trimmedValue.length == 0)
				return _validationResults;

			if(!CharacterUtil.validateCharacters(DECIMAL_DIGITS, trimmedValue)) {
				_validationResults.push(new ValidationResult(true, null,
                                ApplicationConstants.INVALID_CHARACTER,
                                _messageForInvalidCharacter));
				return _validationResults;
			}
			else {
				Alert.show(&quot;No validation errors found&quot;, &quot;Alert&quot;);
			}

			return _validationResults;
		}
</pre>
<p>CharacterUtil is the class which encapsulates the logic to check for the numeric values in the entered characters. If you want to write your custom validator, just change the method written inside this class, with your checks and conditions.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/28/flex-textinputs-custom-validator/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Maven Lucene Plugin 1.0 : Documentation and Usage</title>
		<link>http://xebee.xebia.in/2011/02/28/maven-lucene-plugin/</link>
		<comments>http://xebee.xebia.in/2011/02/28/maven-lucene-plugin/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 17:40:27 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[Maven]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7915</guid>
		<description><![CDATA[Maven Lucene Plugin is an open source maven plugin for Apache Lucene developed by Paritosh Ranjan of  Xebia India IT Architects Ltd . The project is hosted on SourceForge and can be found here. It is released under GNU General Public License (GPL).

]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">
<h2><span style="text-decoration: underline;"><strong>Maven Lucene Plugin</strong></span></h2>
<p style="text-align: justify;">Maven Lucene Plugin is an open source maven plugin for Apache Lucene developed by<a title="Xebia India" href="http://www.xebiaindia.com/" target="_blank"> Xebia India IT Architects Ltd</a> . The project is hosted on SourceForge and can be found <a title="Maven Lucene Plugin" href="https://sourceforge.net/projects/lucene-plugin/" target="_blank">here</a>. It is released under GNU General Public License (GPL).</p>
<p>The artifact is uploaded at Central Maven Repository <a title="Central Maven Repository" href="http://repo1.maven.org/maven2/com/xebia/" target="_blank">http://repo1.maven.org/maven2/com/xebia/</a>. You can browse the artifact <a title="OSS Sonatype Repository" href="https://oss.sonatype.org/index.html#nexus-search;quick~maven-lucene-plugin" target="_blank">here</a>.</p>
<p><strong>maven-lucene-plugin</strong> creates a Lucene index from a file source. The structure of the lucene index i.e. fields, analyzers, indexLocation, fileSourceLocation, store etc can be configured in a configuration file lucene.xml.</p>
<p><strong>lucene.xml</strong> contains all information regarding the lucene index and the data source (from which the index is created). The Maven Lucene Plugin looks for lucene.xml file in the project root directory (adjacent to pom.xml) and creates the lucene index from the file source mentioned in lucene.xml based on the index configuration provided.<span id="more-7915"></span></p>
<p style="text-align: justify;"><span style="text-decoration: underline;">Apache Lucene Version</span></p>
<p style="text-align: justify;">The maven-lucene-plugin uses Lucene version 3.0.3. The index can be opened using Luke 1.0.1. Luke can be downloaded from <a title="Download Luke" href="http://luke.googlecode.com/files/lukeall-1.0.1.jar" target="_blank">here</a>.</p>
<h3><span style="text-decoration: underline;"><strong>Configuring plugin in pom.xml</strong></span></h3>
<p style="text-align: justify;">Configuring the <strong>maven-lucene-plugin</strong> in <strong>pom.xml</strong> is very simple. All information about index configuration needs to be written in <strong>lucene.xml</strong>. Index can be created by running “<strong>createIndex</strong>” goal in the plugin. It can be done by running the goal during any phase as shown in the example plugin configuration. OR it can be called by executing “<strong>createIndex</strong>” goal from command line by “<strong>mvn lucene:createIndex</strong>”.</p>
<p>The “<strong>createIndex</strong>” goal looks for a file “<strong>lucene.xml</strong>” in the project root directory (adjacent to pom.xml). The <strong>lucene.xml</strong> file needs to have all the information related to the configuration of index.</p>
<h4><span style="text-decoration: underline;">Example pom.xml is shown below:</span></h4>
<pre><strong>&lt;build&gt;
 &lt;plugins&gt;
  &lt;plugin&gt;
    &lt;groupId&gt;com.xebia&lt;/groupId&gt;
    &lt;artifactId&gt;maven-lucene-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.0&lt;/version&gt;
    &lt;executions&gt;
     &lt;execution&gt;
      &lt;phase&gt;install&lt;/phase&gt;
      &lt;goals&gt;
       &lt;goal&gt;createIndex&lt;/goal&gt;
      &lt;/goals&gt;
     &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;
 &lt;/plugins&gt;
&lt;/build&gt;</strong></pre>
<h3><span style="text-decoration: underline;">Example lucene.xml</span></h3>
<p style="text-align: justify;"><strong>maven-lucene-plugin</strong> looks for a file <strong>lucene.xml</strong> in the project root directory (adjacent to pom.xml). The <strong>maven-lucene-plugin</strong> will not work without <strong>lucene.xml</strong>. lucene.xml contains all the information about the lucene index.</p>
<h4>Example lucene.xml is provided below and each tag is explained in detail after that:</h4>
<pre><strong>&lt;index&gt;
  &lt;indexLocation&gt;C:\\index&lt;/indexLocation&gt;
  &lt;sourceFileLocation&gt;C:\\file\\data.txt&lt;/sourceFileLocation&gt;
  &lt;overWrite&gt;true&lt;/overWrite&gt;
  &lt;separator&gt;;&lt;/separator&gt;
  &lt;field&gt;
    &lt;name&gt;names&lt;/name&gt;
    &lt;type&gt;string&lt;/type&gt;
    &lt;analyzer&gt;WhiteSpaceAnalyzer&lt;/analyzer&gt;
    &lt;store&gt;true&lt;/store&gt;
  &lt;/field&gt;
  &lt;field&gt;
    &lt;name&gt;hobby&lt;/name&gt;
    &lt;type&gt;string&lt;/type&gt;
    &lt;analyzer&gt;SimpleAnalyzer&lt;/analyzer&gt;
    &lt;store&gt;true&lt;/store&gt;
  &lt;/field&gt;
&lt;/index&gt;</strong></pre>
<p>The parent tag is index. All other information is encapsulated inside it.</p>
<ol>
<li>
<pre><strong>&lt;indexLocation&gt;C:\\index&lt;/indexLocation&gt;</strong></pre>
<p>indexLocation tag points to the directory on your disk where the index will be created after the goal:createIndex is executed.</li>
<li>
<pre><strong>&lt;sourceFileLocation&gt;C:\\file\\data.txt&lt;/sourceFileLocation&gt;</strong></pre>
<p>sourceFileLocation tag points to the file on your disk which will be indexed.</li>
<li>
<pre><strong>&lt;overWrite&gt;true&lt;/overWrite&gt;</strong></pre>
<p>overWrite tag specifies whether the existing index present at the indexLocation (if any) should be deleted or should be overWritten</li>
<li>
<pre><strong>&lt;separator&gt;;&lt;/separator&gt;</strong></pre>
<p>separator tag specifies the delimiter between the field names and the data to be indexed in it. The default separator is ; (Please refer to Sample File Source Format described in the next section for more detailed information).</li>
<li>
<pre><strong>&lt;field&gt;
 &lt;name&gt;names&lt;/name&gt;
 &lt;type&gt;string&lt;/type&gt;
 &lt;analyzer&gt;WhiteSpaceAnalyzer&lt;/analyzer&gt;
 &lt;store&gt;true&lt;/store&gt;
&lt;/field&gt;</strong></pre>
</li>
</ol>
<p>A &lt;field&gt; specifies a Lucene Field. &lt;index/&gt; can have one or many &lt;field/&gt;.</p>
<p>A &lt;field&gt; should contain the following tags :</p>
<p>Following analyzers are supported by maven-lucene-plugin in release 1.0. The default is the WhitespaceAnalyzer.</p>
<ul>
<li><strong> "WhitespaceAnalyzer"</strong></li>
<li><strong> "SimpleAnalyzer"</strong></li>
<li><strong> "KeyWordAnalyzer"</strong></li>
<li><strong> "StopAnalyzer"</strong></li>
<li><strong> "StandardAnalyzer"</strong></li>
</ul>
<p>6. &lt;store&gt; specifies whether this field will be stored in the index or not.</p>
<h3><span style="text-decoration: underline;">Source File Format</span></h3>
<p>This is an example of file source ( file containing data to be indexed). The data in the file source should be written in the format explained below.</p>
<ul>
<li> The top row represents the field names separated by the separator.</li>
<li>The separator is the defined in lucene.xml.</li>
<li>The default separator is “;”.</li>
<li>The rows other than the top row contains values for the field.</li>
<li>The field name should be same as that specified in the &lt;field&gt;&lt;name&gt;fieldName&lt;/name&gt;&lt;/field&gt; tag in lucene.xml.</li>
</ul>
<p>The source file can be seen as a set of columns with the element at the top as the field name. Technically, each row other than the top row (name of fields) is considered as a lucene document.</p>
<p>For eg. in the example file data shown below, names and hobby are the field names.</p>
<address> “names” field has values “albert einstein” and “Leonardo da Vinci”.</address>
<address> “hobby” field has values “invention and discovery” and “Writing Painting”</address>
<p>Example File</p>
<pre><strong>names;hobby
albert einstein;invention and discovery
Leonardo da Vinci;Writing Painting</strong></pre>
<h2><span style="text-decoration: underline;">Maven Lucene Search</span></h2>
<p style="text-align: justify;">maven-lucene-search is a dependency which can be used to search lucene indexes without doing any Lucene specific coding.</p>
<p>It can be added by using dependency</p>
<pre><strong>&lt;dependency&gt;
 &lt;groupId&gt;com.xebia&lt;/groupId&gt;
 &lt;artifactId&gt;maven-lucene-search&lt;/artifactId&gt;
 &lt;version&gt;1.0&lt;/version&gt;
&lt;/dependency&gt;</strong></pre>
<p>It requires a <strong>lucene.xml</strong> file in src/main/resources. This lucene.xml file structure is same as described earlier for maven-lucene-plugin.</p>
<p>Including <strong>maven-lucene-search</strong> as a dependency provides a <strong>LuceneSearcher</strong> interface which has an implementation <strong>LuceneSearcherImpl</strong>. <strong>LuceneSearcher</strong> provides useful and simple methods to work on the Lucene Index created via the maven-lucene-plugin. It provides method to search on different fields and to delete different documents. The overhead of opening index reader and searcher and lucene specific stuff is taken care by the dependency.</p>
<p>The maven-lucene-search uses Lucene version 3.0.3.</p>
<h3><span style="text-decoration: underline;">Example Project</span></h3>
<p style="text-align: justify;">A example project which uses <strong>maven-lucene-plugin</strong> for indexing and <strong>maven-lucene-search</strong> dependency for searching can be found <a title="Example Project" href="https://lucene-plugin.svn.sourceforge.net/svnroot/lucene-plugin/client/" target="_blank">here</a>.</p>
<p style="text-align: justify;">
<address style="text-align: justify;">This project builds a Lucene index from a file <strong>C:\\file\\data.txt</strong>. So, either put data.txt in <strong>C:\\file\\</strong> with the content provided below or change the file location in <strong>lucene.xml</strong> in project root to the correct file. The index is created when <strong>mvn lucene:createIndex</strong> or <strong>mvn clean install</strong> is executed.</address>
<p>The <strong>data.txt</strong> should have the following data:</p>
<pre><strong>names;hobby
albert einstein;invention and discovery
Leonardo da Vinci;Writing Painting</strong></pre>
<p>The project also contains a file <strong>SearchExample.java</strong> which demonstrates the use of <strong>LuceneSearcher</strong> availabe in maven-lucene-search by searching the index created by the plugin.</p>
<h3><span style="text-decoration: underline;">Development and Contribution</span></h3>
<p style="text-align: justify;">The Maven Lucene Plugin is created by Xebia India IT Architects Ltd. It is an open source project hosted at Sourceforge. The project url is <a title="Maven Lucene Plugin" href="http://sourceforge.net/projects/lucene-plugin/" target="_blank">http://sourceforge.net/projects/lucene-plugin/</a>.</p>
<p>The source code of this project can be downloaded from <a title="SVN Repository at SourceForge" href="https://lucene-plugin.svn.sourceforge.net/svnroot/lucene-plugin/trunk/" target="_blank">SVN repository at SourceForge here</a>. The SVN contains these projects</p>
<p>1) <strong>maven-lucene-plugin</strong> - Maven plugin to create index.<br />
2) <strong>maven-lucene-search</strong> - Maven dependency to easily search on the index created by maven-lucene-plugin.</p>
<p>3) client - <em><strong>Example project</strong></em> which uses maven-lucene-plugin to create index and maven-lucene-search to search on the provided index.</p>
<p>New feature requests can be logged <a title="Feature Requests" href="https://sourceforge.net/tracker/?group_id=405195&amp;atid=1678696" target="_blank">here</a> and the bugs can be logged <a title="Bugs" href="https://sourceforge.net/tracker/?group_id=405195&amp;atid=1678693" target="_blank">here</a>. Support requests can be logged <a title="Support Requests" href="https://sourceforge.net/tracker/?group_id=405195&amp;atid=1678694" target="_blank">here</a>.</p>
<p>If you are interested in contributing to this project, then please contact pranjan@xebia.com.</p>
<h3><span style="text-decoration: underline;">Future Releases</span></h3>
<p style="text-align: justify;">In future releases, following features will be included. If you want any specific feature, please log it <a title="Feature Requests" href="https://sourceforge.net/tracker/?group_id=405195&amp;atid=1678696" target="_blank">here</a>.</p>
<ul>
<li>The maven-lucene-plugin should be able to create index from different datasources ( filesource, database, web, xml ).</li>
<li>Create annotations which can be used on fields of classes to index data.</li>
<li>Populate db from a lucene index using indexToDataBase goal.</li>
<li>Integrate luke in the maven-lucene-plugin. A maven goal will be created which opens luke initialized with the index locatioin provided in lucene.xml.</li>
<li>Provide easy to use utility methods for querying and updating the lucene index through a interface in maven-lucene-search.</li>
<li>Package the index as an artifact.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/28/maven-lucene-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Microsoft Web Camps for HTML5</title>
		<link>http://xebee.xebia.in/2011/02/28/html5-meetup-at-delhi/</link>
		<comments>http://xebee.xebia.in/2011/02/28/html5-meetup-at-delhi/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 13:02:31 +0000</pubDate>
		<dc:creator>Jayant Dhingra</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[Web 2.0]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7880</guid>
		<description><![CDATA[Microsoft venture into HTML5 got hold of my attention and led me to visit Microsoft HTML5 meetup on 4th Feb'11 at SCO Complex, Lodhi Road. The day started with warm tea and a light refreshing breakfast. It was a time to have a handshake with the attendees and ice breaking space with the speakers. The [...]]]></description>
			<content:encoded><![CDATA[<div>
<b>Microsoft venture into HTML5 </b>got hold of my attention and led me to visit Microsoft HTML5 meetup on 4th Feb'11 at SCO Complex, Lodhi Road. The day started with warm tea and a light refreshing breakfast. It was a time to have a handshake with the attendees and ice breaking space with the speakers. The speakers from Microsoft were very much enthusiastic with the launch of IE9 and new features being added/introduced to the browser.</p>
<p>The agenda of the event was to demonstrate MS intentions towards <span id="more-7880"></span>the latest waves in the industry. Though MS was silent for quite sometime for its venture in this field finally they came up with the IE9 beta version. MS is targeting to be the best in the browsers war in coming years considering the addons and the capabilities they have implemented in the browser. The HTML5 wave has been led by major browsers like Chrome, Opera, Firefox etc.</p>
<p>The <b style="font-family:verdana; font-size:18"><a href="http://www.w3schools.com/html5/default.asp">HTML5 Specification</a></b> is very interesting and lot of efforts seemed to have put in in building these features post HTML4. Browsers also seemed to have made efforts in complying with the new specification. There is the war being waged amongst the browser community as far as performance, efficiency and usability are concerned. The presenter did show the difference in the browsers capabilities by playing few HTML controls and hence claimed IE to be the best in the breed in coming years. I am not going to share the specification and the features in this article since it is readily available at W3C site and it is left for the reader to experience and decide about it. The only reason why one would choose IE9 or other browser is by testing the performance of the controls. There seems to be major difference in video performance in different browser, for an example, which is due to varied approaches in implementing either through GPU or only with CPU as it used to be earlier.</p>
<p>A new kid on the block-<b style="font-family:verdana; font-size:18">Pinned Sites</b> and MS is supporting various Indian vendors like <a href="http://songbuzz.rediff.com/#">rediff songbuzz</a> and others in broadcasting the updates to the subscribers. Use Pinned Sites to pin websites to the taskbar on your Windows 7 desktop so you can access them later with a single click. For more information about Pinned Sites, see "Pin a website" to your taskbar. Concept of pinned sites came up with their implementation with rediff songbuzz project in which the website is pinned and behaves like a desktop client. The data or the information is timely pushed by the server and the user creates a limited tasklist which he/she subscribes to. In this way user doesn't have to go to the website for regular updates and keeps himself updated.</p>
<p>Internet Explorer 9 is going to be more compliant with JavaScript standards-<b style="font-family:verdana; font-size:18"><a href="http://en.wikipedia.org/wiki/ECMAScript">ECMA4</a></b>. The browser has now improved its Javascript engine which will now work smoothly and efficiently on multicore CPUs.</p>
<p>You would have played 3D and online games as well and that works perfectly fine on windows platform with all the necessary setups and drivers installed. But the crucial point is that games require high end graphics rendering for which lots of computation is required to be done by CPU and GPU. <b style="font-family:verdana; font-size:18">Hardware Acceleration</b> uses the power of your computer's graphics processor (GPU) to speed up graphics-heavy tasks like video streaming or online gaming. Browsers are now-a-days started leveraging the GPU capabilities for rendering graphics on webpages. IE9 has now started using hardware acceleration for its graphics content and other stuff along with using CPU.</p>
<p>It was closed to afternoon when we had a break for lunch and needless to say that the arrangement was amazing. Soon after lunch we assembled in the conference hall and attended the rest of the sessions. The post lunch sessions were chosen to be light considering the lunch effect.</p>
<p><b style="font-family:verdana; font-size:18">CSS3 new features </b>and how it has eradicated long awaited improvements in Usability was the next topic of discussion.<br />
Couple of improvements made to CSS library are:</p>
<div style="float:left; margin-left:50px;">
<li>	Rounded corners via border-radius property</li>
<li>	CSS3 background and border features</li>
<li>	Opacity property</li>
<li>	RGBA, HSL, and HSLA color models</li>
<li>	CSS3 media queries</li>
<li>	CSS3 namespaces, CSS3 values and units</li>
<li>	CSS3 selectors</li>
</div>
<div style="float:left; margin-left:0px;">
<p><b style="font-family:verdana; font-size:18">Strong Javascript</b><br />
ECMAScript ES 3.1 was considered to be standard specification which had "JSON" object which was interoperable through well defined interfaces. Native JSON support started with IE8 and before that json2.js library used to be used on old browsers. JSON object is overridden in js but now browser started implemented JSON serialization and de-serialization since IE8. The js can directly create native JSON object provided by the browser. Since it is ECMA 4 compliant the script would run and behave the same way on all the browsers and would work faster. The <a href="http://blogs.msdn.com/b/ie/archive/2008/09/10/native-json-in-ie8.aspx">earlier problem</a> can also be referred to.</p>
<p>There were couple of videos explaining the features on IE9, MS ActionScript utilities in scenarios and its edge over other browsers. With this note we had a tea break and shared our experiences with the speakers. Post tea there was QnA session which brought an end to this happening event. In totality it was quite a learning session in the field of upcoming technologies which brought an insight into MS contribution to the web community in various capacities.</p>
<p>I really appreciate Microsoft who organized this event and enlightened us with this upcoming and cutting edge technologies' sessions and hope to attend similar kind of events regularly.
</p></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/28/html5-meetup-at-delhi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Should I Re-estimate?</title>
		<link>http://xebee.xebia.in/2011/02/19/should-i-re-estimate/</link>
		<comments>http://xebee.xebia.in/2011/02/19/should-i-re-estimate/#comments</comments>
		<pubDate>Sat, 19 Feb 2011 16:12:06 +0000</pubDate>
		<dc:creator>Robin Nagpal</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Estimation]]></category>
		<category><![CDATA[Estimation]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7841</guid>
		<description><![CDATA[You have already estimated story points for different stories in a project but in the midst of the sprint, you find that your estimates are amiss. This situation leads you in two minds about whether to re-estimate your user stories or not. There has already been much discussion surrounding this subject by various experts. But [...]]]></description>
			<content:encoded><![CDATA[<p>You have already estimated story points for different stories in a project but in the midst of the  sprint, you find that your estimates are amiss. This situation leads you in two minds about whether to re-estimate your user stories or not. There has already been much discussion surrounding this subject by various experts. But agile experts opinions are too many and at times very different also. There might be situations when none of their conceptions fit your project needs and you your self have to find a way out. In this blog I will talk about some of these view points and then I'll explain what adjustments we had to make to these processes to fit our project.</p>
<p><span id="more-7841"></span></p>
<p>First lets see <strong>when do we need to re-estimate</strong>.<br />
James Shore says that you should re-estimate when your understanding of a user story changes, which further affects the effort involved in completing the story. According to him</p>
<blockquote><p>You only need to re-estimate stories when your understanding of the story changes in a way that affects its difficulty or scope.</p></blockquote>
<p>Chris Johnson shares some similar thoughts on this. He says</p>
<blockquote><p>If, before playing a card, more information becomes available that directly reflects the implementation of a card, that card should be re-estimated.</p></blockquote>
<p>Mike Cohn adds some crucial information to these thoughts. He says that we should re-estimate only if the relative size for a story has changed.</p>
<blockquote><p>You should re-estimate only when your opinion of the relative size of one or more stories has changed.</p></blockquote>
<p><br/><br />
<strong>When should we not re-estimate</strong><br />
Chris Jhonson further suggests that we should not re-estimate when we are done with the user story. He explains,</p>
<blockquote><p>I think there is a time and place for re-estimating a story card, but after the card has been played it not one of them.</p></blockquote>
<p>Mike Cohn affirms his previous statement by explaining how velocity normalizes every thing, if effort for each story has increased rather than relative effort for a story.</p>
<blockquote><p>Do not re-estimate solely because progress is not coming as rapidly you as you’d expected.<br />
Let velocity, the great equalizer, take care of most estimation inaccuracies.</p></blockquote>
<p>Mike Cohn elaborates on all this by taking an example, and explaining various approaches that one may take for re-estimation. Below explained is an example similar to the one taken by him.<br />
<br/><br />
<a rel="attachment wp-att-7849" href="http://xebee.xebia.in/2011/02/19/should-i-re-estimate/estimation/"><img class="aligncenter size-full wp-image-7849" title="estimation" src="http://xebee.xebia.in/wp-content/uploads/2011/02/estimation.jpg" alt="" width="679" height="483" /></a></p>
<p><br/><br />
Suppose that team's velocity is 11 and team members decide to pick user stories 1,2 and 3 in 1st sprint, and user stories 3 and 4 in 2nd  sprint. Now when they start  working on user story 2, they find that this story is more complex and its complexity is actually equal to 8 story points. Since story 4 is similar to story 2, they feel that actual estimate of this story also, should be 8. As teams capacity is 11 story points, only user story 1 and 2 could be completed in sprint 1. Teams velocity for sprint 1 turns out to be 6.</p>
<p>Mike Cohn further explains scenarios for dealing with these types of situations.</p>
<p><strong>Scenario 1: No Re-estimation</strong><br />
Team does not re-estimate any of the user stories and takes the velocity of this sprint as 6. The average velocity in these situations will decrease, reflecting that the actual estimates were more than the initial estimates. Even though average velocity compensates for the bigger size of user story 2 and 4, but team still faces issues while committing for the next sprint as their velocity is 6, but they can actually commit 11 story points for next sprint.</p>
<p><strong>Scenario 2: Re-Estimating the Finished Story</strong><br />
As user story 2 was actually equal to 8 story points, team re-estimates this story when it completes this story. This keeps the average velocity of 11. This helps team for the next sprint estimation, as team is capable of actually covering 11 story points, which is equal to the velocity of sprint after re-estimation. However, still team will not be able to complete 11 story points in the sprint in which user story 4 is taken.</p>
<p><strong>Scenario 3: Re-Estimating When Relative Size Changes</strong><br />
In this approach, we re-estimate all the user stories whose relative size we feel have changed. In this case we re-estimate story 2 and 4 and give the new estimates to it. This approach helps in keeping the average velocity same(11 in this case), and helps team in making their commitment for next sprints.</p>
<p>Mike Cohn further talks about re-estimating partially  completed stories. He says</p>
<blockquote><p>I do not recommend giving partial credit for partially finished user stories. My preference is for a team to count the entire estimate toward their velocity (if they completely finished and the feature has been accepted by the product owner) or for them to count nothing toward their story otherwise.</p></blockquote>
<p>I personally feel that re-estimating doesn't lead to much value addition, but there might be some situations where re-estimation is the only option you are left with.</p>
<p>One such situation was when our client wanted an accurate estimate rather than the Fibonacci series that is followed initially during the estimation.   After every sprint, client felt, that as we had already worked on ticket, we should be able to give a much accurate estimate of effort spent. This was because he wanted to calculate  velocity more accurately or wanted to compare effort of stories completed with the ones that were there in the backlog. This is primarily due to client's lack of knowledge in Agile estimation and they don't understand how average velocity takes care of all these scenarios.</p>
<p>It is very important to understand the core need for re-estimation. I generally go with the third scenario explained by Mike Cohn in the above example i.e. "Re-Estimating When Relative Size Changes" and I dont mind twisting and tweaking the recommendations given by Agile experts.</p>
<p>There is no wisdom in blindly following the ideas of Agile experts. Every project has its own needs and scope.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/19/should-i-re-estimate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Has Agile Become Another Waterfall?</title>
		<link>http://xebee.xebia.in/2011/02/18/has-agile-become-another-waterfall/</link>
		<comments>http://xebee.xebia.in/2011/02/18/has-agile-become-another-waterfall/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 07:36:03 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7816</guid>
		<description><![CDATA[These days there is a lot of talk around the relevance of Agile principles in today's context. Some people talk about new Agile Menifesto which might make sense today and some even have termed it yet another waterfall already. To analyse this, first of all it's important to understand what Agile really means from pragmatic [...]]]></description>
			<content:encoded><![CDATA[<p>These days there is a lot of talk around the relevance of Agile principles in today's context. Some people talk about new Agile Menifesto which might make sense today and some even have termed it yet another waterfall already.</p>
<p>To analyse this, first of all it's important to understand what Agile really means from pragmatic point of view. To me, two things came out prominently which you can sugarcoat with many books, presentation, theories etc. However I think that is the crux of being agile:</p>
</p>
<ul>
<li>Inspect and adapt continuously</li>
<li>Agile is nothing but pure common sense.</li>
</ul>
<p><span id="more-7816"></span></p>
<p>There are reasons against each Scrum practice for instance. Those practices are then combined so that they are formalized to a large number of people for helping them out in the project execution. However that's not the end. To me that is just the beginning in the journey of being agile. If you understand it, you don't need to define or redefine the definitions based on time and context. You evolve continuously and at the end still called agile even after a number of years <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> . It's a lifestyle (way of life) and not yet another commodity. It can never become the next waterfall.</p>
<p>Now the argument comes that though from the outset it looks like that "Common Sense" argument makes a lot of sense but what would you term to those practices in Agile which are counter-intuitive?</p>
<p>As I indicated in the beginning that basic fundamental of Agile is "Inspect and Adapt". Even if you argue that there were or are some practices which are counter-intuitive, you are not bound to follow them. Whenever something is started with some principles in mind, it is done with the pure intention that these principles will be beneficial for the people. And with the span of time and with our experience, we all know that even with best analysis and with best intentions, some of the things work and some not.</p>
<p>The beauty here is, Agile doesn't expect you to get stuck just there and call it yet another waterfall. In case something doesn't work, you are expected to do "Inspect and Adapt" as depending on time and context, entire definitions change. Accordingly the practice also is bound to change. For instance, list of "Good to Great" companies made sense 10 years back but not anymore. So it doesnt mean the book is bad. It was written in a set context and time and for that time it made a lot of sense. </p>
<p>Similarly even after continuous "Inspect and Adapt" for years, the basic definition of what Agile means doesn't change.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/18/has-agile-become-another-waterfall/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Annotations To Inject &#8211; Metadata Driven AOP</title>
		<link>http://xebee.xebia.in/2011/02/16/using-annotations-to-inject-metadata-driven-aop/</link>
		<comments>http://xebee.xebia.in/2011/02/16/using-annotations-to-inject-metadata-driven-aop/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 14:42:04 +0000</pubDate>
		<dc:creator>Rohit Garg</dc:creator>
				<category><![CDATA[AOP]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[advisor]]></category>
		<category><![CDATA[Annotation]]></category>
		<category><![CDATA[aop]]></category>
		<category><![CDATA[interceptor]]></category>
		<category><![CDATA[metadata based processing]]></category>
		<category><![CDATA[pointcut]]></category>
		<category><![CDATA[processing]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7531</guid>
		<description><![CDATA[New releases of compilers are getting more and more cautious on taking off the pain of too much verbosity and making the code look much more cleaner, understandable and easily modifiable. A major step that has been taken in Java side is introduction of annotations. Now that they have introduced annotations, plugging in an annotation [...]]]></description>
			<content:encoded><![CDATA[<p>New releases of compilers are getting more and more cautious on taking off the pain of too much verbosity and making the code look much more cleaner, understandable and easily modifiable. A major step that has been taken in Java side is introduction of annotations. Now that they have introduced annotations, plugging in an annotation processor still seems like an unsolved job requiring changes of the level of JVM startup arguments.<br />
<span id="more-7531"></span><br />
<br/><br />
<strong><em>Issues with existing APT (Annotation Processing Tool) :</em></strong></p>
<ul>
<li>The existing API involves changes to the JVM arguments in case some change is required.</li>
<li>Changes at runtime will not be possible as once a annotation processor is started, it will add the processing instructions. You cannot change this behavior in an already running application.</li>
</ul>
<p>I was reading through one article that involved AOP and looked at one of the sample snippets that described about instrumenting Transactional attributes, so called boiler plate code for handling transactions into the services. The text clearly mentioned that it is possible or rather very easy to add metadata based advising into the code. After reading that line, I actually thought that it can be a possibility that the metadata processor or so called <a href="http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/aop/Pointcut.html">Pointcut</a> can be built based on annotation processing and the <a href="http://aopalliance.sourceforge.net/doc/org/aopalliance/aop/Advice.html">Advice</a> implementation can contain the code that you need to instrument or simply hide from your code because you think it is boiler plate.</p>
<p>By implementing this mechanism, you just change your application context file and thus avoid the headache of changing the startup arguments.<br />
Also you can <a href="http://xebee.xebia.in/2010/12/08/spring-altering-your-applicationcontext-at-runtime/">configure your context</a> prior to starting in case you don't want your annotations to become active.<br />
<br/><br />
<strong><em>The code part :</em></strong><br />
Usually its the most tricky part but in our case, this seems the least complex. There is one class named <a href="http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/aop/framework/autoproxy/DefaultAdvisorAutoProxyCreator.html">DefaultAdvisorAutoProxyCreator</a> which needs to be added to the usual <strong>applicationContext.xml</strong> file. You also need to create your own <a href="http://download.oracle.com/javase/1.5.0/docs/guide/language/annotations.html">Annotation</a> and define its settings. Last but not the least, you need a <a href="http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/aop/PointcutAdvisor.html">PointcutAdvisor</a> which will tell spring about which classes to process and what should be the processing.</p>
<p>In the sample code below, I would be adding a <strong>SpookyAnnotation</strong> on top of a bean and will allow the <strong>SpookyingInterceptor</strong> to create a proxy of the bean with the injected code. The <em>SpookyingInterceptor</em> does nothing but adds the advice of a <em>System.out.println</em> statement in the methods of the bean which has this annotation present.</p>
<p><center><em>applicationContext.xml</em></center></p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean:bean
  class=&quot;org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator&quot; /&gt;
&lt;bean:bean
  class=&quot;test.beans.interceptor.SpookyingInterceptor&quot; /&gt;&lt;/pre&gt;
</pre>
<p><center><em>Annotation</em></center></p>
<pre class="brush: java; title: ; notranslate">
@Retention(value= RetentionPolicy.RUNTIME)
public @interface SpookyAnnotation {
	boolean insertSpookiness() default true;
}
</pre>
<p><center><em>Interceptor class</em></center></p>
<pre class="brush: java; title: ; notranslate">
package test.beans.interceptor;

import ....
import test.annotations.SpookyAnnotation;
public class SpookyingInterceptor extends AbstractPointcutAdvisor{

	public Pointcut getPointcut() {
		return new Pointcut() {
			public MethodMatcher getMethodMatcher() {
				return new MethodMatcher() {
					public boolean matches(Method arg0, Class&lt;?&gt; arg1, Object[] arg2) {
						.....
					}
					public boolean matches(Method arg0, Class&lt;?&gt; arg1) {
						.....
					}
					public boolean isRuntime() {
						.....
					}
				};
			}

			public ClassFilter getClassFilter() {
				return new ClassFilter() {
					public boolean matches(Class&lt;?&gt; clazz) {
						if(clazz.getAnnotation(SpookyAnnotation.class) == null) {
							return false;
						} else {
							return clazz.getAnnotation(SpookyAnnotation.class)
								.insertSpookiness();
						}
					}
				};
			}
		};
	}

	public Advice getAdvice() {
		return new MethodBeforeAdvice() {
			public void before(Method method, Object[] methodArgs, Object objOfClazz)
					throws Throwable {
				System.out.println(&quot;The method &quot; + method.getName()
										+ &quot; has been spooked!!&quot;);
			}
		};
	}
}
</pre>
<p><center><em>Bean/Service classes</em></center></p>
<pre class="brush: java; title: ; notranslate">
package test.beans;
import test.annotations.SpookyAnnotation;
@SpookyAnnotation(insertSpookiness = false)
public class BeanWithNonSpookyCode {
	public void callMe() {
		System.out.println(&quot;non spooky one has been called&quot;);
	}
}
</pre>
<pre class="brush: java; title: ; notranslate">
package test.beans;
public class AnotherBeanWithNonSpookyCode {
	public void callMe() {
		System.out.println(&quot;non spooky one has been called&quot;);
	}
}
</pre>
<pre class="brush: java; title: ; notranslate">
package test.beans;
import test.annotations.SpookyAnnotation;
@SpookyAnnotation
public class BeanWithSpookyCode {
	public void callMe() {
		System.out.println(&quot;spooky one has been called&quot;);
	}
}
</pre>
<p><center><em>Bean definitions</em></center></p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean:bean id=&quot;beanWithNonSpooky&quot; class=&quot;test.beans.BeanWithNonSpookyCode&quot;  /&gt;
	&lt;bean:bean id=&quot;anotherBeanWithNonSpooky&quot;
				class=&quot;test.beans.AnotherBeanWithNonSpookyCode&quot;  /&gt;
	&lt;bean:bean id=&quot;beanWithSpooky&quot; class=&quot;test.beans.BeanWithSpookyCode&quot;  /&gt;
</pre>
<p><a href="http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/aop/MethodBeforeAdvice.html">MethodBeforeAdvice</a> is a standard class which instruments the code in before method before the method call.<br />
<br/></p>
<p><strong><em>Conclusion :</em></strong></p>
<ul>
<li>This style of coding is very highly plug and play because removing the <strong>PointcutAdvisor</strong> bean from <strong>applicationContext.xml</strong> will stop annotation processing for this particular annotation and you just need to add annotation to the class which you need to apply the <strong>Advice</strong> to. Rest of the code would remain untouched.</li>
<li>You might feel some startup delay with this code because initializing this structure and instrumenting code surely needs some time, but execution time remains unaffected.</li>
<li>You need <strong>CGLIB</strong> in your class-path for using <a href="http://static.springsource.org/spring/docs/2.0.1/reference/aop-api.html">AOP</a>. Rest is normal spring dependencies that are added to the project. </li>
<li>Java version should at-least be <strong>1.5</strong> because annotations are not supported below that.</li>
</ul>
<p><center><strong>~~~Happy Annotating~~~</strong></center></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/16/using-annotations-to-inject-metadata-driven-aop/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What makes me love Spring Web MVC 3.0</title>
		<link>http://xebee.xebia.in/2011/02/10/love-spring-web-mvc/</link>
		<comments>http://xebee.xebia.in/2011/02/10/love-spring-web-mvc/#comments</comments>
		<pubDate>Thu, 10 Feb 2011 04:37:34 +0000</pubDate>
		<dc:creator>Saket Vishal</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7790</guid>
		<description><![CDATA[There is a plethora of presentation frameworks, Spring Web MVC is just one of them, but with the recent versions, the changes introduced make it a mark above the rest. Following are few positives that caught my eye. Annotation based programming model for MVC Contollers With the introduction of @Controller, @RequestMapping ... creating controllers is [...]]]></description>
			<content:encoded><![CDATA[<p>There is a plethora of presentation frameworks, Spring Web MVC is just one of them, but with the recent versions, the changes introduced make it a mark above the rest. Following are few positives that caught my eye.</p>
<p><em>Annotation based programming model for MVC Contollers</em><br />
With the introduction of @Controller, @RequestMapping ... creating controllers is just so easy and clean. Give any flexible names to method names and parameters. No dependency on the Servlet API, but access to Servlet API is always available.<br />
<span id="more-7790"></span><br />
<em>Less code and Programming ease</em><br />
Whether you talk about simple cases such as using request parameters or session attribute, and accessing Request headers, or complicated cases such multipart(fileupload) support, and multiformat response, all are made easy using annotations.</p>
<p><em>Painfree exception handling</em><br />
HandlerExceptionResolver provides powerful programmatic exception handling mechanism, while the SimpleMappingExceptionResolver provides the same exception handling facility as provided by the Servlet API. Not to forget is the @ExceptionHandler, put it inside the contoller on a standard method, and do the needful, clean and simple.</p>
<p><em>Enhanced look and feel with theming</em><br />
Define the theme characterstics in a properties file or any other source, and then go ahead and use these properties through spring:theme in your jsps. ThemeResolvers makes it easy to figure out which theme to be used.</p>
<p><em>Simple Restification</em><br />
A combination of URI Templates and @PathVariable method parameter annotation is what is all enough for adding REST nature to the application.</p>
<p><em>Speedy prototyping with covention over configuration</em><br />
Stick to some naming conventions, and what you get is freedom from most of the configuration of Spring Web MVC. This can be really very helpful in case of rapid prototyping.</p>
<p>All these above mentioned attributes make a compelling case for use of Spring Web MVC as a preferred presentation framework. Though there can be many arguments against this choice depending upon the respective usage, still it remains my first choice.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/10/love-spring-web-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating JRuby and Java to create a mini rules engine</title>
		<link>http://xebee.xebia.in/2011/02/09/integrating-jruby-and-java-to-create-a-mini-rules-engine/</link>
		<comments>http://xebee.xebia.in/2011/02/09/integrating-jruby-and-java-to-create-a-mini-rules-engine/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 15:22:48 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[JRuby]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7778</guid>
		<description><![CDATA[Ruby is a beautiful language, but that is just me saying it. A thing of beauty has to be experienced on its own by someone. A major reason behind the slow adoption of Ruby in the enterprise is infrastructure / installation and speed. Although, personally I have never seen Ruby as slow (specially 1.9), but [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby is a beautiful language, but that is just me saying it. A thing of beauty has to be experienced on its own by someone. A major reason behind the slow adoption of Ruby in the enterprise is infrastructure / installation and speed. Although, personally I have never seen Ruby as slow (specially 1.9), but asking someone to run Ruby code on his/her machine is a problem as they need to install Ruby and other associated 'gems' used by my program. Enter <a href="http://www.jruby.org" target="_blank">JRuby</a> - it is a 100% pure Java implementation of the Ruby Programming Language, so in effect you can run a JRuby program on any machine that has a JVM. Just include a jar and you are good to go.<br />
<span id="more-7778"></span><br />
JRuby also integrates very easily with Java (both run on JVM) and helps you solve some pain areas in Java. I used it today in my project to dynamically (Ruby being a dynamic and interpreted language) generate and execute rules. Imagine a scenario on a website where you want to find a Customer's class from the loyalty points he has in his account. So lets say, if the customer has upto 1000 loyalty points he is "BRONZE" member, between 1000 and 2000 he is "SILVER" member and so on and so forth.</p>
<p>If this is done in pure Java, you can create these rules in your code but you cannot implement changes easily. For example, adding a new customer class will involve code change and server restart. Using a database, properties files or a rules engine will still not offer you a lot and will be difficult to setup and maintain and one can be assured that they will need to restart the server sooner or later as rules become complex. </p>
<p>However, if we implement this logic in JRuby we will have reasonably clean code and logic can be delegated to a clean and dynamic language like Ruby which even a business manager can maintain.</p>
<p>So lets get started. First let us add the JRuby jar to our project (through Maven) - </p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
&lt;groupId&gt;org.jruby&lt;/groupId&gt;
&lt;artifactId&gt;jruby-complete&lt;/artifactId&gt;
&lt;version&gt;1.5.6&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Now, let us create a simple Ruby script that will contain the logic -</p>
<pre class="brush: ruby; title: ; notranslate">
class CustomerClassSelector
  def choose_class(points)
    return &quot;BRONZE&quot; if (0..999).include?(points)
    return &quot;SILVER&quot; if (1000..1999).include?(points)
    return &quot;GOLD&quot; if (2000..2999).include?(points)
    return &quot;PLATINUM&quot;
  end
end
</pre>
<p>Save it as customer_class_selector.rb at a place where your project config lies. The code itself is pretty easy to understand even if you don't know Ruby syntax. The "(0..999)" is a Range in Ruby and it has a method "include?(param)" that returns true if the param lies in the Range.</p>
<p>Now for calling this code from Java -</p>
<pre class="brush: java; title: ; notranslate">
       String getCustomerClass(int loyaltyPoints) {
		ScriptingContainer container = new ScriptingContainer(LocalContextScope.THREADSAFE);
		container.setLoadPaths(Arrays.asList(&quot;/home/rocky/mysite/config&quot;));
		container.runScriptlet(&quot;require 'customer_class_selector'&quot;);
		Object greeter = container.runScriptlet(&quot;CustomerClassSelector.new&quot;);
		String customerClass = container.callMethod(greeter, &quot;choose_class&quot;, loyaltyPoints, String.class);
		return customerClass;
	}
</pre>
<ol>
<li>In this method, we initiate a Scripting container (package org.jruby.embed) that is available through our Maven dependency / jar added above. We pass it an argument so that container is not loaded as a singleton and the script is run every time its invoked. </li>
<li>Then through this container we load the path where JRuby scripts / libraries are (like classpath in Java).</li>
<li>We then load the scriptlet we saved earlier.</li>
<li>Next we intantiate the class defined in the Ruby script above.</li>
<li>Finally, we call the method choose_class passing the loyalty points and registering the return value type as String.</li>
</ol>
<p>We now can play with the rules inside the Ruby script as much as we want. Anyone can change the Ranges and add/remove Customer classes but we will never need to restart our web application or modify the Java code. That is the power of dynamic languages in action! Simple and powerful, ain't it <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/09/integrating-jruby-and-java-to-create-a-mini-rules-engine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Big bad projects</title>
		<link>http://xebee.xebia.in/2011/02/04/big-bad-projects/</link>
		<comments>http://xebee.xebia.in/2011/02/04/big-bad-projects/#comments</comments>
		<pubDate>Fri, 04 Feb 2011 05:25:20 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Quality]]></category>
		<category><![CDATA[Quality Assurance]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7755</guid>
		<description><![CDATA[A long time back (when I had more hair on my head), one of my managers remarked - "You know guys, I just met an old friend of mine who now works for _____ as a Project Manager and he said that he delivered a 18 months fixed price project right on time and right [...]]]></description>
			<content:encoded><![CDATA[<p>A long time back (when I had more hair on my head), one of my managers remarked - "You know guys, I just met an old friend of mine who now works for _____ as a Project Manager and he said that he delivered a 18 months fixed price project right on time and right on schedule. We need to have the same capabilities as ____." </p>
<p>I sat dumbfounded, I wanted to scream out "He was just lucky or he was lying or you should talk to the team members who worked in that team", but I didn't say anything because pesky "juniors" aren't looked upon very nicely in hierarchical organizations.</p>
<p>I now imagine myself having a conversation with the same manager in that same room, which goes something like this.<br />
<span id="more-7755"></span><br />
<strong>Me</strong> - "Lets play a game. Please indulge me. Can you tell me in exact seconds, the time you will take to reach the nearest door in this room."<br />
<strong>Manager</strong> - "Yes, around 10 seconds."<br />
<strong>Me</strong> - "Good. How can you say that?"<br />
<strong>Manager</strong> - "Coz its 15 feet and I think I can cover 15 feet in 10 seconds."<br />
<strong>Me</strong> - "Fair enough. Now can you tell me the time it will take for you to reach London from Delhi in exact number of seconds. Forget seconds, tell me in minutes."<br />
<strong>Manager</strong> - (after a pause) "Well, depending on flight time and the distance to airport approx 600 minutes."<br />
<strong>Me</strong> - "I have to tell you that even if there is one minute of delay, there is a huge penalty and what if your taxi is late or the flight is delayed ?"<br />
<strong>Manager</strong> - "One cannot say for sure. In fact, no one can tell you with exact certainty because too many un-predictable things can happen."<br />
<strong>Me</strong> - "How many times have you been to London?"<br />
<strong>Manager</strong> - "More than 8 times ."<br />
<strong>Me</strong> - "So you cannot say for certainty the exact time you will take for something which you have done for more than 8 times. But you could tell me the exact time you will take to reach for a nearby door. Why is that?"<br />
<strong>Manager</strong> - "Coz I can see the door. Geez, are you thick or something."<br />
<strong>Me</strong> - "Yes, I have always been a bit thick. But let us apply this analogy to software. You want me to tell you for sure the exact time it will take for me to develop a software which is unique in its own way and which no-one has developed before. But you yourself cannot tell me the exact time you will take to reach London although you have done it more than 8 times."<br />
<strong>Manager</strong> - "Hmmm ... what are you getting at?"<br />
<strong>Me</strong> - "What I am saying is, as you increase the distance or time horizon, uncertainty increases."<br />
<strong>Manager</strong> - "That is quite true."<br />
<strong>Me</strong> - "Yes, so what I can only say with a fair degree of certainty is where we will be in this project after 1-2 weeks."<br />
<strong>Manager</strong> - "You maybe right, but that is not how it works. The customer asks how long will it take to build the whole thing."<br />
<strong>Me</strong> - "Why do think they do that?"<br />
<strong>Manager</strong> - "I guess they feel safe this way, they can allocate a budget to it."<br />
<strong>Me</strong> - "Again, I am a bit thick. So a customer looks at a project, lets say a Reporting System and thinks this work should take 6 months to build for 4 people ergo the time is 6 months and budget is $10,000 or something like that. Do they have the expertise to make this call?"<br />
<strong>Manager</strong> - "Hmmm .. maybe they have the expertise or maybe they don't and sometimes they even ask us to do this."<br />
<strong>Me</strong> - "I am not getting it, why do they do this every single time if it is so error prone and they do not trust even themselves."<br />
<strong>Manager</strong> - "Coz maybe they feel safe."<br />
<strong>Me</strong> - "Ok. So they allocate a budget and outsource to project to someone, asking them to complete it in 6 months or give a penalty. They can sleep easy this way."<br />
<strong>Manager</strong> - "Yes. I think that's it!"<br />
<strong>Me</strong> - "But if I say, I will give it my best and give you a commitment for only the next two weeks of work and see how it goes from there. What would a customer say."<br />
<strong>Manager</strong> - "I don't think he would agree."<br />
<strong>Me</strong> - "Why?"<br />
<strong>Manager</strong> - "Coz he doesn't know when his project will end ?"<br />
<strong>Me</strong> - "But I am working hard and in the best way I can. Which is in no way different than the 6 months commitment I make."<br />
<strong>Manager</strong> - "But he wants a deadline, what if you are slacking?"<br />
<strong>Me</strong> - "Bingo!! Its because the work is done somewhere in a different location and you cannot trust someone is why you want deadlines."<br />
<strong>Manager</strong> - "Yes, I guess that is what outsourcing is about."<br />
<strong>Me</strong> - "But if you trust me as your partner who is fully committed to the project, does the two week commitment sound good."<br />
<strong>Manager</strong> - "Yes. I think so. But I still don't buy it. We have delivered many projects on time after giving a long term commitment."<br />
<strong>Me</strong> - "We all know how that happens. People spend nights in office and quality goes for a toss. Giving the same international travel analogy you put a gun to the pilots head and ask him to fly fast coz you made a commitment to reach London in 10 hours. Except you cannot do that on a plane but you can do it with us developers. Geez... and then people complain about the high rate of software project failures and late bug discovery."<br />
<strong>Manager</strong> - "Hmmm..."<br />
<strong>Me</strong> - "If I say there is a clause that no-one will work beyond 9 hours, how many of your so called successful commitments be successful ?"<br />
<strong>Manager</strong> - "Not a lot."<br />
<strong>Me</strong> - "Just because you can do it, doesn't mean you should."<br />
<strong>Manager</strong> - "I kinda agree, I remember my days when I had to spend 3 nights in the office to deliver a project and I can tell you the code we wrote was shit."<br />
<strong>Me</strong> - "And yet it continues. Why is that?"<br />
<strong>Manager</strong> - "You are irritating me. I say its again its because the customer wants a deadline. He cannot give us a free hand to deliver the project when we say its ready. They don't trust us that much."<br />
<strong>Me</strong> - "Yes. And that my friend is the problem. Trust. If you can monitor each and every second of my day I guess you would be very comfortable with the 2 week work schedule, lets call it a Sprint."<br />
<strong>Manager</strong> - "Yes. Good idea."<br />
<strong>Me</strong> - "If I give you a daily status report, put cameras in my working area and give you a working software demo every two weeks this trust can be built."<br />
<strong>Manager</strong> - "Sounds good. Maybe we can try it."<br />
<strong>Me</strong> - "Yes, lets build that trust by delivering high quality software regularly without making the team slog and lets make our customers really happy."<br />
<strong>Manager</strong> - "And what's there in it for the customer apart from your so called high quality?"<br />
<strong>Me</strong> - "We hear a lot of time, why isn't my software as reliable as my car or as reliable as the house I live in. I think the answer lies here. If I ask a car maker to make a car for me no matter what in 6 months or I ask a builder to build my house, flood or rain in 3 months before a brick is laid, I wouldn't be so comfortable in that car or house later. Software programming is even harder, there are new technologies, the user keeps changing his mind and numerous other un-certainties. Maybe if we follow this model, more software projects would be successful. Lets give it a shot."</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/02/04/big-bad-projects/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Integrate Wolfram&#124;Alpha capabilities in your Application</title>
		<link>http://xebee.xebia.in/2011/01/31/integrate-wolframalpha-capabilities-in-your-application/</link>
		<comments>http://xebee.xebia.in/2011/01/31/integrate-wolframalpha-capabilities-in-your-application/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 06:05:59 +0000</pubDate>
		<dc:creator>Tarun Sapra</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Wolfram|Aplha]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7592</guid>
		<description><![CDATA[Wolfram&#124;Alpha is a well known computation knowledge engine. Recently with the release of it's API version 2.0 it's offering free development account with up to 2000 API calls per month. The API is implemented in a standard REST protocol using HTTP GET method. To get started you first need to download from their site the [...]]]></description>
			<content:encoded><![CDATA[<p>Wolfram|Alpha is a well known computation knowledge engine. Recently with the release of it's API version 2.0 it's offering free development account with up to 2000 API calls per month. The API is implemented in a standard REST protocol using HTTP GET method.<span id="more-7592"></span> To get started you first need to <a href="http://products.wolframalpha.com/api/libraries.html">download</a> from their site the language binding of choice which is basically the client that you wish to use for querying the Wolfram|Alpha engine. While signing up for a free account you would be asked to provide the name of your application which would be calling the Wolfram|Alpha services and a App ID would be generated, you would need to provide this App ID in your client code. To understand the API it's important to first understand the Wolfram|Alpha output format.<br />
<a href="http://xebee.xebia.in/2011/01/31/integrate-wolframalpha-capabilities-in-your-application/tarun-1/" rel="attachment wp-att-7616"><img src="http://xebee.xebia.in/wp-content/uploads/2011/01/tarun.1.png" alt="logx integration" title="logx integration" width="470" height="253" class="alignleft size-full wp-image-7616" /></a><br />
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br />
The above image is an example of Wolfram|Alpha output for the term 'logx', as you can see from the image the output contains all the relevant mathematical information about 'logx' and the result also contains the plot diagram for logx which was not shown in the above image for brevity reasons.<br />
The output is divided into rectangular regions called pods each of which corresponds to one category of results. Each pod has a title ('Root', 'Derivative' etc) and a content which is a GIF image. Pods have subpods that enclose the actual content, the GIF image. The API provides you the flexibility to request the result in number of formats(Image, HTML, PlainText etc). The returned result is an XML document with the pods/subpods represented in the format as requested by the client code. We will take look at the client code requesting the result in the Image format since the actual content being displayed on the Wolfram|Alpha query results are images. To execute the code you need to have the following jars in your class path<br />
<strong>commons-codec-1.3.jar, httpclient-4.0.1.jar, httpcore-4.0.1.jar, commons-logging.jar </strong> (you can use other versions of these also)<br />
Also the <strong>WolframAlpha.jar</strong> is required which you can download from <a href="http://products.wolframalpha.com/api/libraries.html">here</a>.<br />
Here's the code.</p>
<pre class="brush: java; title: ; notranslate">
public class WolframAlphaSample {

	// Your APP id:
	private static String appid = &quot;XXXXXXXXXXX&quot;;

	public static void main(String[] args) {

		//user query
		String input = &quot;integrate logx&quot;;

		// The WAEngine is a factory for creating WAQuery objects,
		// and it also used to perform those queries. You can set properties of
		// the WAEngine (such as the desired API output format types) that will
		// be inherited by all WAQuery objects created from it. Most
		// applications will only need to crete one WAEngine object, which is used throughout
		// the life of the application.
		WAEngine engine = new WAEngine();

		// These properties will be set in all the WAQuery objects created from
		// this WAEngine.
		engine.setAppID(appid);
		engine.addFormat(&quot;image&quot;);

		// Create the query.
		WAQuery query = engine.createQuery();

		// Set properties of the query.
		query.setInput(input);

		try {
			// This sends the query to the Wolfram|Alpha server, gets the XML
			// result and parses it into an object hierarchy held by the WAQueryResult object.
			WAQueryResult queryResult = engine.performQuery(query);

			if (queryResult.isError()) {
				System.out.println(&quot;Query error&quot;);
				System.out.println(&quot;  error code: &quot; + queryResult.getErrorCode());
				System.out.println(&quot;  error message: &quot; + queryResult.getErrorMessage());
			} else if (!queryResult.isSuccess()) {
				System.out.println(&quot;Query was not understood; no results available.&quot;);
			} else {
				// Got a result.
				System.out.println(&quot;Successful query. Pods follow:\n&quot;);
				for (WAPod pod : queryResult.getPods()) {
					if (!pod.isError()) {
						System.out.println(pod.getTitle());
						System.out.println(&quot;------------&quot;);
						for (WASubpod subpod : pod.getSubpods()) {
							for (Object element : subpod.getContents()) {
								System.out.println(((WAImage) element).getTitle());
								System.out.println(((WAImage) element).getURL());
								System.out.println(&quot;&quot;);
							}
						}
						System.out.println(&quot;&quot;);
					}
				}
				// We ignored many other types of Wolfram|Alpha output, such as
				// warnings, assumptions, etc.
				// These can be obtained by methods of WAQueryResult or objects
				// deeper in the hierarchy.
			}
		} catch (WAException e) {
			e.printStackTrace();
		}
	}

}
</pre>
<p>Be sure to provide your APP id in the above code. From the above code you can see that each WAQueryResult holds the Arrays of pods which are further iterated to extract subpods and contents respectively. In a typical scenario in a web application the above code return the pods objects which can be set into the requestScope and then iterated on the UI. Finally the getTitle() and getURL() methods of the WAImage instance can be used to set the HTML img tag url and the corresponding description.<br />
<code></p>
<pre class="brush: xml; title: ; notranslate">
&lt;h2&gt;${waImage.title}&lt;/h2&gt;
&lt;img src=&quot;${waImage.url}&quot; alt=&quot;${waImage.title}&quot; /&gt;
</pre>
<p></code><br />
Thus you can now place the Wolfram|Alpha search results on specific parts of your web-page and not just images but you can also request 'plaintext' and 'html' by specifying the same in the client code.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/31/integrate-wolframalpha-capabilities-in-your-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adobe Flex: Prototype ModelLocator</title>
		<link>http://xebee.xebia.in/2011/01/30/adobe-flex-prototype-modellocator/</link>
		<comments>http://xebee.xebia.in/2011/01/30/adobe-flex-prototype-modellocator/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 08:50:27 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[modellocator]]></category>
		<category><![CDATA[prototype]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7600</guid>
		<description><![CDATA[We all know the advantage of having Singleton ModelLocator. In this blog, i will share my experience working on 'Prototype' ModelLocator. Sometime back, i faced an issue while updating the view/components, which were binded to an ArrayCollection. This ArrayCollection was a public property in 'Singleton' ModelLocator. A TabNavigator with 2 tabs for instance, each tab [...]]]></description>
			<content:encoded><![CDATA[<p>We all know the advantage of having Singleton ModelLocator. In this blog, i will share my experience working on 'Prototype' ModelLocator.</p>
<p>Sometime back, i faced an issue while updating the view/components, which were binded to an ArrayCollection. This ArrayCollection was a public property in 'Singleton' ModelLocator. A TabNavigator with 2 tabs for instance, each tab containing one instance of component X. Component X was binded to 'objArrCollection', which was updated after a service call. The expected behavior should be - Only that instance of Component X should be updated for which the service call was made. So for example, if i make a service call from the first tab to update the first instance of Component X, then only this instance should be udpated. The second instance, present in the second tab should not change. But we were working with Singleton model, that super-impose the 'objArrCollection' with the latest value. Since objArrCollection is binded to both the views, hence both get updated. So in such cases, it is always good to have Prototype ModelLocators.<span id="more-7600"></span></p>
<p>In above mentioned scenario, you can work very well using Singleton modellocators. But then you need to have checks in place. For example, if you are making a service call from the first tab, then after getting result and before actually binding it to the view, you might need some kind of check to see if only the first tab is updated. May be a dictionary, which has 'key' as the tab/component ID and the 'value' as the result. These kind of checks may be complex or even dirty at times. To avoid this you can make your model as prototype. </p>
<p>With prototype models, you are assured that every view has its own model. So the views don't confuse when to udpate themselves. In the use case mentioned above, both the tabs have different instances of the ModelLocator. </p>
<p>Talking about simple MVC based applications, there are many ways to manage the scope of models (as singleton or prototype). In our application, we used Spring ActionScript to manage the top level code, where we specified the scope for our controllers/models.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;!-- Model --&gt;
&lt;Object id=&quot;applicationModel&quot; clazz=&quot;{ApplicationModel}&quot; scope=&quot;prototype&quot;/&gt;

&lt;!-- Controller --&gt;
&lt;Object id=&quot;applicationController&quot; clazz=&quot;{ApplicationController}&quot; scope=&quot;prototype&quot;&gt;
	&lt;ConstructorArg ref=&quot;{applicationModel}&quot;/&gt;
&lt;/Object&gt;
</pre>
<p>Prototype ModelLocator also helps in managing data model while creating Dashboard applications. You may have different views to represent data. Some may be in charts, and some in grids. A dashboard might need to show all these views all-together. And again the same use case, user gesture should update only the intended data model.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/30/adobe-flex-prototype-modellocator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>User Centered Analysis Process</title>
		<link>http://xebee.xebia.in/2011/01/29/user-centered-analysis-process/</link>
		<comments>http://xebee.xebia.in/2011/01/29/user-centered-analysis-process/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 14:06:04 +0000</pubDate>
		<dc:creator>jthakur</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[User Centered Analysis Process]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7679</guid>
		<description><![CDATA[While working on my current project I came across some interesting concepts about User Centered Analysis and Design. The ultimate goal of any designer should always be a “actual user” friendly design. What is the use of a shiny and good looking e-commerce website when it does not have proper navigation to shop through. So [...]]]></description>
			<content:encoded><![CDATA[<p>While working on my current project I came across some interesting concepts about User Centered Analysis and Design. The ultimate goal of any designer should always be a “actual user” friendly design. What is the use of a shiny and good looking  e-commerce website when it does not have proper navigation to shop through. So a good design is just not about colors and shapes its actually about usability for the  “actual users”. <span id="more-7679"></span>So the best way to design an interface is to go through a strategic analysis and design process to produce the most user friendly and good looking interfaces instead of just designing a colorful shiny website. Here I want to share few of my experiences and suggestions to implement this strategic process. These practices are applicable for any interface, starting from a banner to be kept at a conference hall till high end website.</p>
<p>Here are stages for doing User-Centered Analysis (UCA) for the any software user interface:-</p>
<ol>
<li><span style="text-decoration: underline;"><strong>Discovering.</strong></span><br />
<span style="color: #888888;"><em><span style="text-decoration: underline;">Who the end user are for user interface:</span></em></span><br />
It is very important to know Primary users for whom the interface must be a success. For instance, if your end-users are children, designing needs to be done according to their sensibilities, like use sans serif typeface, big and colorful font, chose colorful designs (e.g. pink colors for girls and blue for boys) which are more attractive.For youth/teenager design should have not much content, small fonts, they prefer shorter line lengths, and it should be smartly designed which attract them to use it and interact then only they will use it.</p>
<p>For business people, the user interface should be simple but informative. Related information should be easily available as it takes just 3 seconds for a user to move to other site.</p>
<p>For old people some of the usability points are similar to children e.g. use of sans serif font, big font size. However it shouldn’t be of too much colors.</p>
<p>For people who have visual, motor, auditory and cognitive disabilities special guidelines need to be followed while designing User Interface.</p>
<p><span style="font-family: &amp;amp;amp; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></p>
<p><span style="text-decoration: underline;"><em><span style="color: #808080;">Mental model of the and their past experience.</span></em></span><br />
Often people come-up with mental models which are based on their past experience. Mental models don’t always match with the reality however it sets the expectations, which drive and shape behavior. By constantly refining and revising this model drives requests for functionality.</p>
<p><em><span style="text-decoration: underline; color: #808080;">Stakeholders goals and objectives:</span></em><br />
It helps to design features and functionality (usually phrased as specific metrics regarding sales, costs, name recognition etc ) which are  beneficial to the organization.</li>
<li><strong><span style="text-decoration: underline;">Collecting data on.</span></strong><span style="color: #808080; text-decoration: underline;"><em><br />
User profiles:<br />
</em></span> Individual profiles describe related user groups who will be using the UI. Parameters of general user profiles are health, age, gender, education, language etc.</p>
<p><span style="color: #808080; text-decoration: underline;"><em>Work environment.</em></span><br />
It helps to understand work environment of the users. Different work environment call for different designs. For instance for an application used track of working hours. People used to record time at the end of the week or month which would eventually result in inaccuracies. To avoid this PROBLEM, decision was to offer entry in multiple ways: web, desktop and palm application. Aspects of these three environmental profiles drive aspects of the corresponding designs?</p>
<p>Connectivity? Screen size? Time in which to do the task? Availability of supporting information?</p>
<p><span style="color: #808080; text-decoration: underline;"><em>Field Studies:</em></span><br />
There are many ways to collect data.<br />
Direct – Obtaining data from actual users via direct contact (e.g. face to face)<br />
Indirect – Obtaining data from users without direct contact<br />
Individual – One person at a time<br />
Group – More than one person at a time for example group discussion<br />
Performance – The tasks are performed in the session for example user able to achieve the goal<br />
Discussion – The tasks are discussed, recalled, projected with options given<br />
After collecting data collate and find similarities and variations in responses across different user groups like tasks, frequency of use, time etc.<br />
Document things that are necessary using stories, flow diagrams, images, tables and graphs.</p>
<p><span style="color: #808080; text-decoration: underline;"><em>Scenarios of how user’s will use the interface:</em></span><br />
Scenarios provide the “how-to” perspective It helps to perspective. It help to understand what all task need to do, discovers relationships among tasks, understand how multiple tasks occur together in the real world.</li>
</ol>
<p>All these information help us in gaining more inputs for brainstorming and developing/enhancing a product which is a key to success for the product. User Centered Design mistakes later become maintenance problems and have additional hidden cost in terms of training each individual help desk person. User Centered Design obviously leads towards less hidden or training cost. Initially the freedom to design is high and in turn less cost of change. By getting smart early helps in incorporating good ideas before the site is frozen, User Centered Analysis (UCA) reduces rework and maintenance is greatly reduced.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 163px; width: 1px; height: 1px;">
<p><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves /> <w:TrackFormatting /> <w:PunctuationKerning /> <w:ValidateAgainstSchemas /> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF /> <w:LidThemeOther>EN-US</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables /> <w:SnapToGridInCell /> <w:WrapTextWithPunct /> <w:UseAsianBreakRules /> <w:DontGrowAutofit /> <w:SplitPgBreakAndParaMark /> <w:DontVertAlignCellWithSp /> <w:DontBreakConstrainedForcedTables /> <w:DontVertAlignInTxbx /> <w:Word11KerningPairs /> <w:CachedColBalance /> </w:Compatibility> <m:mathPr> <m:mathFont m:val="Cambria Math" /> <m:brkBin m:val="before" /> <m:brkBinSub m:val="&#45;-" /> <m:smallFrac m:val="off" /> <m:dispDef /> <m:lMargin m:val="0" /> <m:rMargin m:val="0" /> <m:defJc m:val="centerGroup" /> <m:wrapIndent m:val="1440" /> <m:intLim m:val="subSup" /> <m:naryLim m:val="undOvr" /> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"   DefSemiHidden="true" DefQFormat="false" DefPriority="99"   LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Normal" /> <w:LsdException Locked="false" Priority="9" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="heading 1" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" /> <w:LsdException Locked="false" Priority="39" Name="toc 1" /> <w:LsdException Locked="false" Priority="39" Name="toc 2" /> <w:LsdException Locked="false" Priority="39" Name="toc 3" /> <w:LsdException Locked="false" Priority="39" Name="toc 4" /> <w:LsdException Locked="false" Priority="39" Name="toc 5" /> <w:LsdException Locked="false" Priority="39" Name="toc 6" /> <w:LsdException Locked="false" Priority="39" Name="toc 7" /> <w:LsdException Locked="false" Priority="39" Name="toc 8" /> <w:LsdException Locked="false" Priority="39" Name="toc 9" /> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" /> <w:LsdException Locked="false" Priority="10" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Title" /> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" /> <w:LsdException Locked="false" Priority="11" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtitle" /> <w:LsdException Locked="false" Priority="22" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Strong" /> <w:LsdException Locked="false" Priority="20" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Emphasis" /> <w:LsdException Locked="false" Priority="59" SemiHidden="false"    UnhideWhenUsed="false" Name="Table Grid" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" /> <w:LsdException Locked="false" Priority="1" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="No Spacing" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 1" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 1" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 1" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 1" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" /> <w:LsdException Locked="false" Priority="34" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" /> <w:LsdException Locked="false" Priority="29" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Quote" /> <w:LsdException Locked="false" Priority="30" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 1" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 1" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 1" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 1" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 1" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 2" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 2" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 2" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 2" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 2" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 2" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 2" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 2" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 3" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 3" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 3" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 3" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 3" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 3" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 3" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 3" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 3" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 4" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 4" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 4" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 4" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 4" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 4" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 4" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 4" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 4" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 5" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 5" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 5" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 5" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 5" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 5" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 5" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 5" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 5" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 6" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 6" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 6" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 6" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 6" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 6" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 6" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 6" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 6" /> <w:LsdException Locked="false" Priority="19" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" /> <w:LsdException Locked="false" Priority="21" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" /> <w:LsdException Locked="false" Priority="31" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" /> <w:LsdException Locked="false" Priority="32" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" /> <w:LsdException Locked="false" Priority="33" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Book Title" /> <w:LsdException Locked="false" Priority="37" Name="Bibliography" /> <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" /> </w:LatentStyles> </xml><![endif]--><!--[if gte mso 10]> <mce:style><!   /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Table Normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-priority:99; 	mso-style-qformat:yes; 	mso-style-parent:""; 	mso-padding-alt:0in 5.4pt 0in 5.4pt; 	mso-para-margin:0in; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Calibri","sans-serif";} --> <!--[endif]--></p>
<p class="MsoNormal" style="margin-left: 1.5in; text-indent: -1.5in;"><span style="font-family: &amp;amp;amp; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"><br />
</span>i.<span style="font-family: &amp;amp;amp; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>For old people some of the usability points are similar to children e.g. use of sans serif font, big font size. However it shouldn’t be of too much colors..<br />
For people who have visual, motor, auditory and cognitive disabilities special guidelines need to be followed while designing UI.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/29/user-centered-analysis-process/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why WebSocket is quicker</title>
		<link>http://xebee.xebia.in/2011/01/26/why-websocket-is-quicker/</link>
		<comments>http://xebee.xebia.in/2011/01/26/why-websocket-is-quicker/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 16:54:40 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Protocol]]></category>
		<category><![CDATA[Quicker]]></category>
		<category><![CDATA[Web Socket]]></category>
		<category><![CDATA[WebSocket]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7566</guid>
		<description><![CDATA[There is a lot of buzz all around - 'WebSocket is quicker'. But why WebSocket is quicker? As you read this blog this question should get answered. When we say quicker comparison is with? When we say WebSocket is quicker the comparison is always with HTTP. So before we start discussing WebSocket protocol let us [...]]]></description>
			<content:encoded><![CDATA[<p>There is a lot of buzz all around - 'WebSocket is quicker'. But why WebSocket is quicker? As you read this blog this question should get answered.</p>
<h3>When we say quicker comparison is with?</h3>
<p>When we say WebSocket is quicker the comparison is always with HTTP. So before we start discussing WebSocket protocol let us talk about HTTP.</p>
<p><span id="more-7566"></span></p>
<h3>HTTP is stateless</h3>
<p>In HTTP the server never remembers the interaction with a client. Every time a client sends a request to the server the client needs to introduce itself. HTTP has the request headers which helps clients send the so called introduction information to the server. Please note that this information has to be sent over the wire every time client wants to send a request to the server. Similarly when server sends the response back to the client it needs to send details about itself back to the client. HTTP protocol has response headers for this communication. But what is the reason behind this constant overhead.The reason is that the HTTP protocol is stateless.</p>
<h3>WebSocket is a means of full duplex communication between peers (browser and server)</h3>
<p>But the WebSocket protocol is not stateless. In WebSocket communication the client and server go through a process of handshake (to read more about handshake refer to my blog on 'Understanding WebSocket handshake'). Handshake helps the client and server get acquainted with each other. During handshake communicating peers (client and server) share information about each other, like mode(protocol) and language (sub-protocol) of communication, and all other details which are generally shared using the request and response headers of HTTP. Once the handshake is successfully executed a dedicated lane of communication gets established between the client and the server. Which means subsequent communication will not require any introduction information to be sent over the wire.</p>
<h3>Let us understand the difference between HTTP and WebSocket communication using an example.</h3>
<p>Suppose the server wants to send latest NAV of an asset to the client.</p>
<h3>HTTP</h3>
<p>In case of HTTP the client will send a request to the server requesting the NAV and the server will respond with the NAV.</p>
<h4>HTTP Ajax Request</h4>
<pre class="brush: xml; title: ; notranslate">
Request Headersview source (this is an Ajax call).
Host    localhost:8080
User-Agent    Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)
Accept    */*
Accept-Language    en,hi;q=0.7,sq;q=0.3
Accept-Encoding    gzip,deflate
Accept-Charset    ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive    115
Connection    keep-alive
Content-Type    application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With    XMLHttpRequest
Referer    http://localhost:8080/navApp/getNav.do
Content-Length    4858
Cookie    JSESSIONID=385DB76E1CC72C99ACFEE0DCCFD30576; UserInteraction7=KonaFlashBase
Pragma    no-cache
Cache-Control    no-cache&lt;/p&gt;
</pre>
<h4>HTTP Response</h4>
<pre class="brush: xml; title: ; notranslate">
Response Headersview source
Server    Apache-Coyote/1.1
Content-Type    text/html
Content-Length    2
Date    Sun, 23 Jan 2011 05:21:16 GMT
</pre>
<p>The Actual Response</p>
<pre class="brush: xml; title: ; notranslate">
21.22
</pre>
<h3>WebSocket</h3>
<p>WebSocket protocol ensures two way communication(full duplex communication) which means client does not need to send request to the server to receive a response. If the server wants to send the latest NAV of an asset to the client it can do so at will, till the client and server have a connection established between them.</p>
<h4>WebSocket Message</h4>
<p>As compared to the request/response paradigm of HTTP, WebSocket uses a paradigm close to messaging. Any peer can send a message to other at will and the other party would keep listening to any such messages from the peer. To send a message the message needs to be wrapped in a frame. <strong>Each frame of data starts with a  frame type (0xFF byte in our case), followed by the number of bytes in the data, expressed as a big-endian 64 bit unsigned integer, followed by the UTF-8 data.</strong></p>
<p>Which means the extra information sent with the actual data are</p>
<p>1. 0xFF  and</p>
<p>2. number of bytes in the data.</p>
<h4>WebSocket frame types</h4>
<p>But what is 0xFF - In web socket communication the data can be sent using frames. All these frames have to start with a frame type. Frame type signifies the format of data packaged in the data frame. 0xFF frame type means the data is in UTF-8 text format. There is one more frame type 0x00, this frame type is used to close the WebSocket connection. Currently WebSocket protocol supports only two frame types 0xFF and 0x00. In future more frame types may be defined to support more data types.</p>
<h3>Are the headers actually heavy?</h3>
<p>If you compare the extra information in WebSocket with overhead involved in HTTP request/reponse paradigm, the amount of extra data is really less in WebSocket communication. But you may wonder why are we worried about the request and response headers so much? Does it really make any difference? If you look at the total data footprint of request and response it may come close to 1Kb. If the actual data to be communicated is of a few bytes and the rate of exchange of data is very high then the overhead of 1Kb for communicating a few bytes can cause real performance hit. That is why in all such scenarios WebSocket proves to be quicker.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/26/why-websocket-is-quicker/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extreme Programming &#8211; Designing With CRC Cards</title>
		<link>http://xebee.xebia.in/2011/01/18/extreme-programming-designing-with-crc-cards/</link>
		<comments>http://xebee.xebia.in/2011/01/18/extreme-programming-designing-with-crc-cards/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 19:57:26 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Designing]]></category>
		<category><![CDATA[Extreme Programming]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7515</guid>
		<description><![CDATA[We were having problems in most of the design discussions we did as a team. We couldn't get out of the discussion with everyone's consensus on the selected design. In the end, people still nagged about the loopholes in the design or kept proposing a better design. One day we came across “Designing Using CRC Cards” in [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">We were having problems in most of the design discussions we did as a team. We couldn't get out of the discussion with everyone's consensus on the selected design. In the end, people still nagged about the loopholes in the design or kept proposing a better design.</p>
<p style="text-align: justify;">One day we came across “Designing Using CRC Cards” in extreme programming. It looked a bit interesting to us. However, we did not have any references to fall back on. So, we thought of experimenting with it and the results were promising.</p>
<p style="text-align: justify;">Let me describe this process of designing in brief. CRC stands for Class, Responsibilities, and Collaboration. The class of the object is written at the top of the card, responsibilities listed down the left side, collaborating classes are listed to the right of each responsibility. The discussion happens around these cards which evolves as a design. Please <a class="aligncenter" style="display: inline !important;" title="Designing With CRC Cards" href="http://www.extremeprogramming.org/rules/crccards.html" target="_blank">refer this</a> for further reading.<span id="more-7515"></span></p>
<p style="text-align: justify;">Lets talk about the traditional approach of designing first. Here, the team assembles, someone takes the lead and describes the problem and his thoughts on the design. Generally, he is the senior most guy of the team or the person who is supposed to implement it. Then a series of discussions start around it. The problem with this approach is that the discussions generally get out of hand and become generic in nature. The discussions can deviate from the current functionality to other parts of the application.</p>
<p style="text-align: justify;">Here people talk around boxes drawn as components. And when people talk around boxes, they can never get into the nitty gritties which can later become a bottleneck somewhere.</p>
<p style="text-align: justify;">To some, these sessions become an opportunity to exercise/display their finesse of design principles and concepts. Behavioral problems also come into play in these discussions. Some people like to dominate the meeting by never giving another person any chance to speak, no matter how good/bad their idea is. Some introvert people don’t even bother to speak even if they have some good idea with them.</p>
<p style="text-align: justify;">So, when we tried CRC cards with designing, the first thing we noticed was, no one was leading/dictating the design discussion. The whole team sat together and each person created one card per class as per their design. This also ensured that ideas from each team member come up. Then each member presented their cards, talking about the responsbilites it will have.</p>
<p style="text-align: justify;">The first round of describing cards was not that deep. So, it took very less time, and faulty/incorrect ideas where dismissed in the beginning. In other words, we can say that the best of the ideas were filtered out pretty quickly.</p>
<p style="text-align: justify;">Now, instead of talking around boxes, we were talking about real classes where we were able to state their responsbilities. This allowed us to think in Object Oriented way. The selected cards were further discussed and their weaknesses and problems were easily uncovered. We continued doing this until everyone agreed upon the design.</p>
<p style="text-align: justify;">The cards kept a check on the discussion, so that it could not divert to other areas of application. As the discussions were card centric, so, the discussions revolved around them only and we ended up designing exactly what was required. Due to all these, the time taken was comparatively one fifth of what it would have been in a traditional designing session.</p>
<p style="text-align: justify;">Also, in the end we had a written design, which was more than a set of high level boxes. We had classes, its responsbilities and how they were going to communicate. Sometimes, we used white board also to explain things a little bit, but even that was card centric.</p>
<p style="text-align: justify;">Therefore, I will say that “Designing With CRC Cards” makes designing comfortable and effective. If traditional design sessions are giving you headaches, and you want to design as a team, then try out “Designing With CRC Cards”, it will work.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/18/extreme-programming-designing-with-crc-cards/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Swiz Framework 1.0</title>
		<link>http://xebee.xebia.in/2011/01/12/swiz-framework-1-0/</link>
		<comments>http://xebee.xebia.in/2011/01/12/swiz-framework-1-0/#comments</comments>
		<pubDate>Wed, 12 Jan 2011 02:00:07 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flex Architectures]]></category>
		<category><![CDATA[Swiz]]></category>
		<category><![CDATA[swiz framework]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7483</guid>
		<description><![CDATA[Swiz framework just announce 1.0 release , I have worked on other frameworks available in the market for development in Adobe Flex , after some research i found swiz the simplest , easiest and solves my purpose of using a framework without much hassle ,In this blog we are going to see two things why should [...]]]></description>
			<content:encoded><![CDATA[<p>Swiz framework just announce 1.0 release , I have worked on other frameworks available in the market for development in Adobe Flex , after some research i found swiz the simplest , easiest and solves my purpose of using a framework without much hassle ,In this blog we are going to see two things why should i use Swiz framework and how to use it.</p>
<p><span id="more-7483"></span></p>
<p>Following are the reasons that interest me for using the framework.</p>
<ul>
<li>You don't need to extend the framework specific classed</li>
<li>Framework doesn't impose any design patterns</li>
<li>No Boilerplate code</li>
</ul>
<p><strong>You don't need to extend the framework specific classed</strong><br /> I think this is a major reason why I would use swiz over the others. A lot of time while i m writing components i had to extend the events from my custom components. This made my custom components unusable for other projects. I had to often rewrite the events while reusing the components in another project. With Swiz while you are designing the custom components, events can be core flex event that extends Event class. Swiz provides a great flexibility of Event handling as well as Mediating. We will see in the code later how to handle events using Swiz</p>
<p><strong>Framework doesn't impose any design patterns</strong><br /> This gives me a lot of flexibility in designing the application as I want. Earlier in one of the frameworks I had to implement the command pattern , etc. That did restrict me while designing the application. As whenever i had to design a functionality I had to take care of how I have to integrate with the underlying framework.</p>
<p><strong>No Boilerplate code</strong><br /> Yet another added advantage. No more writing the same boiler plate code to add a new functionality every time. Actually this comes packaged when you have to impose the design patterns by the framework.</p>
<p>A lot will be clearer in the video below. We are going to see the following things in the Video</p>
<p>1. Swiz Framework<br /> 2. Configuring Swiz<br /> 2. How to use [Inject]<br /> 3. How to process events using Swiz<br /> 4. How to call server side service with one line of code<br /> 5. Dispatching the event without have to extend EventDispacher for non UI components.</p>
<p><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/FDVygVijpv8?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/FDVygVijpv8?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/12/swiz-framework-1-0/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The Curious case of Field and Property Access in Hibernate</title>
		<link>http://xebee.xebia.in/2011/01/10/the-curious-case-of-field-and-property-access-in-hibernate/</link>
		<comments>http://xebee.xebia.in/2011/01/10/the-curious-case-of-field-and-property-access-in-hibernate/#comments</comments>
		<pubDate>Mon, 10 Jan 2011 06:18:12 +0000</pubDate>
		<dc:creator>Vaibhav Sehgal</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Annotations]]></category>
		<category><![CDATA[Field access]]></category>
		<category><![CDATA[Property Access]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6549</guid>
		<description><![CDATA[Have you ever wondered whether placing Hibernate annotations over both the fields and getters(properties) in an entity class would land you in trouble. Well as Rajdeep and I discovered, if you haven't tried it out, it will. As shown in the following code, CustomerHotelBooking is an entity bean which acts as a link between Customer and Hotel. [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">Have you ever wondered whether placing Hibernate annotations over both the fields and getters(properties) in an entity class would land you in trouble. Well as <a href="http://xebee.xebia.in/author/rajdeep/">Rajdeep</a> and I discovered, if you haven't tried it out, it will. <span id="more-6549"></span></p>
<p> As shown in the following code, CustomerHotelBooking is an entity bean which acts as a link between Customer and Hotel. Ideally, this entity would be mapped by Hibernate, to a CustomerHotelBooking table having hotel_id as a foreign key with type as bigint. However, it does not happen this way. On the contrary the CustomerHotelBooking table has a column named hotel with type as tinyblob. Can you figure out why this happens?
</p></div>
<pre class="brush: plain; title: ; notranslate">
@Entity
public class CustomerHotelBooking {

        @Id
        @GeneratedValue
        private long id;

        private Hotel hotel;

        private Customer customer ;

        @ManyToOne
        @Cascade(value = { CascadeType.ALL })
        public Hotel getHotel() {
                return hotel;
        }
...
</pre>
<p>Well, this points to a classic rule of Hibernate Access types (the focus of this blog) ; "<strong>Be consistent while placing your annotations or use @Access instead</strong>". By default if we don't use @Access, Hibernate looks for <strong>@Id</strong> or <strong>@EmbeddedId</strong> and then decides whether it should look for other annotations on the fields or on the getters(properties).Thus either place the annotations on the fields only or on the getters(properties) only. Mixing them and not using @Access will cause abnormal behaviour.</p>
<p>So if you still want to play mix-n-match then do it the following way (using <strong>@Access(AccessType.PROPERTY) </strong>or<strong> @Access(AccessType.FIELD)</strong> )</p>
<pre class="brush: plain; title: ; notranslate">
@Entity
public class CustomerHotelBooking {

        @Id
        @GeneratedValue
        private long id;

        private Hotel hotel;

        private Customer customer ;

        /**
         * @return the hotel
         */
        @Access(AccessType.PROPERTY)
        @ManyToOne
        @Cascade(value = { CascadeType.ALL })
        public Hotel getHotel() {
                return hotel;
        }
...
</pre>
<p>You could also place the @Access(AccessType.PROPERTY) or @Access(AccessType.FIELD) annotation on the class instead to mark the properties or fields as the access types. Thats a personal preference that we leave to you, but for us Field access wins hands down for its clarity.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/10/the-curious-case-of-field-and-property-access-in-hibernate/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pair Programming With Two Keyboards</title>
		<link>http://xebee.xebia.in/2011/01/05/pair-programming-with-two-keyboards/</link>
		<comments>http://xebee.xebia.in/2011/01/05/pair-programming-with-two-keyboards/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 19:32:16 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Pair Programming]]></category>
		<category><![CDATA[Extreme Programming]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7453</guid>
		<description><![CDATA[Today when I started pair programming, me and my partner did an experiment by using two keyboards. I don’t know whether its advised to do in pair programming or not, but we started it mostly out of curiosity and fun. Generally we pair with only one keyboard and one person becomes the navigator and the [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Today when I started pair programming, me and my partner did an experiment by using two keyboards. I don’t know whether its advised to do in pair programming or not, but we started it mostly out of curiosity and fun.</p>
<p style="text-align: justify;">Generally we pair with only one keyboard and one person becomes the navigator and the other person becomes the driver. We change the roles every half/one hour.</p>
<p style="text-align: justify;">One major problem while pair programming with only one keyboard is that the navigator can doze off in between with his eyes on screen and mind somewhere in Hawaii. This is a pretty common thing, specially for newbies who start pairing. And if the driver is someone who loves himself and his code a lot, then he will neither know nor mind the navigator’s virtual Hawaii trip.<br />
<span id="more-7453"></span><br />
Other than that, the person who codes a particular part is having more control over it than the navigator. So, when we switch the roles of the navigator and driver, the new driver takes some time to have a complete control over the code. The outcomes of this can be loss of productivity due to time taken by the navigator to take the complete control over the code written earlier . And if the new driver is not able to grasp the old code soon, the new code written by him might not be the best he can write.</p>
<p style="text-align: justify;">The navigator has to adjust himself to grab the keyboard if he wants to contribute a line or to analyze something using keyboard. The keyboard’s need arises if the navigator wants to highlight something on the code, or he wants to name/rename a variable/method/class, then writing is far better than spelling it out. Grabbing the keyboard requires a bit of shifting of chairs and sitting positions. The main point is that there is discomfort involved, which can lead to early tiredness.</p>
<p style="text-align: justify;">So, when we started coding with two keyboards, we both had control over the code at the same time. We switched the driver/navigator role every two to five minutes. So, the code was being written by both of us. At any moment of time, both of us were having the complete picture of the code being written. No one can distinguish who wrote which part of the code. The same level of control over the code enabled us to think better than what we would have thought in a navigator’s role, which, ultimately, lead to a better design.</p>
<p style="text-align: justify;">The other benefit was that the code was being continuously refactored by the pair. There was less talk and more coding. Whatever the problem was, no matter how small, was being fixed then and there. In short, the code was more cleaner than it would have been.</p>
<p style="text-align: justify;">As both the driver and navigator were involved in the coding for most of the time, there was no boredom or disconnect from code involved, which prevented even a yawn, leave aside dozing off. And of course, you don’t need to shift your chair every now and then, so, its more comfortable and enjoyable.</p>
<p style="text-align: justify;">Sometimes, we had problems when both of us started typing at the same time. To fix this problem, we kept a green flag. The person having the green flag was allowed to type, this solved the chaos pretty much.</p>
<p style="text-align: justify;">In all, I would say that if you have not tried pair programming with two keyboards, try it out. Its more comfortable, enjoyable and productive.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/05/pair-programming-with-two-keyboards/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Secret Angel flue grips Xebia India</title>
		<link>http://xebee.xebia.in/2011/01/03/secret-angel-flue-grips-xebia-india/</link>
		<comments>http://xebee.xebia.in/2011/01/03/secret-angel-flue-grips-xebia-india/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 13:57:11 +0000</pubDate>
		<dc:creator>vandana</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[#Team building activity]]></category>
		<category><![CDATA[Christmas]]></category>
		<category><![CDATA[New Year]]></category>
		<category><![CDATA[Secret Angel]]></category>
		<category><![CDATA[Xebia]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7427</guid>
		<description><![CDATA[We wanted to do something for Christmas and New Year and doing the same old things wasn’t motivating us. That’s where we were introduced to the idea of playing “Secret Angel”. It was 24th of December, and we started planning to get this idea floated among our fellow Xebians. This game is all about keeping [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">We wanted to do something for Christmas and New Year and doing the same old things wasn’t motivating us. That’s where we were introduced to the idea of playing “Secret Angel”. It was 24th of December, and we started planning to get this idea floated among our fellow Xebians.</p>
<p style="text-align: justify;">This game is all about keeping your “child” happy and surprised all through the duration that this game is played. So an Angel is identified (secretly) for an individual Child. Ideally, every angel picks a slip from the hat to find his child, however we customized it a bit, since we were doing it for the first time, so we (HR Team) shuffled the names and assigned a child to all the angels. The thumb rule was, all who volunteered to play became the default Angels. The surprise generally would be gifts, messages, poems and pranks among other things. <span id="more-7427"></span></p>
<p style="text-align: justify;">Though we were not sure if people would really enjoy this game but it did take us by a surprise to see that all our fellow colleagues not only participated but went an extra mile to surprise the child. Everyone had only one question crossing their mind, who is my secret Angel, and how is he / she going to surprise me? The suspense kept on increasing as angels started surprising their respective child.</p>
<p style="text-align: justify;">All kind of surprises hit the blocks, eatables were the most popular ones. Chocolates, Pastries, Brownies, and Fresh and hot “Maggie” topped the list.</p>
<p style="text-align: justify;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/OPvQuNoQXzI?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/OPvQuNoQXzI?fs=1&amp;hl=en_US" allowfullscreen="true" allowscriptaccess="always"></embed></object></p>
<p style="text-align: justify;">The creativity of the Angels (our fellow colleagues) was visible through their gifts like a personalized coffee mug, photo frame, hand- made cards and t-shirts.</p>
<p style="text-align: justify;">For those who were spectators to this game now started feeling left out and wanted to participate on the 2nd day of the game. Cafeteria talks were only around gifts and guesses. Some work areas were buzzing with ideas for creating some secret mission strategies for their child to find his surprise. People were really engrossed in the game now and were only waiting for getting to know who their secret Angel was. People were really feeling warm (especially in this chilly weather) and overwhelmed with the gestures shown by their fellow Xebians. Angels went on and found out likes and dislikes of their child to provide them with a suitable gift. One of the angels downloaded the photograph of the child from a social networking site and got it printed on a coffee mug.</p>
<p style="text-align: justify;">As is rightly said “all good things come to an end” and so was true for this game as well, although we wanted to continue with the game but we had already decided on the last day of the game. We all gathered to adieu to 2010 and welcome 2011. Everyone was eagerly waiting to uncover the secret Angels. So we started with asking people to guess their Angels. Some of them did guess it right but some of us were totally taken by a surprise to know our Angels. Some of the “Child” had already planned for a surprise for their Angels and gave them return gifts when their name was revealed. The fun ended with cutting the cake and we relished the snacks served.<a rel="attachment wp-att-7441" href="http://xebee.xebia.in/2011/01/03/secret-angel-flue-grips-xebia-india/secret-angel-at-christmas-time4/"><img class="size-medium wp-image-7441 " title="Its time to uncover Angels.....cutting New Year cake" src="http://xebee.xebia.in/wp-content/uploads/2011/01/Secret-Angel-at-Christmas-Time4-300x212.jpg" alt="" width="300" height="212" /></a></p>
<p>Personally, I really enjoyed this game. The thrill and the fun part of it were truly awesome. “Secret Angel” game was a big hit at Xebia as it was really engaging. The game brought people together to think and decide upon an appropriate gift for the child. It helped people to know each other better. Creativity and innovation were the main highlights of the game. The game created an atmosphere of joy, kindness and thankfulness which otherwise remains uncovered.</p>
<p style="text-align: justify;">We are all looking forward to many more activities and fun this year.</p>
<p style="text-align: justify;">Wish you all a very Happy New Year 2011.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/03/secret-angel-flue-grips-xebia-india/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My First Pair Programming Experience- It takes two to tango!!</title>
		<link>http://xebee.xebia.in/2011/01/03/my-first-pair-programming-experience-it-takes-two-to-tango/</link>
		<comments>http://xebee.xebia.in/2011/01/03/my-first-pair-programming-experience-it-takes-two-to-tango/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 04:18:59 +0000</pubDate>
		<dc:creator>Divya Agrawal</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Pair Programming]]></category>
		<category><![CDATA[XP]]></category>
		<category><![CDATA[Extreme Programming]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7355</guid>
		<description><![CDATA[Yesterday evening, while travelling back to home from office, going over the day's activities, my wandering mind was struck with a thought- Pair Programming proclaims to help us improve not only as a developer but as a craftsman. I have been practicing Pair Programming now for quite some time at Xebia, has it really lived [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday evening, while travelling back to home from office, going over the day's activities, my wandering mind was struck with a thought- Pair Programming proclaims to help us improve not only as a developer but as a craftsman. I have been practicing Pair Programming now for quite some time at Xebia, has it really lived up to its promise, or all these things just exist in theory. The thought led me to revel on my entire Pairing experience, which I would like to share with everybody.</p>
<p>Two people sitting together, sharing a screen, brainstorming together-Pairing has always sounded like fun.<br />
<span id="more-7355"></span><br />
In my case I was pairing with Yogesh, whose experience and skill levels are much more than mine. So it was quite natural for me to feel apprehensive about it turning more into a  teacher/student kind of a situation. But all such worries were shed as I began pairing up. I was never criticized or put under pressure to speed up, rather always encouraged to give suggestions, think up alternate ways to implement a functionality. We always had good discussions, with both of us explaining our views and ideas and then taking up the best approach. Such conversations really helped open up my mind and improved my thought process.</p>
<p>To make pairing even more interesting,  we came up with a game where we gave each other points whenever either of us came up with a solution to a problem and deducted points whenever we missed out on (sometimes very obvious ) issues. It kept us both always on our toes while pairing, always pushing for more points. Well, but just don't ask the final scores though!<br />
<a rel="attachment wp-att-7387" href="http://xebee.xebia.in/2011/01/03/my-first-pair-programming-experience-it-takes-two-to-tango/pairon/"><img class="alignnone size-medium wp-image-7387" title="pairon" src="http://xebee.xebia.in/wp-content/uploads/2011/01/pairon-300x172.jpg" alt="" width="300" height="172" /></a></p>
<p>A few things that I particularly liked about the whole experience are:</p>
<ul>
<li><strong>Increased Efficiency</strong>- The 	constant inflow of ideas, the added brainpower helped us get over 	hurdles quickly and we were able to come up with ways to do 	everything even better.</li>
<li><strong>Better Concentration</strong>- While 	pairing, one gets less distracted by the surroundings and there are 	less interruptions, so the focus on programming increases.</li>
<li><strong>Cleaner Coding</strong>, as there 	are an added pair of eyes scanning the code alongside.</li>
<li><strong>Good Learning Curve</strong>- 	Pairing really helps in thorough understanding and grasping of concepts as there 	are discussions and pondering over problems from a wider 	perspective.</li>
<li><strong>Frequent Knowledge Sharing- </strong>In 	our case whenever there was a new problem to solve, we used to split 	up, do our own research, study for some time and then again sit 	together to share our findings and join heads to brainstorm on 	ideas.</li>
</ul>
<p><strong>The Results:</strong> I have benefited a lot by pairing, improving in not only my coding style but also the entire perspective of looking at a problem. As a navigator, I learned to keep a sharp eye on the code, to think up alternatives to every proposed solution, thinking ahead on a problem from all angles, probable problems that may arise and their solutions. On being the driver for the first time my hands shook and I was a bit nervous with a pair of critical eyes watching my every key press, but once I got over that, it proved to be really beneficial, with me getting to know the faster way of coding(read: learning a lot of eclipse shortcuts) and writing cleaner, more readable code.</p>
<p>To sum up:</p>
<p>It takes two to tango,</p>
<p>two to move,</p>
<p>together the two can see it through</p>
<p>overcome the hurdles, make their way,</p>
<p>as the day fades away.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2011/01/03/my-first-pair-programming-experience-it-takes-two-to-tango/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Spring Integration : Configuring Mail Replier Adapter</title>
		<link>http://xebee.xebia.in/2010/12/31/spring-integration-configuring-mail-replier-adapter/</link>
		<comments>http://xebee.xebia.in/2010/12/31/spring-integration-configuring-mail-replier-adapter/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 18:29:17 +0000</pubDate>
		<dc:creator>Nitin Khattar</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Integration]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7300</guid>
		<description><![CDATA[On 17th &#38; 18th November, 2010 in Xebia India we had an in-house training on basics of Spring Integration by the Spring Integration Guru - Iwein Fuld, himself. The training had an exclusive emphasis on the hands on practice of the basics of spring integration including Message Channels, Message Endpoints , Core Messaging Framework and [...]]]></description>
			<content:encoded><![CDATA[<p>On 17th &amp; 18th November, 2010 in Xebia India we had an in-house training on basics of <a href="http://www.springsource.org/spring-integration" target="_blank">Spring Integration</a> by the Spring Integration Guru - Iwein Fuld, himself. The training had an exclusive emphasis on the hands on practice of the basics of spring integration including Message Channels, Message Endpoints , Core Messaging Framework and few Integration Adapters like File Adapter, Mail Adapter and Twitter Adapter.</p>
<p>I got to be a part of the team which was exploring the <strong>Mail Support Adapter</strong>. We worked on features that include reading a message through a channel and sending it within a mail, parsing the message for a url link and enriching the content with the data on that web page and finally replying via a mail in response to a mail received.</p>
<p>The last feature although appeared as quite easier to implement but I somehow faced few problems in configuring the Mail Replier. So in this blog I will elaborate on some common problems in configuring the mail replier and possible ways to solve them as well.</p>
<p>A <strong>Mail Replier</strong> consists of two basic steps:</p>
<ol>
<li>Configuring Mail Inbound      Channel Adapter to be able to access and read a received mail.</li>
<li>Generating a Reply Message      and sending it back to the original sender.</li>
</ol>
<p><span id="more-7300"></span>For the first step, we used <strong>IMAP Adapter</strong> as the Inbound Channel Adapter out of the two available options of IMAP &amp; POP3 Mail Receiver. Within IMAP Adapter we used Polling option rather than Event-Driven because we used Gmail Server which doesn’t supports IMAP IDLE and therefore doesn’t supports Event-Driven. For the correct syntax you can refer to the <a href="http://static.springsource.org/spring-integration/docs/2.0.0.RELEASE/reference/htmlsingle/#mail-inbound" target="_blank">Spring Integration Manual</a>.</p>
<p>This blog revolves more around the <span style="text-decoration: underline;">second step</span> of the Mail Replier. So once the configuration of the IMAP Adapter is successfully completed, the received message can thereby be accessed. The received message is of the type of <strong>MimeMessage</strong>. Mime Message has a predefined <strong>reply</strong> function with a “<strong>reply-to-all</strong>” Boolean flag that returns a message of type <strong>Message</strong>. The new message will have its attributes and headers set up appropriately. The "Subject" field is filled in with the original subject prefixed with "Re:" . It will not have any content, which can then be added using various predefined functions.</p>
<p>So finally a call is made to a function of a service-activator that accepts the received MimeMessage and in turn returns a reply of type Message.</p>
<pre class="java"><span style="color: #000000; font-weight: bold;">public</span> Message sendMessage<span style="color: #66cc66;">&#40;</span>MimeMessage mimeMessage<span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> MessagingException <span style="color: #66cc66;">&#123;</span>
 	Message replyMessage = mimeMessage.<span style="color: #006600;">reply</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span>;
	replyMessage.<span style="color: #006600;">setText</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;MimeMessage Reply&quot;</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">return</span> replyMessage;
<span style="color: #66cc66;">&#125;</span></pre>
<p>The reply message is then passed to the Mail-Outbound-Adapter which using the mail-sender (for eg. JavaMailSenderImpl ) is expected to send this message to its marked destination.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;i:service-activator input-channel=&quot;imapChannel&quot;
	ref=&quot;mailReplier&quot; method=&quot;sendMessage&quot; output-channel=&quot;mailReply&quot;/&gt;
&lt;i:channel id=&quot;mailReply&quot; /&gt;
&lt;bean id=&quot;mailReplier&quot; class=&quot;com.xebia.nuse.mail.ImapReplyActivator&quot; /&gt;
&lt;mail:outbound-channel-adapter channel=&quot;mailReply&quot;
mail-sender=&quot;mailSender&quot; /&gt;
&lt;bean id=&quot;mailSender&quot; class=&quot;org.springframework.mail.javamail.JavaMailSenderImpl&quot;&gt;
	&lt;property name=&quot;host&quot; value=&quot;${mail.host}&quot; /&gt;
	&lt;property name=&quot;username&quot; value=&quot;${mail.username}&quot; /&gt;
	&lt;property name=&quot;password&quot; value=&quot;${mail.password}&quot; /&gt;
	&lt;property name=&quot;javaMailProperties&quot;&gt;
		&lt;props&gt;
			&lt;prop key=&quot;mail.smtp.auth&quot;&gt;true&lt;/prop&gt;
			&lt;prop key=&quot;mail.smtp.starttls.enable&quot;&gt;true&lt;/prop&gt;
		&lt;/props&gt;
	&lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>Oops….an exception occurs when we try to run the application</p>
<p><em><span style="color: #ff0000;"> SEVERE: org.springframework.integration.MessageHandlingException: Unable to create MailMessage from payload type [javax.mail.internet.MimeMessage], expected byte array or String.<br />
at org.springframework.integration.mail.MailSendingMessageHandler.convertMessageToMailMessage (MailSendingMessageHandler.java:98)<br />
org.springframework.integration.mail.MailSendingMessageHandler.handleMessageInternal (MailSendingMessageHandler.java:71)<br />
org.springframework.integration.handler.AbstractMessageHandler.handleMessage (AbstractMessageHandler.java:78)<br />
org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch (UnicastingDispatcher.java:110)<br />
org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch (UnicastingDispatcher.java:97) org.springframework.integration.channel.AbstractSubscribableChannel.doSend (AbstractSubscribableChannel.java:44)<br />
org.springframework.integration.channel.AbstractMessageChannel.send (AbstractMessageChannel.java:157) org.springframework.integration.channel.AbstractMessageChannel.send (AbstractMessageChannel.java:128)<br />
org.springframework.integration.core.MessagingTemplate.doSend (MessagingTemplate.java:288)<br />
org.springframework.integration.core.MessagingTemplate.send (MessagingTemplate.java:149)<br />
…<br />
</span></em></p>
<p>As you can see when mail-outbound-adapter tries to send this reply with payload of type MimeMessage, it throws MessageHandlingException.</p>
<p>So in order to solve this problem I came across two plausible solutions:</p>
<p><strong> Solution 1: Modify the received MimeMessage </strong><br />
This includes changing the subject of the received message explicitly and replacing the recipient’s address with that of sender’s address. Now if we return this modified MimeMessage to the mail-outbound-Adapter, we will get the same exception again. So in order to avoid this, we need to inject <strong>JavaMailSender</strong> into the corresponding service-activator which in turn uses its predefined <strong>send</strong> function to send the MimeMessage. This also avoids the need for the use of mail-outbound-adapter.</p>
<pre class="java"><span style="color: #000000; font-weight: bold;">private</span> JavaMailSender mailSender;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> setMailSender<span style="color: #66cc66;">&#40;</span>JavaMailSender mailSender<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006600;">mailSender</span> = mailSender;
<span style="color: #66cc66;">&#125;</span>
.
.
.
<span style="color: #000000; font-weight: bold;">final</span> Address<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> senderAddresses = mimeMessage.<span style="color: #006600;">getFrom</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
mimeMessage.<span style="color: #006600;">setSubject</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Reply::&quot;</span>+mimeMessage.<span style="color: #006600;">getSubject</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
mimeMessage.<span style="color: #006600;">setRecipient</span><span style="color: #66cc66;">&#40;</span>RecipientType.<span style="color: #006600;">TO</span>, senderAddresses<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
mailSender.<span style="color: #006600;">send</span><span style="color: #66cc66;">&#40;</span>mimeMessage<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>
<p><strong> Solution 2: Create a new SimpleMailMessage</strong><br />
This includes creating a new reply message altogether, i.e. using a <strong>SimpleMailMessage </strong>which models a simple mail message, including data such as the from, to, cc, subject, and text fields and it lacks various sophisticated features like attachment, special character encodings, etc but there is very less need of such features in an auto-reply. And one more thing to note is that we need not to inject JavaMailSender into the service-activator and can continue to use the mail-outbound-adapter for sending the reply.</p>
<pre class="java">Address<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> senderAddresses = mimeMessage.<span style="color: #006600;">getFrom</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
MailMessage mailMessage = <span style="color: #000000; font-weight: bold;">new</span> SimpleMailMessage<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
mailMessage.<span style="color: #006600;">setSubject</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Reply: &quot;</span>+ mimeMessage.<span style="color: #006600;">getSubject</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
mailMessage.<span style="color: #006600;">setTo</span><span style="color: #66cc66;">&#40;</span>senderAddresses<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
mailMessage.<span style="color: #006600;">setText</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Thanks for sending the mail&quot;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">return</span> mailMessage;
<span style="color: #66cc66;">&#125;</span></pre>
<p>In this way the problem of configuring the Mail Replier was hence-forth solved.<br />
The <strong>Integration Graph</strong> of the xml file we created for exploring Spring Integration Mail Support is as follows:<br />
<a href="http://xebee.xebia.in/wp-content/uploads/2011/01/spring-integration-mail.bmp"><img class="aligncenter" src="http://xebee.xebia.in/wp-content/uploads/2011/01/spring-integration-mail.bmp" alt="Spring Integration Mail Support" width="690" height="319" /></a><br />
I am new to Spring Integration and have just started exploring its features. If you know about other ways to solve this problem, please feel free to drop me a line.</p>
<p>You can have the code base from our gitHub repository at <a href="https://github.com/xebia/NuseBites" target="_blank">https://github.com/xebia/NuseBites</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/31/spring-integration-configuring-mail-replier-adapter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring-Android: Spring for Android!!!</title>
		<link>http://xebee.xebia.in/2010/12/31/spring-android-spring-for-android/</link>
		<comments>http://xebee.xebia.in/2010/12/31/spring-android-spring-for-android/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 18:16:13 +0000</pubDate>
		<dc:creator>Yogesh Kapoor</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Middleware]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Restful]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring-Android]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[RestFul]]></category>
		<category><![CDATA[Webservice]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=7269</guid>
		<description><![CDATA[With an aim to ease the development of android applications Spring-Android, an extension to Spring framework is released.The framework with it's first release brings in RestTemplate and commons-logging support for the Android based applications. This blog is the result of my experience while using the Spring-Android framework in one of the android applications that I [...]]]></description>
			<content:encoded><![CDATA[<p>With an aim to ease the development of android applications <a href="http://www.springsource.org/spring-android">Spring-Android</a>, an extension to Spring framework is released.The framework with it's first release brings in RestTemplate and commons-logging support for the Android based applications.</p>
<p>This blog is the result of my experience while using the Spring-Android framework in one of the android applications that I am  currently working on.This post mainly focuses on the steps involved to get it working.</p>
<p><span id="more-7269"></span></p>
<p>The sample Webservice in this scenario has a method defined to handle GET requests that return all the Projects presently configured along with certain details and an array of issues. The class is as below:</p>
<pre class="brush: java; title: ; notranslate">
public class Project {
	private String name;
	private Integer id;
	private String owner;
	private Issue[] issues;
	…
	//getter and setters for all
	…
}
</pre>
<p>On a Web-service <em>GET</em> request, the project data is retrieved in JSON representation.<br />
A request to get all projects configured in the system gets back with the response below: </p>
<pre class="brush: java; title: ; notranslate">
[{&quot;class&quot;:&quot;com.xyz.Project&quot;,&quot;id&quot;:1,&quot;issues&quot;:[],&quot;name&quot;:&quot;TestProject0&quot;,&quot;owner&quot;:&quot;Test0&quot;},
{&quot;class&quot;:&quot;com.xyz.Project&quot;,&quot;id&quot;:2,&quot;issues&quot;:[],&quot;name&quot;:&quot;TestProject1&quot;,&quot;owner&quot;:&quot;Test1&quot;},
{&quot;class&quot;:&quot;com.xyz.Project&quot;,&quot;id&quot;:3,&quot;issues&quot;:[],&quot;name&quot;:&quot;TestProject2&quot;,&quot;owner&quot;:&quot;Test2&quot;}]
</pre>
<p>That completes the Rest service scenario description. Now let's find out how to access it in an Android application using Spring-Android's RestTemplate.</p>
<p>With my basic eclipse Android project already in place, I just created a lib folder so as to include Spring-Android's jar. You can download the jar files from <a href="http://www.springsource.com/download/community">here</a></p>
<p>Specifically, I have included spring-android-rest-template-1.0.0.M1.jar and spring-android-commons-logging-1.0.0.M1.jar.<br />
Apart from these two, we need to have commons-httpclient 3.x jar. This jar is required for using Spring-Android's RestTemplate. Android supports commons-httpclient 4.x. and Spring-Android's RestTemplate may support this in future.</p>
<p>Please note that we have to <strong>include the Jars from the lib folder to the Project's class path</strong> for the Dex compilation process.</p>
<p>Now, with the basic setup done, let's move over to our simple Android Activity that makes use of the Spring-Android's RestTemplate.</p>
<pre class="brush: java; highlight: [7,8,9,10]; title: ; notranslate">
public class DefaultActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	RestTemplate restTemplate = new RestTemplate();
	restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
	String url = &quot;http://192.168.1.146:8080/grailsRestWS/project/&quot;;
	String data = restTemplate.getForObject(url, String.class);
	setContentView(R.layout.main);
	}
</pre>
<p>Let's try to understand the code given above</p>
<p><strong>Line 7:</strong> It creates a restTemplate object. The RestTemplate aides Restful communication with the HTTP servers.</p>
<p><strong>Line 8:</strong> The restTemplate is assigned a requestFactory.<br />
RequestFactory is used for creating HttpClientRequest representing a client side http request.</p>
<p><strong>Line 9:</strong> The url used is not localhost or the loop back address 127.0.0.1.<br />
You might have guessed it already. The application is deployed onto a device or an Android emulator. It is the device that takes the localhost IP not the development machine. To resolve this, I have used the IP address as per my machine's network configuration.</p>
<p><strong>Line 10:</strong> It is a rest call to the web-service url. Please notice that it is a HTTP GET request as indicated by the name getForObject().<br />
I have specified the String.class as the second argument to the method which means the data returned is to be interpreted as String data.</p>
<p>The method supported by the <strong>RestTemplate</strong> are listed below</p>
<pre class="brush: java; light: true; title: ; notranslate">
HTTP 	        RestTemplate
DELETE 	        delete(String, String...)
GET 	        getForObject(String, Class, String...)
HEAD 	        headForHeaders(String, String...)
OPTIONS 	    optionsForAllow(String, String...)
POST 	        postForLocation(String, Object, String...)
PUT 	        put(String, Object, String...)
</pre>
<p>But, when I try to run this code I get an exception</p>
<pre class="brush: java; light: true; title: ; notranslate">
no suitable HttpMessageConverter found for response type [com.xebia.android.Project] and
content type [application/json]
</pre>
<p>That's because we are not dealing with text data here but JSON data type</p>
<p>Making this work requires few changes to our activity class. Below are the changes to be made</p>
<pre class="brush: java; title: ; notranslate">
public class DefaultActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		...
		RestTemplate restTemplate = &lt;strong&gt;getRestTemplate()&lt;/strong&gt;;
		JSONData[] jsonData = 	restTemplate.getForObject(url,ProjectData[].class);
		...
	}

	private RestTemplate getRestTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
		&lt;strong&gt;MappingJacksonHttpMessageConverter jsonConverter =
                                new MappingJacksonHttpMessageConverter();
		List&lt;MediaType&gt; supportedMediaTypes = new ArrayList&lt;MediaType&gt;();
		supportedMediaTypes.add(new MediaType(&quot;application&quot;,&quot;json&quot;));
		jsonConverter.setSupportedMediaTypes(supportedMediaTypes);&lt;/strong&gt;

		List&lt;HttpMessageConverter&lt;?&gt;&gt; listHttpMessageConverters = restTemplate
				.getMessageConverters();
		restTemplate.setMessageConverters(listHttpMessageConverters);
		return restTemplate;
	}
</pre>
<p>To handle the JSON array data the response should be understandable by the restTemplate.</p>
<p>As such, in the code above I have registered a <strong> MappingJacksonHttpMessageConverter </strong>with the restTemplate so as to read and write JSON data. </p>
<p>Also, we need to convey what sort of data our converter can handle e.g. text, xml, jpeg, json etc.<br />
This is done by defining a supported <strong>MediaType</strong> which in our case is MediaType("application","json")</p>
<p>You may have noticed that the second argument to the getForObject method in the code above is changed from String.class to ProjectData.class.<br />
This is because the messageCoverters for JSON and the mediaType which our converter can handle have been implemented.<br />
We can now safely state that the response from the web service is an array of ProjectData.</p>
<p>Here's our <strong>Android client </strong>side class representing Project data</p>
<pre class="brush: java; title: ; notranslate">
@JsonIgnoreProperties( {&quot;class&quot; })
public class JSONData {
	private String name;
	private Integer id;
	private String owner;
	private Issue[] issues;
	…
	//getter and setters for all
	…
}
</pre>
<p>here, JsonIgnoreProperties annotation conveys the JSON mapper that these are the properties to be excluded.<br />
The JSON response contains a class variable which I am ignoring in the code above.</p>
<pre class="brush: java; title: ; notranslate">
{&quot;class&quot;:&quot;com.xyz.Project&quot;,&quot;id&quot;:1,&quot;issues&quot;:[],&quot;name&quot;:&quot;TestProject0&quot;,&quot;owner&quot;:&quot;Test0&quot;}
</pre>
<p>Please note that issues property is declared as an array. This is because with JSON it's easier to work with arrays.</p>
<p>Note: I was getting <strong>java.lang.VerifyError </strong> when I tried to run the application in my environment and after including jackson-core-asl-1.6.1.jar and jackson-mapper-asl-1.6.1.jar everything seems to be working fine.</p>
<p>The post just describes RestFul GET method using Spring-Android's RestTemplate.The other supported RestFul methods can also be implemented in similar manner. This is the first milestone release for Spring-Android and much more can be expected in the future releases-<strong>Spring Security OAuth client </strong>being one of them.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/31/spring-android-spring-for-android/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Speech to Text Conversion in Java</title>
		<link>http://xebee.xebia.in/2010/12/31/speech-to-text-conversion-in-java-2/</link>
		<comments>http://xebee.xebia.in/2010/12/31/speech-to-text-conversion-in-java-2/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 11:06:36 +0000</pubDate>
		<dc:creator>Shruti Mehra</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Speech-to-text]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6962</guid>
		<description><![CDATA[This blog aims at creating a project for Speech-to-text conversion (Speech Recognition) on JAVA by using Eclipse IDE, Maven and a speech recognition system written entirely in Java language called Sphinx-4. Steps for Speech-to-text converter project setup: 1. Create a simple Maven project. 2. Add "http://repository.opencastproject.org/nexus/content/groups/public/" to your set of repositories in pom.xml 3. Add [...]]]></description>
			<content:encoded><![CDATA[<p>This blog aims at creating a project for Speech-to-text conversion (Speech Recognition) on <strong>JAVA</strong> by using <strong>Eclipse IDE</strong>, <strong>Maven</strong> and a speech recognition system written entirely in Java language called <strong>Sphinx-4</strong>.</p>
<p>Steps for Speech-to-text converter project setup:<br />
1. Create a simple Maven project.<br />
2. Add "<strong>http://repository.opencastproject.org/nexus/content/groups/public/</strong>" to your set of repositories in pom.xml<br />
3. Add Sphinx-4 dependency in pom.xml of your project.<span id="more-6962"></span></p>
<p>Your pom.xml should look like the following:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
  xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

  &lt;groupId&gt;com.xebia&lt;/groupId&gt;
  &lt;artifactId&gt;speech-to-text-converter&lt;/artifactId&gt;
  &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
  &lt;packaging&gt;jar&lt;/packaging&gt;

  &lt;name&gt;speech-to-text-converter&lt;/name&gt;
  &lt;url&gt;http://maven.apache.org&lt;/url&gt;

  &lt;properties&gt;
    &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
  &lt;/properties&gt;

  &lt;repositories&gt;
	&lt;repository&gt;
		&lt;id&gt;sphinx-repository&lt;/id&gt;
		&lt;name&gt;Nexus Repository&lt;/name&gt;
		&lt;url&gt;http://repository.opencastproject.org/nexus/content/groups/public/&lt;/url&gt;
	&lt;/repository&gt;
  &lt;/repositories&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;cmu.sphinx&lt;/groupId&gt;
  	  &lt;artifactId&gt;sphinx4&lt;/artifactId&gt;
  	  &lt;version&gt;4.0&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

&lt;/project&gt;
</pre>
<p>We will first write the java code for the speech recognizer. Create a class and name it "<strong>HelloWorld.java</strong>".<br />
Code it as:</p>
<pre class="brush: java; title: ; notranslate">
package com.xebia.speech-to-text-converter;

import java.io.IOException;
import java.net.URL;

import edu.cmu.sphinx.frontend.util.Microphone;
import edu.cmu.sphinx.recognizer.Recognizer;
import edu.cmu.sphinx.result.Result;
import edu.cmu.sphinx.util.props.ConfigurationManager;
import edu.cmu.sphinx.util.props.PropertyException;

/**
 * A simple HelloWorld demo showing a simple speech application built using Sphinx-4. This application uses the Sphinx-4
 * endpointer, which automatically segments incoming audio into utterances and silences.
 */
public class HelloWorld {

    public static void main(String[] args) throws IOException, PropertyException, InstantiationException {
        ConfigurationManager cm;

        if (args.length &gt; 0) {
            URL url = new URL(args[0]);
            cm = new ConfigurationManager(url);
        } else {
            cm = new ConfigurationManager(HelloWorld.class.getResource(&quot;helloworld.config.xml&quot;));
        }

        Recognizer recognizer = (Recognizer) cm.lookup(&quot;recognizer&quot;);
        recognizer.allocate();

        // start the microphone or exit if the program if this is not possible
        Microphone microphone = (Microphone) cm.lookup(&quot;microphone&quot;);
        if (!microphone.startRecording()) {
            System.out.println(&quot;Cannot start microphone.&quot;);
            recognizer.deallocate();
            System.exit(1);
        }

        System.out.println(&quot;Say: (Good morning | Hello) (( Winfred | Evandro | Paul | Philip | Will )&quot;);

        // loop the recognition until the program exits.
        while (true) {
            System.out.println(&quot;Start speaking. Press Ctrl-C to quit.\n&quot;);

            Result result = recognizer.recognize();

            if (result != null) {
                String resultText = result.getBestFinalResultNoFiller();
                System.out.println(&quot;You said: &quot; + resultText + '\n');
            } else {
                System.out.println(&quot;I can't hear what you said.\n&quot;);
            }
        }
    }
}
</pre>
<p>To set it, up and running, we will write a grammar file for the input expected by the recognizer.</p>
<p>Name it "<strong>hello.gram</strong>" and place it in the same package as HelloWorld.java file. Grammar file is always saved with <strong>.gram</strong> extension. The name of this file is used in the configuration file.</p>
<p>The grammar file will take the following form:</p>
<pre class="brush: java; title: ; notranslate">
#JSGF V1.0;
/**
* JSGF Grammar for Hello World example
*/
grammar hello;

public &lt;greet&gt; = (Good morning | Hello) &lt;name&gt;;
&lt;name&gt; = ( Winfred | Evandro | Paul | Philip | Will );
</pre>
<p>According to this grammar, the system can recognize the following if spoken:<br />
1. Good morning Winfred<br />
2. Good morning Will<br />
3. Hello Winfred<br />
4. Hello Philip<br />
or anything starting with a &lt;greet&gt; and followed by a &lt;name&gt; from the options available in grammar.</p>
<p>We also need to write a configuration file for the recognizer to configure various Sphinx-4 components.<br />
Name this file as "helloworld.config.xml" and place it in the same package as your HelloWorld.java file.<br />
Remember that the name of this file will be used in code for HelloWorld.java.<br />
You can find the code for the configuration file here: <a rel="attachment wp-att-7142" href="http://xebee.xebia.in/2010/12/31/speech-to-text-conversion-in-java-2/helloworld-config/">helloworld.config.xml</a>.</p>
<p>After performing the above steps, you can simply execute HelloWorld.java as Java Application, speak in the microphone any text in the grammar format and you will find your speech converted to text and displayed on the command prompt.</p>
<p>Sphinx-4 uses a file <strong>cmudict.0.6d</strong> found in <strong>WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar</strong> at location<br />
<strong>/edu.cmu.sphinx.model.acoustic.WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.Model!/edu/cmu/sphinx/model/acoustic/WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz/dict/cmudict.0.6d</strong> as its dictionary. This dictionary file contains words along with their pronounciation e.g. WINFRED  W IH N F R IH D will be the entry for the word Winfred in this file. You can also add your set of words in this file in the same format, i.e. word followed by its pronounciation, package it and replace the original WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar and you are ready to go!</p>
<p>These newly added words will now be recognized by Sphinx-4, provided, you also change the grammar for these words.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/31/speech-to-text-conversion-in-java-2/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Create an executable jar using maven shade plugin</title>
		<link>http://xebee.xebia.in/2010/12/31/create-an-executable-jar-using-maven-shade-plugin/</link>
		<comments>http://xebee.xebia.in/2010/12/31/create-an-executable-jar-using-maven-shade-plugin/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 05:15:41 +0000</pubDate>
		<dc:creator>samarth rastogi</dc:creator>
				<category><![CDATA[Build Tools]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Maven Plugins]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[BeanDefinitionParsingException]]></category>
		<category><![CDATA[executable]]></category>
		<category><![CDATA[jar]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[Shade]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6961</guid>
		<description><![CDATA[Last week, while working on a requirement to create an executable jar in our project, I tried the following two maven plug-ins: * Maven assembly plug-in * Maven onejar plug-in Using these plug-ins I was able to successfully create an executable jar but my executable was dependent on some Spring framework jars for its effective [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;">Last week, while working on a requirement to create an executable jar in our project, I tried the following two maven plug-ins:</span> <span style="color: #000000;"><strong> </strong></span></p>
<p><span style="color: #000000;"><strong> * </strong>Maven assembly plug-in</span></p>
<p><span style="color: #000000;"><strong> * </strong>Maven onejar plug-in</span></p>
<p><span style="color: #000000;">Using these plug-ins I was able to successfully create an executable jar but my executable was dependent on some Spring framework jars for its effective working and on executing the jar</span></p>
<p><span style="color: #000000;">I encountered some weird exceptions .  <em>(see a part of stack trace below)</em>..</span></p>
<p><em><span style="color: #ff0000;">Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException:</span></em></p>
<p><em><span style="color: #ff0000;"><span id="more-6961"></span><br />
Configuration problem: Unable to locate Spring NamespaceHandler<br />
for XML schema namespace [http://www.springframework.org/schema/context]<br />
at org.springframework.beans.factory.parsing.FailFastProblemReporter.<br />
error(FailFastProblemReporter.java:68)<br />
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)<br />
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80)<br />
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.<br />
error(BeanDefinitionParserDelegate.java:284)<br />
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.<br />
parseCustomElement(BeanDefinitionParserDelegate.java:1332)<br />
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.<br />
parseCustomElement(BeanDefinitionParserDelegate.java:1325)<br />
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.<br />
parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135)<br />
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.<br />
registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)....</span></em></p>
<p><span style="color: #000000;">I was getting these exception because the files in META-INF folder in spring jars were overwriting each other. </span><span style="color: #000000;">In our case there are several spring jars all having META-INF/spring.handlers, META-INF/spring.schemas which are used by Spring to handle XML schema namespaces. In final executable jar these files were overwriting each other.</span></p>
<p><span style="color: #000000;">Finally I found an effective maven plugin called <a href="http://maven.apache.org/plugins/maven-shade-plugin/" target="_blank">maven shade plugin</a> which resolved the problem.</span></p>
<p><span style="color: #000000;">This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade i.e. rename the packages of some of the dependencies.<br />
<span style="text-decoration: underline;"><strong><br />
Following are the steps which I followed to resolve this issue:</strong></span></span></p>
<ol>
<li><span style="color: #000000;">Create a resources folder in your src/main(ie src/main/resources)</span></li>
<li><span style="color: #000000;">Create a META-INF folder in your src/main/resources</span></li>
<li><span style="color: #000000;">Make MANIFEST.MF, spring.handlers and spring.schemas files under src/main/resources/META-INF.</span></li>
<li><span style="color: #000000;">Paste the following in plugins section of your pom.xml</span></li>
</ol>
<pre class="brush: java; title: ; notranslate">
&lt;plugin&gt;
 &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
 &lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
 &lt;version&gt;1.4&lt;/version&gt;
 &lt;executions&gt;
  &lt;execution&gt;
   &lt;phase&gt;package&lt;/phase&gt;
       &lt;goals&gt;
          &lt;goal&gt;shade&lt;/goal&gt;
       &lt;/goals&gt;
   &lt;configuration&gt;
    &lt;transformers&gt;
     &lt;transformer
   implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;
      &lt;mainClass&gt; com.company.project.Main &lt;/mainClass&gt;
     &lt;/transformer&gt;
     &lt;transformer
      implementation=&quot;org.apache.maven.plugins.shade.resource.AppendingTransformer&quot;&gt;
      &lt;resource&gt;META-INF/spring.handlers&lt;/resource&gt;
     &lt;/transformer&gt;
     &lt;transformer
      implementation=&quot;org.apache.maven.plugins.shade.resource.AppendingTransformer&quot;&gt;
     &lt;resource&gt;META-INF/spring.schemas&lt;/resource&gt;
     &lt;/transformer&gt;
    &lt;/transformers&gt;
    &lt;shadedArtifactAttached&gt;true&lt;/shadedArtifactAttached&gt;
    &lt;!-- optional --&gt;
    &lt;shadedClassifierName&gt;executable&lt;/shadedClassifierName&gt;
     &lt;/configuration&gt;
   &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #000000;"><strong><span style="font-weight: normal;">5.</span> </strong>Build your project and you will get executable jar.</span></p>
<p><span style="color: #000000;">What actually happened is the problem of overwriting files like spring.handlers and spring.schemas.</span></p>
<p><span style="color: #000000;"> <strong>Shades provides a provision to append contents of multiple files into one file.</strong></span></p>
<p><span style="color: #000000;">While aggregating classes/resources from several artifacts into one uber JAR with overlapping resources, things become complicated.</span></p>
<p><span style="color: #000000;">Shades provides you several “Resource Transformers”, in this case, we used<em> <strong>ManifestResourceTransformer </strong></em>to set the main class of the executable jar <strong>.</strong></span></p>
<p><span style="color: #000000;">Some jars contain additional resources (such as .properties files) that have the same file name. To avoid overwriting, you can opt to merge them by appending their content into one file. Here we merged the contents of all the files with that specific name using the <strong><em>AppendingTransformer</em></strong>. For xml files use XmlAppendingTransformer.</span></p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 684px; width: 1px; height: 1px; overflow: hidden;"><span style="color: #000000;">&lt;plugin&gt;<br />
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;<br />
&lt;version&gt;1.4&lt;/version&gt;<br />
&lt;executions&gt;<br />
&lt;execution&gt;<br />
&lt;phase&gt;package&lt;/phase&gt;<br />
&lt;goals&gt;<br />
&lt;goal&gt;shade&lt;/goal&gt;<br />
&lt;/goals&gt;<br />
&lt;configuration&gt;<br />
&lt;transformers&gt;<br />
&lt;transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"&gt;<br />
&lt;mainClass&gt; com.company.project.Main &lt;/mainClass&gt;<br />
&lt;/transformer&gt;<br />
&lt;transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"&gt;<br />
&lt;resource&gt;META-INF/spring.handlers&lt;/resource&gt;<br />
&lt;/transformer&gt;<br />
&lt;transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"&gt;<br />
&lt;resource&gt;META-INF/spring.schemas&lt;/resource&gt;<br />
&lt;/transformer&gt;<br />
&lt;/transformers&gt;<br />
&lt;shadedArtifactAttached&gt;true&lt;/shadedArtifactAttached&gt;&lt;!-- optional --&gt;<br />
&lt;shadedClassifierName&gt;executable&lt;/shadedClassifierName&gt;<br />
&lt;/configuration&gt;<br />
&lt;/execution&gt;<br />
&lt;/executions&gt;<br />
&lt;/plugin&gt; </span></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/31/create-an-executable-jar-using-maven-shade-plugin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Understanding WebSocket handshake</title>
		<link>http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/</link>
		<comments>http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 17:25:57 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[WebSocket]]></category>
		<category><![CDATA[WS://]]></category>
		<category><![CDATA[WSS://]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6732</guid>
		<description><![CDATA[In this blog I will discuss in detail the process of handshake in WebSocket Protocol. The first  step in WebSocket communication is the formal handshake between the client and the server. The discussion is based on the latest specification released on 16th August 2010 by I. Hickson. I will deal in detail the request and [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog I will discuss in detail the process of handshake in WebSocket Protocol. The first  step in WebSocket communication is the formal handshake between the client and the server. The discussion is based on the latest <a href="http://www.whatwg.org/specs/web-socket-protocol/">specification</a> released on 16th August 2010 by I. Hickson. I will deal in detail the request and response headers and also discuss the why aspect.</p>
<p>If reader is more interested in getting started with WebSocket you may read the blog -<a href="http://xebee.xebia.in/2010/10/05/web-socket-communication-using-jwebsocket/"> Web Socket Communication Using  jWebSocket</a>.</p>
<h3><span id="more-6732"></span></h3>
<h3>Introduction to Web Socket</h3>
<p>The ability to push data from server to client has been a long standing requirement for developing certain web based applications. HTTP protocol requires the client to send a request in order  to receive a response from server. To overcome this short coming few workarounds like polling, long polling and comet based solutions are commonly used. WebSocket protocol addresses this issue and provides a standard means of seamless communication between the client and server. Asynchronous requests can be sent by both client and server to each other. Clients have callback methods and servers can have listeners to listen to events from each other. This mode of communication is commonly referred to as full duplex communication and since WebSocket is based over TCP it uses the underlying TCP socket for communication. The additional advantage of using WebSocket protocol is its very high scalability due reduced network traffic and latency.</p>
<p>Web Socket <a href="http://www.whatwg.org/specs/web-socket-protocol/">specification</a> along with <a href="http://dev.w3.org/html5/websockets/">Web Socket API</a> forms the complete specification for using Web Sockets.</p>
<h3>Why handshake?</h3>
<p>Web Socket communication is based upon a dedicated connection between the client and server, using which both  parties can send data to each other. But before the connection gets established between the client and the server it is mandatory requirement that both the parties should agree to do so. This process is known as hand shake.  Therefore the first step in Web Socket communication is formal handshake between the client and the server which can be initiated by client alone. Browser (client) initiates the handshake by sending a HTTP GET request with an offer to upgrade to Web Socket protocol.</p>
<h3>Delving deep into the handshake</h3>
<p>Now I will start dealing with the various aspects involved in Web Socket handshake and then show how one or more of the above mentioned headers are used to facilitate the handshake.</p>
<h3>Request Headers</h3>
<p>Based on <a href="http://www.whatwg.org/specs/web-socket-protocol/">latest Web Socket specification</a> the typical request for a handshake should look like this</p>
<div id="attachment_7093" class="wp-caption alignleft" style="width: 551px"><a rel="attachment wp-att-7093" href="http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/requestheaders-4/"><img class="size-full wp-image-7093" title="requestHeaders" src="http://xebee.xebia.in/wp-content/uploads/2010/12/requestHeaders3.jpg" alt="Request Headers" width="541" height="225" /></a><p class="wp-caption-text"> </p></div>
<ul>
<li><strong>Connection and Upgrade</strong> - The browser (client) initiates the handshake by sending a HTTP GET request. But the connection is to be established using WebSocket protocol. Therefore  in the client request there should be some information which will tell the server that the client wants to upgrade the connection from HTTP protocol to  WebSocket protocol. To convey this information client includes two headers
<ul>
<li>Connection : Upgrade                   - Tells the server that the connection is an upgrade type of connection.</li>
</ul>
<ul>
<li>Upgrade:WebSocket                      - Tells the server the protocol to which the connection is to be upgraded.</li>
</ul>
<ol>
<li>The request uses GET method.</li>
<li>The request header has a Connection header with value Upgrade and a Upgrade header with value WebSocket</li>
</ol>
</li>
<blockquote>
<h4>A brief context of Upgrade Header</h4>
<p>To ease the deployment of incompatible future protocols  HTTP1.1 included a new request header 'Upgrade'. By sending the <code>Upgrade</code> header, a client can inform a server of the set of protocols it supports as an alternate means of communication. The server may choose to switch protocols, but this is not mandatory.</p></blockquote>
<p>Similarly on the server side there will be checks to ensure that</p>
<p>Only if the above two conditions are satisfied server will further process the other headers and finally establish the connection. The server side code can be somewhat like this</p>
<pre class="brush: java; title: ; notranslate">
if (aReq.getMethod() != HttpMethod.GET) {
sendHttpResponse(aCtx, aReq, new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN));
return;
}
// Serve the WebSocket handshake request.
if (HttpHeaders.Values.UPGRADE.equalsIgnoreCase(aReq.getHeader(HttpHeaders.Names.CONNECTION))
&amp;&amp; HttpHeaders.Values.WEBSOCKET.equalsIgnoreCase(aReq.getHeader(HttpHeaders.Names.UPGRADE))) {

//start processing the upgrade request.

}
</pre>
</ul>
<ul>
<li><strong>Host</strong> - It is important to ensure that the protocol is protected against threats of DNS rebinding and it should be possible to serve multiple domains from one IP address. Keeping these requirements in mind the WebSocket protocol specification requires that the handshake request should contain the Host header. Hackers use DNS rebinding to read data from private network. To know more about DNS rebinding <a href="http://vimeo.com/7907871">watch this video</a>.</li>
</ul>
<ul>
<li><strong>Origin</strong> - The server should be able to make an informed decision about whether it wishes to accept a handshake invitation from a client. The Origin request header enables the client to send information about the origin of each request to the server. Servers can use this information to decide if each request is valid or not. To know more about Origin header <a href="http://people.mozilla.com/~bsterne/content-security-policy/origin-header-proposal.html">click here</a>.</li>
</ul>
<ul>
<li><strong>Sec-WebSocket-Protocol</strong> - It is possible that the applications develop a few application level protocol layered over the WebSocket protocol. Such protocols are considered  as sub-protocols. The client should explicitly mention the sub-protocol /s which it can use to send/receive data to/from server. Sec-WebSocket-Protocol header is the sub protocol selector. In this header the client can send space separated list of strings. These string represent the sub-protocol the (the application-level protocol  layered over the WebSocket protocol) that the client can use. For example a client may be capable of handling sub protocols which send data packets in JSON, CSV or XML format. In that case the sub protocol details can be added in this header.</li>
</ul>
<ul>
<li><strong>Sec-WebSocket-Key1 and Sec-WebSocket-Key2</strong> - Since the handshake request is a plain HTTP request, there should be some way for server to identify that  it received a valid Web Socket handshake request.  This is important to ensure that the server accepts connection only from valid Web Socket requests. The security against cross protocol hacking is ensured by sending the headers Sec-WebSocket-Key1 and Sec-WebSocket-Key2 from the client. We will see in detail how these keys help ensure a cross protocol security when we discuss the response headers.</li>
<li><strong>Cookies</strong> - Like Sec-WebSocket-Protocol, Cookies is also an optional header which the client can use to send cookies to the server.</li>
<li><strong>Last 8 bytes</strong> - At the end of the handshake request there are 8 bytes of data.  Sec-WebSocket-Key1 and Sec-WebSocket-Key2 and 8 byte data are used by the server to generate the challenge response. I will talk in detail about the challenge response when I will discuss the response headers.</li>
</ul>
<h3>Response Headers</h3>
<p>On receiving the request for handshake, server starts processing the request and creates a response. Based on <a href="http://www.whatwg.org/specs/web-socket-protocol/">latest Web Socket specification</a> the typical response for a handshake should look like this.</p>
<div id="attachment_7108" class="wp-caption alignleft" style="width: 612px"><a rel="attachment wp-att-7108" href="http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/reponseheaders-3/"><img class="size-full wp-image-7108" title="reponseheaders" src="http://xebee.xebia.in/wp-content/uploads/2010/12/reponseheaders2.jpg" alt="reponseheaders" width="602" height="206" /></a><p class="wp-caption-text"> </p></div>
<ul>
<li><strong>HTTP-Status-Line</strong> - The  first line is an HTTP Status-Line, with the status code 101 - HTTP/1.1 101 WebSocket Protocol Handshake (the HTTP version and reason code are not important).</li>
<li><strong>Connection and Upgrade</strong> - For HTTP compatibility reasons the server response also includes the Upgrade and the Connection header.</li>
<li><strong>Sec-WebSocket-Location</strong> - Server also returns the host information to the client through the Sec-WebSocket-Location header. This helps both client and server agree on which host is in use for interaction.</li>
<li><strong>Sec-WebSocket-Origin</strong> - Server clearly specifies with which origin/origins it agrees to create a WebSocket connection. This is very important from security perspective.</li>
<li><strong>Sec-WebSocket-Protocol</strong>- The server also responds back with the sub-protocol it would be using to interact with the client. This response completes the cycle and establishes the sub-protocol which would be used for this connection.</li>
<li><strong>Challenge response</strong> -Server needs to assure the client that the handshake request sent by the client was received by a valid WebSocket server. That it could understand the request and agrees to interact with the client using WebSocket protocol. To ensure this the client had sent to the server three pieces of information Sec-WebSocket-Key1, Sec-WebSocket-Key2 and the 8 bit data at the end of the request. The server is supposed to process this data in a particular way specified in the specification and then create a challenge response and put it in the response. This is the answer to the challenge sent by the client. On receiving the response handshake  from the server the client checks the response code, other headers and also the challenge response. Along with other things only if the challenge response matches the result expected by the client the connection is established, otherwise the connection is closed.</li>
</ul>
<p>All these detailed handshake rules have been laid out to ensure the following</p>
<ul>
<li>Client and server can make a informed decision to allow each other to create a WebSocket connection between themselves. The Host, Sec-WebSocket-Location and the Origin headers help ensure this.</li>
<li>No imposter should be able to break the cross protocol security. Which means a WebSocket server should be able to make a clear distinction between a carefully crafted form submit, or a XmlHttpRequest pretending to be a WebSocket handshake request and a real WebSocket handshake. Quoting from the specification<br />
<blockquote><p>This is primarily achieved by requiring that the server prove that it read the handshake, which it can only do if the handshake contains the appropriate parts which themselves can only be sent by a<br />
WebSocket handshake; <strong>in particular, fields starting with |Sec-| cannot be set by an attacker from a Web browser, even when using |XMLHttpRequest|.</strong></p></blockquote>
<p>Similarly the client also checks that the handshake response received from the server has a correct challenge response, which is based on the keys sent by the client to the server. This ensures that no server side code can act to be pretending as the Web Socket server.</li>
</ul>
<p>In my next blog I will discuss how data can be exchanged post handshake (frame of data, frame type  and sub protocols).</p>
<h3>Resources</h3>
<ul>
<li><a href="http://www.whatwg.org/specs/web-socket-protocol/">WebSocket Specification - 16th August 2010</a></li>
<li><a href="http://dev.w3.org/html5/websockets/">WebSocket API W3C Editor's Draft 14 December 2010</a></li>
<li><a href="http://jwebsocket.org/">jWebSocket</a></li>
</ul>
<h3>Related articles</h3>
<ul>
<li><a href="http://xebee.xebia.in/2010/10/05/web-socket-communication-using-jwebsocket/">WebSocket communication using  jWebSocket</a></li>
<li><a href="http://xebee.xebia.in/2010/11/02/multithreading-in-javascript-with-web-workers/">WebWorkers</a></li>
<li><a href="http://xebee.xebia.in/2010/12/30/html5-vs-native-mobile-apps/">HTML5 vs Native mobile apps</a></li>
</ul>
<div xmlns:v="http://rdf.data-vocabulary.org/#" typeof="v:Person">
  Author <span property="v:name">Shankar</span>,<br />
  Organization URL:<br />
  <a href="http://xebiaindia.com/" rel="v:url">http://xebiaindia.com/</a>.<br />
  I work as <span property="v:title">Senior Consultant</span><br />
  at <span property="v:affiliation">Xebia India</span>.
</div>
<div id="_mcePaste" style="position: absolute; width: 1px; height: 1px; overflow: hidden; top: 95px; left: -10000px;">/*<br />
* To change this template, choose Tools | Templates<br />
* and open the template in the editor.<br />
*/<br />
jQuery.fn.extend({<br />
everyTime: function(interval, label, fn, times, belay) {<br />
return this.each(function() {<br />
jQuery.timer.add(this, interval, label, fn, times, belay);<br />
});<br />
},<br />
oneTime: function(interval, label, fn) {<br />
return this.each(function() {<br />
jQuery.timer.add(this, interval, label, fn, 1);<br />
});<br />
},<br />
stopTime: function(label, fn) {<br />
return this.each(function() {<br />
jQuery.timer.remove(this, label, fn);<br />
});<br />
}<br />
});jQuery.extend({<br />
timer: {<br />
guid: 1,<br />
global: {},<br />
regex: /^([0-9]+)\s*(.*s)?$/,<br />
powers: {<br />
// Yeah this is major overkill...<br />
'ms': 1,<br />
'cs': 10,<br />
'ds': 100,<br />
's': 1000,<br />
'das': 10000,<br />
'hs': 100000,<br />
'ks': 1000000<br />
},<br />
timeParse: function(value) {<br />
if (value == undefined || value == null)<br />
return null;<br />
var result = this.regex.exec(jQuery.trim(value.toString()));<br />
if (result[2]) {<br />
var num = parseInt(result[1], 10);<br />
var mult = this.powers[result[2]] || 1;<br />
return num * mult;<br />
} else {<br />
return value;<br />
}<br />
},<br />
add: function(element, interval, label, fn, times, belay) {<br />
var counter = 0;if (jQuery.isFunction(label)) {<br />
if (!times)<br />
times = fn;<br />
fn = label;<br />
label = interval;<br />
}interval = jQuery.timer.timeParse(interval);if (typeof interval != 'number' || isNaN(interval) || interval &lt;= 0)<br />
return;if (times &amp;&amp; times.constructor != Number) {<br />
belay = !!times;<br />
times = 0;<br />
}times = times || 0;<br />
belay = belay || false</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HTML5 vs Native mobile apps</title>
		<link>http://xebee.xebia.in/2010/12/30/html5-vs-native-mobile-apps/</link>
		<comments>http://xebee.xebia.in/2010/12/30/html5-vs-native-mobile-apps/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 13:52:37 +0000</pubDate>
		<dc:creator>Robin Nagpal</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[mobile usability]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6774</guid>
		<description><![CDATA[Do you want to expand your web based solution to serve smart phone/tablet users? If  yes, then you will have to opt for either a native mobile application or a web application. This blog provides for an extensive comparative study of both options and explains why HTML5 would prove to be a better solution. The [...]]]></description>
			<content:encoded><![CDATA[<p>Do you want to expand your web based solution to serve smart phone/tablet users? If  yes, then you will have to opt for either a native mobile application or a web application. This blog provides for an extensive comparative study of both options and explains why HTML5 would prove to be a better solution.</p>
<p><span id="more-6774"></span>The platforms which currently dominate the smart phone/tablet market are :<br />
1. iOS (for iPhone)<br />
2. Android<br />
3.  Blackberry OS<br />
4.  Symbian</p>
<p>Lets first see what all is required to develop native mobile applications.</p>
<p>In order to develop a native mobile application, you will have to go through the following steps :<br />
<strong> </strong></p>
<p><strong>Development</strong><br />
Each platform has a different programming language tied to it, which in turn requires specific programming language skills, which are vastly different from web programming skills. This would require developers trained in that specific language to  be hired.<br />
<strong> </strong></p>
<p><strong>Deployment</strong><br />
Furthermore, platforms like iOS and Android  have an app store associated with them, and native applications can be downloaded only from their app stores. Also, uploading an application on the Apple App Store is a long drawn process (could take 1-2 weeks) . Although, the process for uploading your app on the android market  is a tad bit simpler.<br />
<strong> </strong></p>
<p><strong>Bug Fixing / Enhancement</strong><br />
Well if the above still seemed a cakewalk, then lets look at the pain involved with bug fixes/enhancements on native apps. For each bug that is fixed, the fix would have to be replicated on each platform in turn, and the application would have to be uploaded again on each app store (the vicious circle would repeat every time) ! The whole process usually would eat up more than a month of your precious time.</p>
<p>Now lets compare this whole process to a much simpler solution offered by HTML5.</p>
<p>HTML5 provides elements like header, nav, article, section, aside, and footer which make content more browser-readable. There are a lot of frameworks that are built upon HTML5 API's which rapidly speed up the development and reduces complexity. To name a few, <strong>jQuery Mobile</strong>,<strong> iUI</strong>: iPhone User Interface Framework, <strong>jQTouch</strong> are amongst the popular development frameworks for HTML5.</p>
<p>So HTML5 does great  when it comes to UI, but what about other things like GPS, performance, storing of data in mobile or servers pushing content to your apps?</p>
<p>For this, HTML5 provides API's which cater to these features. Here is the list of some of these which can help you develop applications as powerful as native mobile applications:</p>
<ul>
<li> <strong>Geolocation API</strong> helps you get the location of the user. This API in turn, uses the on-board GPS device.</li>
<li><strong>Web workers API</strong> allows you to run multiple threads in browser.</li>
<li><strong>Web storage, Web Sql</strong> allows you to store data at client side either in the for of key value pair or in relation database format.</li>
<li><strong>Web Socket</strong> provides bi-directional, full-duplex communications channels,  over a single Transmission Control Protocol (TCP) socket.</li>
</ul>
<p>Using these API's you can now store offline data, run multiple threads and push content from server. These API's open a whole new arena where web applications can directly compete with native mobile apps.</p>
<p>Now, lets look at the different phases of HTML5 application development :</p>
<p><strong>Development</strong><br />
An HTML5 based web  application can run on phones across multiple platforms,which shortens development time and contributes to ease of development. Also, since HTML5 is a web based solution, the skill set required is almost same as that a normal web developer.<br />
An HTML 5 compliant browser is required to run HTML 5 applications, and most smart phones/tablets in the market come with one by default.</p>
<p><strong>Deployment</strong><br />
The deployment of HTML5 application is same as the normal web application. You can push the latest code to production whenever you want.</p>
<p><strong>Bug Fixing/Enhancement</strong><br />
Compared to the cycle for native apps, the enhancement cycles for an HTML5 app is very small as the application can be deployed immediately after the enhancement is made. Similar is the case for Bug fixes.</p>
<p>Lets side by side see the comparison of HTML5 and Native apps.</p>
<p><a rel="attachment wp-att-7047" href="http://xebee.xebia.in/2010/12/30/html5-vs-native-mobile-apps/compare/"><img class="alignleft size-full wp-image-7047" title="compare" src="http://xebee.xebia.in/wp-content/uploads/2010/12/compare.jpg" alt="" width="680" height="329" /></a></p>
<p>Thus, there are pros and cons of both the techniques used for developing  mobile app. If you want to build a simple internet based application  just go for HTML5 , however if you want to develop a performance  intensive application like games etc making native applications is  always a better choice.</p>
<p>Some of the big players who are following this trend are<br />
<a href="http://www.fliptrack.com/" target="_new">http://www.fliptrack.com/</a><br />
<a href="http://www.nextstop.com" target="_new">http://www.nextstop.com</a></p>
<p>Related Articles</p>
<p><a href="http://xebee.xebia.in/2010/11/02/multithreading-in-javascript-with-web-workers/" target="_new">Web Workers</a></p>
<p><a href="http://xebee.xebia.in/2010/12/30/understanding-websocket-handshake/">Understanding WebSocket handshake</a></p>
<p><a href="../2010/10/05/web-socket-communication-using-jwebsocket/">WebSocket communication using  jWebSocket</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/30/html5-vs-native-mobile-apps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating Seam-Hibernate Maven archetype</title>
		<link>http://xebee.xebia.in/2010/12/29/creating-seam-hibernate-maven-archetype/</link>
		<comments>http://xebee.xebia.in/2010/12/29/creating-seam-hibernate-maven-archetype/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 11:23:58 +0000</pubDate>
		<dc:creator>Rajdeep Mann</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Maven Archetype]]></category>
		<category><![CDATA[Maven3]]></category>
		<category><![CDATA[Seam]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Maven archetype]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6531</guid>
		<description><![CDATA[It all started when me and Vaibhav were getting our feet wet in a new project. The project was based on Seam and Hibernate. While trying to create sample projects involving Seam and Hibernate, we found most of the constructs were using Ant as build tool, thus limiting stuff like reporting, standard build lifecycle. Further they used [...]]]></description>
			<content:encoded><![CDATA[<p>It all started when me and <a href="http://xebee.xebia.in/author/vaibhav sehgal/">Vaibhav</a> were getting our feet wet in a new project. The project was based on <a href="http://www.seamframework.org">Seam</a> and <a href="http://www.hibernate.org">Hibernate</a>. While trying to create sample projects involving Seam and Hibernate, we found most of the constructs were using <a href="http://ant.apache.org/">Ant</a> as build tool, thus limiting stuff like reporting, standard build lifecycle. Further they used seam-gen to generate startup projects. Also, available maven archetypes used EJB's (not suited to our purpose). So we thought of creating our own maven archetype based on Seam and Hibernate.</p>
<p><span id="more-6531"></span>We went through the following steps to create the archetype:</p>
<ul>
<li>First we created the structure of the project that we wanted to be generated from the archetype.</li>
</ul>
<ul>
<li>We then used the command  <strong>mvn archetype:create-from-project</strong> (in root directory). An important file to be considered after this step is <strong>archetype-metadata.xml</strong> (found in target/generated-sources/archetype/src/main/resources/META-INF/maven) which contains meta information about the directories and files that will be included in the archetype. We can further enrich this file by marking required properties, giving them default values or even creating new properties. For example
<pre class="brush: xml; title: ; notranslate">
      &lt;requiredProperties&gt;
	    &lt;requiredProperty key=&quot;groupId&quot;&gt;
	      &lt;defaultValue&gt;com.xebia&lt;/defaultValue&gt;
	    &lt;/requiredProperty&gt;
	  &lt;/requiredProperties&gt;
</pre>
</li>
<li>We now ran <strong>mvn install </strong>(after navigating to target/generated-sources/archetype) to finally generate the required archetype.</li>
</ul>
<p>This method allowed us to use an IDE to generate the startup project and automatically convert it into the the archetype by running few commands.</p>
<p>The archetype uses seam, hibernate to provide the core functionality and spring,  dbunit are used in test cases. The project generated from archetype has user registration, login-logout functionality implemented.<br />
The structure of our project was :</p>
<pre class="brush: xml; title: ; notranslate">

|--pom.xml
`-- src
|-- main
|   |-- java
|   |   `-- com
|   |       `-- xebia
|   |           `-- seam
|   |               |-- components
|   |               |   |-- Login.java
|   |               |   `-- Register.java
|   |               `-- domain
|   |                   `-- User.java
|   |-- resources
|   |   |-- hibernate.cfg.xml
|   |   |-- hibernate.properties
|   |   `-- seam.properties
|   `-- webapp
|       |-- home.xhtml
|       |-- index.jsp
|       |-- login.xhtml
|       |-- META-INF
|       |   `-- MANIFEST.MF
|       |-- register.xhtml
|       |-- template.xhtml
|       `-- WEB-INF
|           |-- components.xml
|           |-- faces-config.xml
|           |-- lib
|           |-- pages.xml
|           `-- web.xml
`-- test
|-- java
|   `-- com
|       `-- xebia
|           `-- seam
|               |-- components
|               |   `-- LoginTest.java
|               `-- databaseSetup
|                   `-- IDataMethods.java
`-- resources
|-- dataset.xml
`-- hibernate-test.cfg.xml
</pre>
<p>It was fun learning how maven can be used to do stuff that cannot be done with the help of other build tools which are pretty limited in the build scope.<br />
The archetype source is <a href="http://xebee.xebia.in/wp-content/uploads/2010/12/archetype.zip">here</a> , just unzip it and run mvn install to install the archetype in local repository.Then use <strong>mvn</strong> <strong>archetype:generate -DarchetypeCatalog=local</strong> to generate new project. We plan to release it to the maven repositories soon. Watch this blog for more updates.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/29/creating-seam-hibernate-maven-archetype/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android : ListView With Images and Cursor.</title>
		<link>http://xebee.xebia.in/2010/12/28/android-listview-with-images-cursor/</link>
		<comments>http://xebee.xebia.in/2010/12/28/android-listview-with-images-cursor/#comments</comments>
		<pubDate>Tue, 28 Dec 2010 17:30:48 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Cursor]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[IconicAdapter]]></category>
		<category><![CDATA[ListView]]></category>
		<category><![CDATA[SimpleCurserAdapter]]></category>
		<category><![CDATA[SQLLite]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6825</guid>
		<description><![CDATA[Hello , I have recently  put my feet into the vast sea of Android by working on my first hands-on simple 'Android Application' which allows you to create and manage personal reminders like Birthday,  Anniversary,   home inauguration etc. and send customized messages based on the type of event. So in this application,  I encountered [...]]]></description>
			<content:encoded><![CDATA[<p>Hello ,</p>
<p>I have recently  put my feet into the vast sea of Android by working on my first hands-on simple 'Android Application' which allows you to create and manage personal reminders like Birthday,  Anniversary,   home inauguration etc. and send customized messages based on the type of event.</p>
<p>So in this application,  I encountered a requirement of displaying the data in a listView from Database using cursors along with images which I downloaded from some external source. I wanted the listView to display data and images dynamically based on my business logic.</p>
<p>After some experiments and looking over the related broken chunks scattered all over android related websites and blogs,<br />
I created this simple piece of code that does all which I mentioned earlier using the following:</p>
<p>1. A Custom view Layout<br />
2. IconicAdapter<br />
3. SimpleCursorAdapter Implementation</p>
<p><span id="more-6825"></span></p>
<p>I did some extension of the code to implement AlertDialog and ItemClickListeners for deleting and refreshing view which can be helped with if desired by any viewer.</p>
<p><a rel="attachment wp-att-6826" href="http://xebee.xebia.in/2010/12/28/android-listview-with-images-cursor/snapshot/"><img class="size-full wp-image-6826 alignleft" title="SnapShot" src="http://xebee.xebia.in/wp-content/uploads/2010/12/SnapShot.png" alt="" width="358" height="511" /></a>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>First of all, Create your custom layouts for showing list contents in your way (imagelist.xml )</p>
<pre class="brush: java; title: ; notranslate">&lt;/pre&gt;
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout
 xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 android:layout_width=&quot;wrap_content&quot;
 android:layout_height=&quot;wrap_content&quot;&gt;
 &lt;ListView android:id=&quot;@+id/LISTVIEW&quot; android:layout_width=&quot;wrap_content&quot;
   android:layout_height=&quot;wrap_content&quot;&gt;
/ListView&gt;
&lt;/LinearLayout&gt;
&lt;pre&gt;</pre>
<p>This is the renderer layout xml (mylayout.xml)</p>
<pre class="brush: java; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;wrap_content&quot;&gt;

 &lt;ImageView android:id=&quot;@+id/labelImage&quot; android:layout_width=&quot;32dip&quot;
     android:layout_height=&quot;32dip&quot; android:layout_marginTop=&quot;14dip&quot; /&gt;
 &lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
     android:id=&quot;@+id/label1&quot; android:layout_width=&quot;wrap_content&quot;
     android:layout_height=&quot;wrap_content&quot;
     android:textAppearance=&quot;?android:attr/textAppearanceMedium&quot;
     android:gravity=&quot;center_vertical&quot; android:paddingLeft=&quot;6dip&quot;
     android:minHeight=&quot;?android:attr/listPreferredItemHeight&quot;
     android:textColor=&quot;#ffffff&quot; /&gt;
 &lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
     android:id=&quot;@+id/label2&quot; android:layout_width=&quot;wrap_content&quot;
     android:layout_height=&quot;wrap_content&quot;
     android:textAppearance=&quot;?android:attr/textAppearanceSmall&quot;
     android:gravity=&quot;center_vertical&quot; android:paddingLeft=&quot;2dip&quot;
     android:minHeight=&quot;?android:attr/listPreferredItemHeight&quot;
     android:textColor=&quot;#ffffff&quot; /&gt;
 &lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
     android:id=&quot;@+id/label3&quot; android:layout_width=&quot;wrap_content&quot;
     android:layout_height=&quot;wrap_content&quot;
     android:textAppearance=&quot;?android:attr/textAppearanceSmall&quot;
     android:gravity=&quot;center_vertical&quot; android:paddingLeft=&quot;6dip&quot;
     android:minHeight=&quot;?android:attr/listPreferredItemHeight&quot;
     android:textColor=&quot;#ffffff&quot; /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>And here is the Activity which uses a cursor to map the database values  in the labels of listView and overriding the getView() method of IconicAdapter and setting the image based on your logic.</p>
<pre class="brush: java; title: ; notranslate">
import .....
public class MyActivity extends Activity {
 public DBManager helper;
 private String[] from;
 private int[] to;
 private Cursor c;
 private ListView list;

 @Override
 public void onCreate(Bundle savedInstance) {
     super.onCreate(savedInstance);
     setContentView(R.layout.imagelist);
     list = (ListView) findViewById(R.id.LISTVIEW);
     getOccasions();
     list.setAdapter(new IconicAdapter());
  }

 private void getOccasions() {
     helper = new DBManager(this);
     helper.open();
     c = helper.getAll();
     from = new String[] { DBManager.NAME,
      DBManager.OCCASION_TYPE,
     OccasionManagerDAO.DBManager };
     if (c.getCount() == 0) {
       helper.close();
     } else {
       c.moveToFirst();
     }
     to = new int[] { R.id.label1, R.id.label2, R.id.label3 };
  }

 class IconicAdapter extends SimpleCursorAdapter {
     IconicAdapter() {
     super(MyActivity.this, R.layout.listviewlayout, c, from, to);
 }

 public View getView(int position, View convertView, ViewGroup parent) {
     View row = super.getView(position, convertView, parent);
     ImageView icon = (ImageView) row.findViewById(R.id.labelImage);
     if (c.getString(5).toLowerCase().equals(&quot;birthday&quot;)) {
         icon.setImageResource(R.drawable.bday);
     } else if(c.getString(5).toLowerCase().equals(&quot;anniversary&quot;)){
         icon.setImageResource(R.drawable.anniv1);
     }
     else{
         icon.setImageResource(R.drawable.gift);
     }
     return (row);
  }
 }
}
</pre>
<p>Do try and let me know if anything fails to work for you ...</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/28/android-listview-with-images-cursor/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Work stands still&#8230;when Xebia enjoys their annual &#8220;Skiindia&#8221;</title>
		<link>http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/</link>
		<comments>http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 06:47:31 +0000</pubDate>
		<dc:creator>sparveen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6734</guid>
		<description><![CDATA[For these few days in a year everything comes to a standstill at Xebia. No standup, no planning meeting, no retro, people just wish to make the most out of these three days. It was Wednesday, Dec 8th and we were working usual but there was a flavor of excitement and anticipation in the air. [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align: justify;">For these few days in a year everything comes to a standstill at Xebia. No standup, no planning meeting, no retro, people just wish to make the most out of these three days. It was Wednesday, Dec 8th and we were working usual but there was a flavor of excitement and anticipation in the air. We were all looking forward to our much awaited annual trip. Our memories of the last year trip were still alive and we were all set to put them a step back in our mind and make space for the new ones. This time we were looking forward to capturing the  beautiy of the mountains. We were set to move to “Kanatal”, a picture perfect location amidst the tall mountain range. <a rel="attachment wp-att-6820" href="http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/_dsc0343-2/"><img class="alignright size-medium wp-image-6820" title="Xebia Family" src="http://xebee.xebia.in/wp-content/uploads/2010/12/DSC03431-300x199.jpg" alt="" width="300" height="199" /></a></div>
<div style="text-align: justify;">The most enthusiastically awaited event of Xebia took us all by storm once again. <strong>Dec 9, 10 &amp; 11 left us mesmerized</strong> and asking for more as usual.<span id="more-6734"></span></p>
<p>Two of our French colleagues joined us for the trip. They seemed to more excited than us as it was their very first encounter with real India. <strong>The fun started right when we boarded the train.</strong> Though it was midnight, but it seemed as if we have just started our day.  Dumb-Charades topped the favoured list of all.</p>
<p>With sleep in our eyes, we got down at Dehradun and started our 3 days journey to Kanatal. The view outside was abslutely stunning. Beautiful and raw. Billboards of Kanatal Resort &amp; Spa on the way were pumping all the excitement in.</p>
<p>After the rollercoaster ride in the buses with people feeling motion sickness and trying to hold on till we reach our destination, we could see the other side of the personalities already. We were all bond eternally to a common goal……. The goal that we all will enjoy and have fun irrespective of the challenges posed by the coiled journey into the mountains and FUN is what we all were committed to!!</p>
<p>Almost in an hour we reached the most awaited <strong>Kanatal Resort</strong>, a five star facility amidst the nature. Nothing more one can ask for. After warm welcome by hotel staff, we headed to our respective rooms.</p>
<p>Afternoon was scheduled for a<strong> trip to Dhanaulti</strong>,a 20 mins drive from Kanatal. Coaches started after exotic lunch and we reached the bio park of Dhanaulti . Trekking and finding our way together to the top was a great  feeling. Looking at the people giving hand of help to each other and looking after for each other was depicting the true Xebia culture. Some of us visited <strong>the famous Surkanda Devi Temple</strong> and for some of us it was a real health check. The spot is located on a hill and one reaches there after a steep 1.5 km trek. Make sure that next time if you plan to visit this place, travel during daylight.</p>
<p>With a <strong>predefined itinerary for all the three days</strong>, people had planned their hot water bath at swimming pool, Spa, Steam bath &amp; Sona Bath. Forgetting the daily chores, people were having fun playing Fuss ball, badminton, Video games,Basket ball and lot other activities.</p>
<p>The evening was all decked up for the much awaited <strong>DJ Theme Night</strong>.  <a rel="attachment wp-att-6817" href="http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/dscn1474-2/"><img class="alignleft size-medium wp-image-6817" title="MEOW moment of the DJ Night" src="http://xebee.xebia.in/wp-content/uploads/2010/12/DSCN14741-300x225.jpg" alt="" width="243" height="182" /></a>With everybody in Red and Black attire and hiding behind their Eye Masks, it was fun to get hold of their partners for the Paper Dance , which also happened to be top-pick of the day. Amused to see our European colleagues dancing the Indian way and still wanting for more, we all went to bed waiting for another day to start.</p>
<p>Unexpectedly, all ready on time, we met on breakfast table and soon left for scheduled <strong>rock climbing and rappelling</strong>. <a rel="attachment wp-att-6818" href="http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/img_1238/"><img class="alignright size-medium wp-image-6818" title="On Top of the WORLD!!" src="http://xebee.xebia.in/wp-content/uploads/2010/12/IMG_1238-300x168.jpg" alt="" width="271" height="168" /></a>Excited about it, some waited for their turn while other went trekking ahead to explore the nature beauty. Mountains, farms and fields… we all came back to resort where, the hot lunch was served in middle of Jungle. To our surprise, last day’s DJ success paved way for today’s DJ program. All decked up in our best with unlimited cocktails and snacks, we enjoyed till midnight. People who appeared to be reserved in office, came out to be a real surprise. Some dance performances were a real pick of the day kind of items, people whom we couldn’t imagine to shake a leg were break dancing!!</p>
<p>Already feeling sad, we got up Saturday morning, still wanting to stay more. <strong>Mussoorie was the destination</strong> now. With all the fun during the way, we reached Mussoorie and were all set for our shopping spree followed by exotic lunch at hotel.</p>
<p>Trip ended at New Delhi station at mid night. Ski India gives all of us a chance to come out from our shells, to charge our batteries and to unwind &amp; unfold ourselves to feel more connected with each other and ready for the all the hard work ahead. Everyone looks forward for such trip every year.</p>
<p>Already looking forward for our Ski India 2011.</p>
<p>GO TEAM!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/27/work-stands-still-when-xebia-enjoys-their-annual-skiindia/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Caching in JBoss Seam based web applications</title>
		<link>http://xebee.xebia.in/2010/12/21/caching-in-jboss-seam-based-web-applications/</link>
		<comments>http://xebee.xebia.in/2010/12/21/caching-in-jboss-seam-based-web-applications/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 05:44:21 +0000</pubDate>
		<dc:creator>ggembali</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6475</guid>
		<description><![CDATA[Caching is one important area where you can drastically improve the performance of your web application. The data that needs to be cached can be of two different types : Rendered data (like html snippet,xml or JSON) and Java objects. JBoss seam provides few out of the box caching solutions for both types of data. [...]]]></description>
			<content:encoded><![CDATA[<p>Caching is one important area where you can drastically improve the performance of your web application. The data that needs to be cached can be of two different types : Rendered data (like html snippet,xml or JSON) and Java objects. <a href="http://seamframework.org/">JBoss seam </a>provides few out of the box caching solutions for both types of data. As seam is component based framework, it provides these features through pre-configured application scoped components. You can easily switch between different cache provider like JBoss Tree caching and EHCaching. Here, I will take you through different steps to use caching features in seam in an effective manner.</p>
<p><span id="more-6475"></span></p>
<p>As I said above, in Seam everything is a component (You can get full details <a href="http://docs.jboss.org/seam/2.2.0.GA/reference/en-US/html/concepts.html">here</a>). So first lets configure this caching component in Seam by specifying it in components.xml as follows.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;components xmlns=&quot;http://jboss.com/products/seam/components&quot;
    xmlns:cache=&quot;http://jboss.com/products/seam/cache&quot;
   xsi:schemaLocation=&quot;
    http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.2.xsd
    http://jboss.com/products/seam/cache http://jboss.com/products/seam/cache-2.2.xsd
&quot;&gt;
   &lt;cache:eh-cache-provider configuration=&quot;ehcache.xml&quot; /&gt;
&lt;/components&gt;</pre>
<p>The caching configuration file provided above is optional and note that we are using ehache provider. So the configuration file format has no seam specific things. If you want you can switch your cache provider with tree cache just by replacing ehcache line with</p>
<pre class="brush: xml; title: ; notranslate">&lt;cache:jboss-cache-provider configuration=&quot;treecache.xml&quot; /&gt;
</pre>
<p>Irrespective of the provider, the following details will remain same.</p>
<h4>Page fragment caching :</h4>
<p>This feature provides a mechanism to cache the rendered data like html snippet (part of the html page). When I first heard about it, the first question that came to mind is <strong><em>"Why not cache the page using web server?"</em></strong>.  This is obviously the best option if you need to cache the whole page, but if you want to cache only a part of it, web server can not provide that. And another advantage you can have with page fragment caching is, programmatic control over caching.</p>
<p>In seam, a part of html can be cached just by surrounding it with<a href="http://www.jsftoolbox.com/documentation/seam/09-TagReference/seam-cache.html" target="_blank"> s:cache</a> tag.</p>
<pre class="brush: xml; title: ; notranslate">&lt;div&gt;
  &lt;span&gt;I am not cached &lt;/span&gt;
&lt;div&gt;
&lt;s:cache&gt;
	&lt;div&gt;
		&lt;span&gt;I am cached. No need to render every time  &lt;/span&gt;
	&lt;/div&gt;
&lt;/s:cache&gt;
</pre>
<p>So simple. Isn't it?  You can provide regions and keys like in any normal caching, as attributes to further control caching.</p>
<h4>Object Caching :</h4>
<p>If you have used frameworks like Hibernate, you might have heard about caching the database returned objects (Level1 caching). Just like caching objects returned from database, you might like to use few objects returned from service layer. For example, if you are building social network site you might need list of country objects at different places like in registration form, search form etc. So it makes sense to cache them instead of populating them from database every time. Note that page fragment caching won't be effective if you are using this list at different places in different formats. To use this feature you can inject the cache provider component and use it to put\remove\update operations.</p>
<pre class="brush: java; title: ; notranslate">
@In
private CacheProvider&lt;CacheManager&gt; cacheProvider;
----
----
Object obj = cacheProvider.get(&quot;key&quot;,&quot;region&quot;);
update(obj);
cacheProvider.put(&quot;key&quot;,&quot;region&quot;,obj);
</pre>
<p>Here the CacheProvider is an abstract class that is a wrapper around underlying cache manager. So you can implement a custom cache provider by implementing this abstract class. Infact above page fragment caching also uses this <code>CacheProvider</code> in the background (afterall html snippet which is nothing but a String Object).</p>
<h4>When to use what :</h4>
<p>Well we have two ways of caching. But when to use page fragment caching and when to use object caching. One simple rule normally I use, to make this decision is - "<strong><em>Am I going to reuse the model objects at different places?</em></strong>".  If the answer is 'No', go for page fragment caching. Because it doesn't make sense go through all the layers to again create the same html fragment instead of caching the final output.</p>
<p>This is the basic setup that can get you started seam caching. Further you can explore providing custom caching manager, some more parameters to decide between page fragment caching and object caching. Suggestions and questions in these areas are most welcome <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/21/caching-in-jboss-seam-based-web-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How easy is to develop online games using jQuery!</title>
		<link>http://xebee.xebia.in/2010/12/08/how-easy-is-to-develop-online-games-using-jquery/</link>
		<comments>http://xebee.xebia.in/2010/12/08/how-easy-is-to-develop-online-games-using-jquery/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 12:30:02 +0000</pubDate>
		<dc:creator>Jayant Dhingra</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6377</guid>
		<description><![CDATA[Online Games!!! Be it a bear fishery, yeti sports, shooting gallery, battlefield or urban terror only thing that comes to mind is the powerful graphics and the animations that attract and bind the player to play. Now a days most of the lightweight online games are driven by flash leveraging the benefits of flash based [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>Online Games!!!</p>
<p>Be it a bear fishery, yeti sports, shooting gallery, battlefield or urban terror only thing that comes to mind is the powerful graphics and the animations that attract and bind the player to play. Now a days most of the lightweight online games are driven by flash leveraging the benefits of flash based technologies and other heavyweights fall under the category of offline or network based. <span id="more-6377"></span></p>
<p>On a smaller scale, the basic premise of the gaming effects is to obtain image tranformation, image manipulation, animations, visual and audio effects. The effects are basically driven geometrically which could be amongst rotary, linear motion, circular motion, rectilinear or polygonic motion etc. The rotation includes circular or angular etc. These kinds of effects and motions, in two dimensions or three dimensions, can also be very easily obtained by using scripting language (jQuery) and CSS. There are other stuffs too that take care of storage and state management but in this blog I am only writing about how to get the frontend effects using jQuery.</p>
</div>
<p>Developing an online game 2d or 3d is not that much difficult ever since <a href="http://jquery.com/">jquery</a> launched animate plugin in the API. The plugin not only helps in creating animation effects but also provides a platform where in one can introduce the added effects with the help of CSS. Most of animations like easing, moving, rotating, looping, delay, timeout intervals can be caused by .animate() function of jQuery object. Another important thing is to make good use of z-index of CSS which actually helps positioning of elements or images. Lastly, these effects are bound to the user events (mouse or keys) for the virtual reality experience.</p>
<div>
<p>To start with let me show you how to write a <em>jQuery plugin</em>. The reason for writing plugin is to make the most out of the library and abstract the most clever and useful functions out into reusable code that can save time and make development even more efficient.</p>
<p>The code listing below shows the sample plugin skeleton.</p>
<pre class="brush: java; title: ; notranslate">&lt;br /&gt;
(function( $ ){&lt;br /&gt;
  $.fn.myPlugin = function() {&lt;/p&gt;
&lt;p&gt;    // provide some logic this plugin does.&lt;/p&gt;
&lt;p&gt;  };&lt;br /&gt;
})( jQuery );&lt;/p&gt;
&lt;p&gt;</pre>
<p>The listing below calls the myPlugin written above on the given element.</p>
<pre class="brush: java; title: ; notranslate">&lt;br /&gt;
$('#element').myPlugin();&lt;br /&gt;
</pre>
<p>Next code listing shows how to set width to all the div elements and setting color to blue.</p>
<pre class="brush: java; title: ; notranslate">&lt;br /&gt;
(function( $ ){&lt;br /&gt;
  $.fn.setWidthDim = function( type ) {&lt;/p&gt;
&lt;p&gt;	return this.each(function() {&lt;/p&gt;
&lt;p&gt;		var $this = $(this);&lt;br /&gt;
      if ( !type || type == 'width' ) {&lt;br /&gt;
        $this.width( $this.width() );&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
  };&lt;br /&gt;
})( jQuery );&lt;br /&gt;
</pre>
<p>Calling above plugin:</p>
<pre class="brush: java; title: ; notranslate">&lt;br /&gt;
$('div').setWidthDim('width').css('color', 'blue');&lt;br /&gt;
</pre>
<p>To understand more about the syntax and jQuery function object, refer the docs at <a href="http://docs.jquery.com/Plugins/Authoring">jQuery Plugin</a>.</p>
<p>Here, I intend to <em>rotate an image at an angle and move the image linearly in that direction</em> with some animation effects. This probably is fair enough start for the preparation of gaming engine as far as scripting is concerned. The animation effects could be chosen directly from .animate plugin or some open source resources which can add needed effects to it as per the requirements. In this example, the easing effect used is the default .animate easing feature, special easing functions could also be plugged-in though. The duration of the animation is the time in ms; higher the duration slower the speed and vice versa.</p>
<p><strong> </strong></p>
<div style="text-align: left; width: 700px; margin-left: 0px;"><strong>Image Movement with angular rotation using jQuery Plugin-AngularMove.js</strong></div>
<p><strong>Usage:</strong></p>
<p>  $("#image").angularMove(parameters)</p>
<p><strong>Returns:</strong></p>
<p>  jQueryAngularMoveElement</p>
<p>function returns angularMoveElement instance to help connect events with actually created 'rotation' element.</p>
<p><strong>Parameters:</strong></p>
<p> ({</p>
<p>  angleRotation: angleRotationValue,</p>
<p>  move: moveValue,</p>
<p>  duration: durationValue,</p>
<p>  keepGoing: keepGoingValue,</p>
<p>  easing: easingValue</p>
<p> })</p>
<p>jQuery(imgElement).angularMove</p>
<p><strong>Where:</strong></p>
<p>- angleRotationValue: clockwise rotation given in degrees (between -360 and 360, angle given more than 360 leads to only rotation</p>
<p>but no linear motion),</p>
<p>- moveValue(boolean): boolean value for linear motion,</p>
<p>- durationValue: A string or number determining duration of the animation {"slow", "fast", or number like 100},</p>
<p>- keepGoingValue(boolean): boolean value for same animation effects to go infinitely,</p>
<p>- easingValue: A string indicating which easing function to use for the transition {"linear", "swing"}</p>
<p><strong>Example:</strong></p>
<pre class="brush: java; title: ; notranslate">&lt;/p&gt;
&lt;p&gt;	1. Animation effects to go infinitely&lt;br /&gt;
		$(document).ready(function()&lt;br /&gt;
		{&lt;br /&gt;
			$(&quot;#image&quot;).angularMove({&lt;br /&gt;
					angleRotation: -60,&lt;br /&gt;
					move: true,&lt;br /&gt;
					duration: 100,&lt;br /&gt;
					keepGoing: true,&lt;br /&gt;
					easing: 'linear'&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;/p&gt;
&lt;p&gt;	2. Animation effects to go until duration as specified in parameter&lt;br /&gt;
		$(document).ready(function()&lt;br /&gt;
		{&lt;br /&gt;
			$(&quot;#image&quot;).angularMove({&lt;br /&gt;
					angleRotation: -60,&lt;br /&gt;
					move: true,&lt;br /&gt;
					duration: 4000,&lt;br /&gt;
					keepGoing: false,&lt;br /&gt;
					easing: 'linear'&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;/p&gt;
&lt;p&gt;</pre>
<p><strong>Demo:</strong></p>
<p>The example shown below works fine on IE 8 though script is tested on IE 8 and Google Chrome.</p>
<p>The plugin does bind to key events to a certain extent. Controls for the manual movementare as follows:</p>
<p>Key- j : left, i: up and l: right</p>
<p>and switching from infinite to manual mode requires window refresh.</p>
<p><!--</p>
<p>/* <[CDATA[ */ 			html, body { 				padding: 0; 				margin: 0; 				height:710px; 			} 			img { 				position:relative; 				z-index:0; 				width:auto; 				opacity: 1.00; 			} 			/* ]]&gt; */</p>
<p>--></p>
<p><script type="text/javascript">// <![CDATA[
      			function rotateAndMove() { 				$("#j_img").angularMove({ 					angleRotation: parseInt($("#inAngle").val()), 					move: true, 					duration: parseInt($("#inDur").val()), 					keepGoing: $('input[name=chkb]').attr('checked'), 					easing: 'linear' 				}); 			} 			function changeDur() { 			if($('input[name=chkb]').attr('checked')){ 				$("#inDur").attr('disabled', true).val('100'); 			} else { 				$("#inDur").attr('disabled', false); 			} 		}
// ]]&gt;</script><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script><script src="http://xebee.xebia.in/wp-content/uploads/2010/12/jquery.angularMove.1.1.js" type="text/javascript"></script></p>
<p><script src="http://wilq32.adobeair.pl/jQueryRotate/jQueryRotate.js" type="text/javascript"></script></p>
<div id="id1" style="position: relative; width: 680px; background: url(http://xebee.xebia.in/wp-content/uploads/2010/12/bg_img.png) no-repeat left top; height: 410px; overflow: hidden;"><img id="j_img" style="background-color: transparent!important; position: absolute; border: 0px;" src="http://xebee.xebia.in/wp-content/uploads/2010/12/jt_img.png"  alt="" /></div>
<table style="margin-top: 10px; width: 675px;  border: green 1px solid; padding: 2px;">
<tr>
<td  width="150px">Angle:</p>
<input id="inAngle" size="10" type="text" value="120" /></td>
<td width="170px">Duration (ms):</p>
<input id="inDur" size="10" type="text" value="100" /></td>
<td width="150px">Infinite :</p>
<input id="inInf" onclick="return changeDur();" checked="checked" name="chkb" type="checkbox" value="Infinite" /></td>
<td>
<input id="clik" onclick="return rotateAndMove();" type="button" value="Play" style="width:100px"/></td>
</tr>
</table>
<div>
<p>You can download the complete source code of the plugin from Github repository</p>
<p><a href="https://github.com/jdhingra/AngularMove">jquery.angularMove.1.1.js</a>.</p>
<p>For writing a plugin refer the docs at <a href="http://docs.jquery.com/Plugins/Authoring">jQuery Plugin</a>.</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/08/how-easy-is-to-develop-online-games-using-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring &#8211; Altering your applicationContext at runtime</title>
		<link>http://xebee.xebia.in/2010/12/08/spring-altering-your-applicationcontext-at-runtime/</link>
		<comments>http://xebee.xebia.in/2010/12/08/spring-altering-your-applicationcontext-at-runtime/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 06:25:46 +0000</pubDate>
		<dc:creator>Rohit Garg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[ApplicationContext]]></category>
		<category><![CDATA[Bean]]></category>
		<category><![CDATA[Creation]]></category>
		<category><![CDATA[dynamic]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6609</guid>
		<description><![CDATA[In my previous blog over spring integration, I gave a hint over creating adapters dynamically. In this writeup, I would try to detail out the things a bit. Primarily spring is all about maintaining objects so called beans in the memory through a configuration file. A better design is the one which doesn't involve creation [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous blog over spring integration, I gave a hint over creating adapters dynamically. In this writeup, I would try to detail out the things a bit. Primarily spring is all about maintaining objects so called beans in the memory through a configuration file. A better design is the one which doesn't involve creation of objects in a way that its hard to find out where and why has it been created. Hence spring has gained a lot of popularity these days because it provides a mechanism to split the creation and binding part from the actual logic.<br />
<span id="more-6609"></span><br />
<br/></p>
<p><em><strong>Practical application :</strong></em><br />
Spring application context needs to be modified only if there is a requirement of a parent context which provides a configuration management functionality over the actual application. In case you want to start or stop your application by giving a command or maybe some configuration that you want to change inside your context and restart it. A typical example could be a managed network messaging system that doesn't initially know the place that it needs to send data to. In such a case, the configuration is received while the application is running and the beans need to be created after the configuration has been received and broken into logical pieces.</p>
<p><em><strong>The code part :</strong></em><br />
For achieving this, the framework relies on a configuration file generally referred to as <em>applicationContext.xml</em> file. This file is an externalized source to describe and even bind the objects of classes written within your code together. You might have faced scenarios where you actually don't know what needs to be written inside the XML because either its being evaluated through some logic or work-flow that actually decides what needs to be created and passed.</p>
<p>Spring framework provides a simple and useful solution to this by giving the developer an option to create the beans and register them inside the context. This can be done by using an interface named <em>ConfigurableApplicationContext</em>.</p>
<p>The class hierarchy is somewhat like :</p>
<blockquote>
<pre>	ApplicationContext
		-&gt; ConfigurableApplicationContext
			-&gt; Actually implemented classes like WebApplicationContext,
				ClassPathApplicationContext etc.
</pre>
</blockquote>
<p>The purpose of putting in ConfigurableApplicationContext in between the hierarchy is just that you can get the <em>BeanFactory</em> object from SpringContext and register your own created objects in there. Following method is used to get the object of BeanFactory currently in use :</p>
<blockquote><p>ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;</p></blockquote>
<p>We just need a <em>SingletonBeanRegistry</em> object to be able to register our custom created bean to the spring's context. The class hierarchy for the same goes like:</p>
<blockquote>
<pre>	SingletonBeanRegistry
		-&gt; ConfigurableListableBeanFactory</pre>
</blockquote>
<p>Thus, one can directly create a variable of type <em>SingletonBeanRegistry</em> by using this method. Now, in order to register your object to spring, just use the following code:</p>
<blockquote><p>beanRegistry.registerSingleton("uniqueBeanName", object);</p></blockquote>
<p><em><strong>Points to take care :</strong></em><br />
There are certain things that need to be kept in mind before doing this otherwise application wil not boot up or might cause problems while running :</p>
<ol>
<li>The instance should be fully initialized before registering it to the context, i.e. spring will not call any callback methods that are supposed to be executed for doing the initialization like adding aspects, wiring of beans inside etc. However, Spring will call start and stop callbacks as and when the state of applicationContext changes.</li>
<li>The instance will not receive any destructive callbacks either. Thus, one must code for that separately either in stop, or one can choose to register the <em>BeanDefinition</em> object to have such functionality. The way to create a bean definition object is just use the <em>BeanDefinitionBuilder</em> which is a creator class for the same.</li>
<li>Bean name as mentioned above should be unique or you will get an <em>IllegalArgumentException</em> while registering.</li>
</ol>
<p><em><strong>Sample application :</strong></em><br />
Please follow this <a href="https://github.com/xebia/SIChat">URL</a> to download and try out the sample application. Refer to the README.txt file for instructions.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/08/spring-altering-your-applicationcontext-at-runtime/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Java to Javascript &#8211; Part 1</title>
		<link>http://xebee.xebia.in/2010/12/05/java-to-javascript-part-1/</link>
		<comments>http://xebee.xebia.in/2010/12/05/java-to-javascript-part-1/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 15:41:10 +0000</pubDate>
		<dc:creator>Ravindra</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6451</guid>
		<description><![CDATA[A few years(before Web2.0) back a Java developer moving to Javascript would have missed a lot of things from his/her extreme programming bible (Unit tests, Mocks, OO (not really)). In this blog i try to cover my experience of moving to Javascript development and a few new frameworks that bring good practices to Javascript development. [...]]]></description>
			<content:encoded><![CDATA[<p>A few years(before Web2.0) back a Java developer moving to Javascript would have missed a lot of things from his/her extreme programming bible (Unit tests,  Mocks, OO (not really)). In this blog i try to cover my experience of moving to Javascript development and a few new frameworks that bring <a title="use of good or best could trigger a debate on Xebia Tech list" href="#">good </a>practices to Javascript development. Almost everything is based out of jQuery world as that is what i am using, other frameworks like Prototype/YUI must be great but i have not worked on them.</p>
<p>For using jQuery i would say</p>
<p style="text-align: center;">“You add $ to anything and it becomes possible.. literally”.</p>
<p style="text-align: center;"><span id="more-6451"></span></p>
<p><strong>Logging and Debugging</strong></p>
<p>First things first. Developer consoles in IE 8/ Chrome/ Firefox are great, you can log stuff to these consoles.Firebug console API is here so you could do a lot of things in firebug. We identified one performance related issue using by simply using the time function (Firebug Profiler’s output was too fine grained and did not point to exact code region). I do not use the debugger as our scripts are loaded dynamically so they do not help anyway. Sufficient logging always helps. If you really want to persist your logs, you could asynchronously post the logs to server.</p>
<pre class="brush: jscript; title: ; notranslate">

(function($){
  if(console) {
    $.log = function(obj) {
      console.log(obj);
    }
  }
})(jQuery);
</pre>
<p>You can look at the <a href="http://getfirebug.com/wiki/index.php/Console_API">Firebug console API</a> for other methods available on the console.</p>
<p>Super cool alert: You wrap alert(JSON.stringify(obj)) as $.alert and see the object as inside out when you want (you will need json2.js).</p>
<p>You can also have a look at http://plugins.jquery.com/project/jQueryLog (which has nice templating feature as well).</p>
<p><strong>Dependency Injection</strong></p>
<p>Being a dynamic language this has never been a problem for Javascript as you could add /remove properties at will to an object or all of it’s *types*.<br />
Following code shows a small IOC container implementation. The DI takes as config input and wires up the objects.  The _getClosure method on line #12 is a fix for strange problem i faced with the closures. It kind of showed me why anonymous inner classes would only access the final variables of the scope outside. I was using an inline function definition on line #12 and binding it to the dependency name, but it was always binding to the last value of the variable.</p>
<pre class="brush: jscript; title: ; notranslate">
com.framework.DIEngine = {
  _objCache: {},

  init: function(config) {
    for (obj in config) {
      var instance = config[obj].instance;
      if (config[obj].dependencies) {
        for (depIdx in config[obj].dependencies) {
          var dep = config[obj].dependencies[depIdx];
          $.log(dep);
          $.log('bound to:' + dep);
          instance[dep] = this._getClosure(dep); // bind a function to ask from DIEngine
        }
      }
      this._objCache[obj] = instance; // store the instance
    }
  },

  _getClosure: function(dep) {
    return function() {return com.framework.DIEngine.get(dep)};
  },

  get: function(name) {
    $.log('Asked DI for:' + name);
    return this._objCache[name];
  }
};
</pre>
<p><strong>Packaging</strong></p>
<p>You can mirror packages by creating objects inside a hierarchy. Your declarations automatically add new classes/objects to the namespace. By doing this you can rest assured that you are not conflicting with any other variables in some other library.</p>
<p>A sample namespace can be declared as below and then you define all your objects in the attached namespace.</p>
<pre class="brush: jscript; title: ; notranslate">
var com = {
  framework:{},
  app:{}
};

// define objects in namespace.
com.app.Mapper = {
// foo bar
}
</pre>
<p><strong>Object Orientation</strong></p>
<p>One of the major things that a java developer misses is the absense of class hierarchies, it is hard to model the data without significant code duplication. Following articles describe how to make use of javascript’s object oriented nature. A simple approach is to maintain a registry of objects and then create new objects by extending registered objects. We had objects which would have a single instance( singletons) so it was easy. John Resig’s link below explains in detail how to implement object orientation. Code looks much structured and readable compared to prototype based approach mentioned in sitepoint article.</p>
<ul>
<li><a href="http://articles.sitepoint.com/article/oriented-programming-1" target="_blank">http://articles.sitepoint.com/article/oriented-programming-1</a></li>
<li><a href="http://www.javascriptkit.com/javatutors/oopjs.shtml" target="_blank">http://www.javascriptkit.com/javatutors/oopjs.shtml</a></li>
<li><a href="http://ejohn.org/blog/simple-javascript-inheritance/" target="_blank">http://ejohn.org/blog/simple-javascript-inheritance/</a></li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
var OO = {
  _ooRegistry: {},

  register : function(subName, base, subDef) {
    if (!(typeof base == 'string') ) {
      subDef = base; // will this become global?
      base = {};
    } else {
      base = this._ooRegistry[base];
    }
    this._ooRegistry[subName] = $.extend({},base, subDef );
    this._ooRegistry[subName]._super = base;
  },
  get: function(cls) {
    return this._ooRegistry[cls];
  }
};

OO.register('baseClass', {
  hello: function() {
    $.log(&quot;Base class invoked.&quot;);
    return &quot;Namaskaar&quot;;
  }
});

OO.register('subClass','baseClass', {
  hello: function() {
    $.log(&quot;Sub class invoked.&quot;);
    $.log(&quot;Invoking super&quot;);
    this._super.hello();
    return &quot;Wazz up.&quot;;
  }
});
</pre>
<p><strong>Unit Testing</strong></p>
<p>Let's now put the code above to test.  jQuery offers <a title="QUnit" href="http://docs.jquery.com/Qunit">QUnit</a> as the unit testing framework. Following code puts the DI code and the OO code to test. QUnit provides nice setup and teardown lifecycle methods as JUnit.</p>
<pre class="brush: jscript; title: ; notranslate">
// OO test
$(document).ready(function() {

  module(&quot;OO tests.&quot;);

  test(&quot;OO get test&quot;, function() {
    var base = OO.get('baseClass').hello();
    var sub = OO.get('subClass').hello();
    ok(base == 'Namaskaar', 'Base class object invoked.');
    ok(sub == 'Wazz up.', 'Sub class object invoked.');
  });
});

// DI test
$(document).ready(function() {

  module(&quot;DI tests.&quot;, {
      setup: function() {
        com.framework.DIEngine.init({
            reducer: {instance:com.app.Reducer},
             mapper:{instance:com.app.Mapper},
             service:{instance:com.app.Service, dependencies: ['reducer', 'mapper']}
          });
      },
      teardown: function() {
        // tear down..
      }
    });

  test(&quot;DI get test&quot;, function() {
    expect(2); // 2 assertions in the test
    var mapper = com.framework.DIEngine.get('mapper');
    ok(mapper &amp;&amp; typeof mapper == 'object', 'Mapper is defined  &amp; is an object.');
    ok(mapper.name == 'mapper', 'It is indeed mapper.');
  });
});
</pre>
<p>QUnit can be integrated with the continuous integration systems which launch browsers and the collect test results from the DOM. QUnit documentation explains how this can be done. QUnit provides nice callbacks for various events in the test lifecycle. I find QUnit.done of particular interest as it can be used to inform you of test failures by posting back to a URL ( an app there could trigger a message to your team's instant messaging system).  Other callbacks can be used to collect the data on individual tests and then send it on 'done' callback.</p>
<p>In the next part of this blog i will try to cover</p>
<ul>
<li>Use of mocks in Javascript testing</li>
<li>Dependency management</li>
<li>Messaging ( events!!)</li>
<li>The *this* mystery</li>
<li>Deployment and code checks ( JSLint)</li>
</ul>
<p><strong>Even More</strong></p>
<p>You could have a peek at  <a title="Javascript MVC" href="http://javascriptmvc.com">JavascriptMVC</a> (It is in production release now). It is a Grails equivalent in the javascript world. It brings everything under one roof and has much more advanced capabilities that what is mentioned here. Then why did we not use it? Firstly JavascriptMVC 3.0 was under heavy development and was not even in Beta. We felt that what we were developing required us to be in control of our code.  JavascriptMVC offers solutions for a lot of problems that we donot have. It really is a great framework which is trying to pitch in the Enterprise Javascript  concept.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/12/05/java-to-javascript-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes from Software Testing Conference (STC 2010)</title>
		<link>http://xebee.xebia.in/2010/11/30/notes-from-software-testing-conference-stc-2010/</link>
		<comments>http://xebee.xebia.in/2010/11/30/notes-from-software-testing-conference-stc-2010/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 18:03:23 +0000</pubDate>
		<dc:creator>Rajneesh</dc:creator>
				<category><![CDATA[Quality]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Software testing]]></category>
		<category><![CDATA[STC2010]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6470</guid>
		<description><![CDATA[Recently I attended STC 2010, the 10th edition of the international Software testing conference organized by QAI in Bangalore on 22-23 Nov. This year the theme of the conference was Testing 3.0- From transaction to transformation. I was pretty excited to see the conference program as the speakers included a good mix of industry leaders, [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I attended <a href="http://www.qaiglobal.com/minisites/stc_2010/index.htm">STC 2010</a>, the 10th edition of the international Software testing conference organized by <a href="http://www.qaiglobal.com/QGS/Default.asp">QAI</a> in Bangalore on 22-23 Nov. This year the theme of the conference was Testing 3.0- From transaction to transformation. I was pretty excited to see the conference program as the speakers included a good mix of industry leaders, practitioners and testing experts slated to present on a wide array of interesting topics. This is a short experience report of the 2 day conference based on the sessions I managed to attend as well as relate to and my interaction with some of the speakers/participants.</p>
<h3><span style="color: #000080;">Day 1</span></h3>
<p>Although still weary from late arrival at Bangalore, me and my colleague managed to reach the venue in time. As soon as we got ourselves registered we quickly glanced through the schedule and marked sessions of interest.The program on day 1 initially was all keynotes followed by 3 parallel tracks.  The parallel tracks were split up based on categories such as Business leadership, Test program management and Techniques and Tools. Majority of the sessions I chose to attend were in the 'Tools and Techniques' category.<br />
<span id="more-6470"></span></p>
<p>The proceedings started with a session by <a href="https://www.microsoft.com/india/msindia/msindia_executive_amit.aspx">Amit Chatterjee</a> from Microsoft. His presentation started with a futuristic video displaying the power of surface computing and smart devices (cool MS technology). He posed the obvious question to the audience as to how we are going to test such complex software. His talk was titled ' What does it take for professional testers to succeed in an Agile team?' in which he talked about how agile has transformed the role of a tester from 'Critical' to 'Creative and Collaborative'. He also stressed on the fact that testers should focus on the flow of value and reduction of waste which is possible through greater collaboration. He reckoned that in order to succeed in agile environment we need ‘smart’ tools to reduce cycle time. Few tips he offered were lightweight planning, exploratory testing and minimizing set-up time by using techniques such virtualization. He also talked about test impact analysis which can allow execution of only impacted test cases while regression to make regression testing smarter and faster. Since the essence of what he spoke was mainly agile and related practices, I could relate to his presentation fairly easily as we at <a href="http://xebiaindia.com/in">Xebia</a> have been focusing on agile since very beginning. His talk suggested that agile practices are gaining a lot of traction within big companies like Microsoft which is a positive trend.</p>
<p>Next was a talk titled 'Modern Applications Demand-A sophisticated approach to Quality' by Andrew Bearsley from HP. He stressed the need for 'Automation' and 'Modernization' in order to meet the current quality challenges. Automation, he said, has to be applied at task, process and service delivery level. By 'Modernization' he meant to be fast, lean and innovative in order to achieve quality goals. He also introduced a new tool called 'HP Sprinter' which sort of tries to address the lack of tooling in agile testing space from the HP stable. Finally he talked of few techniques around which the tool is built like exploratory testing, mirror testing, data injection, screen annotation and smart defect logging to accelerate the test execution process.</p>
<p>The final keynote session was from <a href="http://www.infosys.com/about/management-profiles/Pages/manish-tandon.aspx">Manish Tandon</a> from Infosys. He stressed on business process based approach to testing. His paper 'Transformation in Testing and Testing in Transformation' highlighted the transformation in tester profile enabled by the current business dynamics and technology landscape. He rightly remarked that the testers lie at a unique intersection of domain and technology and possess lot of power which can enable positive change. Some of the key takeaways were that testers needs to transform and align with business, end to end approach to quality has to be adopted and building agility into test teams is the way forward.</p>
<p>Next were the parallel tracks from which I would like to mention a few I managed to attend and relate to. First one was 'Journey to next level of automation- A road less traveled' by Ashish Guru-Capgemini. Ashish spoke about a number of frameworks that has been developed in-house and how those led to increase in test coverage and savings in terms of time, effort and cost. These reusable frameworks have some really nice features as they are tool agnostic, configurable to work with and without UI and can be plugged into any other framework. I felt the 20 minutes of time allotted to each speaker was too less to gain much as they scrambled to complete their presentation in the stipulated time. After the session I had a short discussion with Ashish on creating a reusable framework using open-source tools like Selenium by applying some of the concepts he talked about in his paper. Since time was at premium we agreed to discuss this later at some other forum. </p>
<p>The other presentation which I really liked was 'DIY:Cloud based low cost, Elastic load generation using open source tools' where Nikhil from MindTree presented his experiences of creating a performance testing framework based on two of the most promising and upcoming trends in the Software industry: Open source tools and Cloud. I liked this since I too have been tinkering with this idea of creating a cloud based load testing capability using open source tools and it was good to hear someone sharing his practical experiences on the same. Nikhil and his team used <a href="http://staf.sourceforge.net/">STAF </a>and some other open source tools for their framework and deployed it on <a href="http://aws.amazon.com/ec2/">Amazon EC2</a> to generate load. They also wrote some custom utilities for performance monitoring, error logging and reporting. In my opinion we have just seen the tip of the iceberg and these new platforms and technologies will shape the 'testing to come'.</p>
<p>Another paper was from Arit from 'MindTree' with an interesting and catchy title 'An elegant approach to automated software testing using the dimension of AI'. I carried high expectations from the session but rather was left with some un-answered questions and a feeling of wanting more. Arit talked about creating an intelligent oracle for verifying automated tests using machine learning. It seemed to me a lot like creating an n-way combination of tests with some flavor of model based testing and Markov Models. Creating an intelligent oracle this way is very complex and as a tester you would fall in a trap spending a lot of effort verifying the oracle rather than the application itself. Although I must confess that it was a brave attempt by the speaker to try and experiment with something like this but I do feel there was lot of scope for further experimentation and backing-up the claims with some solid practical experiences. I wish Arit a very good luck in his research. </p>
<p>After a frantic schedule throughout the day, the evening provided the much needed respite and opportunity to unwind. The evening was very well planned with awards night punctuated with some entertaining performances by a local dance troupe and some really crazy antics by the organizers and the attendees. Everybody had a nice time with drinks, laughter and good food.</p>
<h3><span style="color: #000080;">Day 2</span></h3>
<p>Day 2 had keynote sessions till lunch followed by a couple of parallel tracks post lunch. Almost all the speakers presented papers related to trends in software quality and testing. Suresh Ramakrishnan from capegemini presented <a href="http://www.capgemini.com/insights-and-resources/by-publication/2010-11-world-quality-report/">World Quality Report</a> which contained some insightful revelations. Some of the important findings of the report were:<br />
•	Business is looking for a new tester profile with well rounded skills in business domain as well as technical expertise.<br />
•	Companies are willing to invest more into automation across the SDLC to improve quality<br />
•	QA outsourcing is on the rise but its bringing in some additional demands<br />
•	Performance and security testing are increasingly being recognized as important.<br />
•	Leveraging cloud and virtualization to reduce cost and effort is on the rise.<br />
•	Agile can significantly improve application quality, productivity and time to market but it is not a cure-all remedy.</p>
<p>Another paper titled 'Catalyze Testing through modern technology' presented by Sripriya Kalyanasundram from Cognizant again stressed most of points that came out of the report. She reiterated that non-functional testing is gaining lot of traction and SOA methods and agile delivery are some of the trends that are poised to gain greater momentum.</p>
<p>Amongst the parallel tracks there were a couple of talks I liked. The first one was by <a href="http://testertested.blogspot.com/">Pradeep Soundarajan</a> tilted 'The Next Generation Tester'. Pradeep made a passionate plea for 'brainual testing' rather than 'manual testing' in a very animated way. He emphasized the need of constant learning to master the craft of testing and also shared some innovative and useful ways in which testers can explore and test products even when they seem to be "blocked" by missing specifications or lack of direction while following a more traditional approach.<br />
Another talk was on 'Test Encapsulation' by <a href="http://www.testingperspective.com/">Rahul Verma</a> of McAfee. His presentation was one of the highlights of the conference. He spoke about generics around test frameworks or 'Meta-Frameworks' (which he described as a framework of frameworks). He emphasized the need to create 'intelligent tests' and the importance of careful abstraction and test encapsulation. Test encapsulation is a way to create a test such that it has all the information regarding its environment, set-up, execution, tear-down, reporting/logging and error handling available to it and the test has the ability to make decision at run time based on its invocation parameters to execute or skip execution or execute in a specific way.</p>
<p>Overall, the conference was very well organized and we got to meet and network with some really great testers and business leaders.<br />
QAI alongwith <a href="http://www.edistatesting.com/">Edista Testing</a> (Pradeep Chennavajuhula and his team) did a tremendous job to organize the event at this scale successfully and hence deserve a big round of applause. Having said this, I also felt  need for some obvious improvements (quality over quantity-granting more time for paper presentations, taking feedback for individual sessions, to have space for on-the-spot short talks and discussions, inviting more thought leaders and testing practitioners from across the globe).</p>
<p>This was my first year at STC and I would definitely like to come back next year (hopefully I can present a paper) and encourage everyone from the testing community to participate in the event.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/30/notes-from-software-testing-conference-stc-2010/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flex: In-Memory Image Cache</title>
		<link>http://xebee.xebia.in/2010/11/25/flex-in-memory-image-cache/</link>
		<comments>http://xebee.xebia.in/2010/11/25/flex-in-memory-image-cache/#comments</comments>
		<pubDate>Thu, 25 Nov 2010 02:34:26 +0000</pubDate>
		<dc:creator>sraheja</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Custom Component]]></category>
		<category><![CDATA[Image]]></category>
		<category><![CDATA[Memory Optimization]]></category>
		<category><![CDATA[Optimization]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6266</guid>
		<description><![CDATA[The Need: Flex, by default, maintains an in-memory cache for all the images embedded in the application at compile time. However, for the images loaded at runtime, there is no default cache implementation. So, over a period of time it may happen that we have redundant image data (BitmapData) in the memory. This would unnecessarily [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The Need:</strong></p>
<p><strong> </strong>Flex, by default, maintains an in-memory cache for all the images embedded in the application at compile time. However, for the images loaded at runtime, there is no default cache implementation. So, over a period of time it may happen that we have redundant image data (BitmapData) in the memory. This would unnecessarily increase application's total memory usage and data transfer over the network.</p>
<p>Let us analyze difference in total memory consumption when we use an image once or multiple number of times for both the scenarios:</p>
<p><span id="more-6266"></span></p>
<ul>
<li style="font-style: italic;">Embed at compile time:<br />
<span style="font-style: normal;">The application with single embed takes around 83.8 MB in my browser:<br />
</span><span style="font-style: normal;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Image source="@Embed(source='images/2MB.jpg')" width="400" height="400"/&gt;<br />
</span><br />
<span style="font-style: normal;">With multiple embeds (10) for the same image, it takes around 84.1 MB in total. The difference is almost negligible.<br />
</span></li>
</ul>
<ul>
<li style="font-style: italic;">Load at runtime:<br />
<span style="font-style: normal;">A single usage of an image without embedding it at compile time, i.e. by specifying a URL from where image will be loaded at runtime, takes around 85 MB of memory.<br />
</span><span style="font-style: normal;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Image source="images/2MB.jpg" width="400" height="400"/&gt;<br />
</span><span style="font-style: normal;"><br />
However, using it multiple number of times(10) takes around 138 MB in total. There is a significant difference of 53 MB in this scenario.</span></li>
</ul>
<p><strong>Problem:</strong></p>
<p>The redundant image data in memory can cost us a lot and make our application sluggish in nature.<br />
<strong> </strong></p>
<p><strong>Solution:<br />
</strong>A simple solution for this problem can be to embed all the images into our application at compile time. However:</p>
<ul>
<li>That will drastically increase overall SWF size of the application.</li>
<li>Also, nature of some of the applications may require loading images at run time.</li>
</ul>
<p><!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px} -->A better solution is to have an in-memory image data cache. This can optimize the total memory usage and will also reduce overhead of loading external resources again and again. However, even after the cache in place, we will have to write plumbing code everywhere for making a lookup into cache before loading an image and also add loaded image data into the cache.</p>
<p>So, here is an implementation of CachedImage component which extends from Image component. The only difference is, for a given source URL, it will first make a lookup into ImageDataCache. If it finds an appropriate BitmapData, it will re-use it else it will load data from the URL and add it to the cache. So, we can easily replace all instances of Image component in our application by CachedImage and save a lot in terms of total memory usage and data transfer over the network.</p>
<p>Here is the implementation for few important methods of CachedImage component. Declarative variable and function names along with code comments will help you understand the code better. Complete source code for both the components (CachedImage and ImageDataCache) is enclosed at the end.</p>
<pre class="brush: as3; title: ; notranslate">
/**
* Setter for source, it makes a lookup into the cache for existing image data.
**/
override public function set source(value:Object):void {

    if(value is String) {

        _imageId = value as String;

        var hasImageData:int = _imageDataCache.hasImageData(_imageId);

        if(hasImageData == ImageDataCache.IMAGE_DATA_PRESENT) {

            // the scenario when image data is already there in cache

            var bitmapData:BitmapData = _imageDataCache.getImageData(_imageId);

            super.source = new Bitmap(bitmapData);

        } else if(hasImageData == ImageDataCache.IMAGE_DATA_LOADING) {

            // the scenario when image data is currently not in cache, however, load

            // request for it has already been started by some other CachedImage instance

            _imageDataCache.addEventListener(ImageDataCacheEvent.IMAGE_DATA_ADDED,

                onImageDataAddedInCache, false, 0, true);

        } else {

            // the scenario when image data will be loaded into memory for this instance

            addEventListener(Event.COMPLETE, onImageLoadComplete, false, 0, true);

            _imageDataCache.markImageDataLoading(_imageId);

            super.source = value;

        }

    } else {

        // the scenario when image data is embedded into the application at compile time

        super.source = value;

    }

}

/**
* onImageDataLoadComplete is the handler for image load complete event.
*
* It puts loaded BitmapData into the cache if it is not there
**/

private function onImageDataLoadComplete(event:Event):void {

    if(_imageDataCache.hasImageData(_imageId) != ImageDataCache.IMAGE_DATA_PRESENT) {

        var bitmapData:BitmapData = (content as Bitmap).bitmapData;

        _imageDataCache.putImageData(_imageId, bitmapData);

    }

}
</pre>
<p>ImageDataCache implements following methods:</p>
<pre class="brush: as3; title: ; notranslate">

function getImageData(imageId:String):BitmapData;

function putImageData(imageId:String, imageData:BitmapData):void;

function markImageDataLoading(imageId:String);

function hasImageData(imageId:String);

function purgeImageData(imageId:String);

function clear();
</pre>
<p><strong>Conclusion:</strong></p>
<p>The difference in using CachedImage once and 10 times for the same URL is almost negligible (0.2 MB), however that is huge for Image (53 MB). You can download the complete source code <a href='http://xebee.xebia.in/wp-content/uploads/2010/11/ImageCacheProject.zip'>here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/25/flex-in-memory-image-cache/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Experiencing Spring Integration with Iwein Fuld</title>
		<link>http://xebee.xebia.in/2010/11/23/experiencing-spring-integration-with-iwein-fuld/</link>
		<comments>http://xebee.xebia.in/2010/11/23/experiencing-spring-integration-with-iwein-fuld/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 18:25:10 +0000</pubDate>
		<dc:creator>Iti Agarwal</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[GIT]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Software Craftsmanship]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6324</guid>
		<description><![CDATA[Place : Xebia India, gurgaon Day 1: 17 Nov, 2010 This morning, I was going to attend Spring Integration training by no other than the guru himself, Iwein Fuld. I was definitely excited. I entered the training location to find close to 15 people in the room, we were supposed to sit in groups of [...]]]></description>
			<content:encoded><![CDATA[<h4>Place : Xebia India, gurgaon</h4>
<h4>Day 1: 17 Nov, 2010</h4>
<p>This morning, I was going to attend Spring Integration training by no other than the guru himself, Iwein Fuld. I was definitely excited. I entered the training location to find close to 15 people in the room, we were supposed to sit in groups of 5. We made 3 groups and got seated.</p>
<p><span id="more-6324"></span></p>
<p><a rel="attachment wp-att-6420" href="http://xebee.xebia.in/2010/11/23/experiencing-spring-integration-with-iwein-fuld/samsung-2/"><img class="alignnone size-medium wp-image-6420" title="Training hall" src="http://xebee.xebia.in/wp-content/uploads/2010/11/2010-11-17-15.34.591-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>Iwein first took us over through the concepts of Spring Integration and how they could be used to implement a messaging system in multiple independent applications to integrate them together. It was an engaging power point presentation in which he beautifully used pictorial description for explaining the concepts. Check it out <a href="http://www.slideshare.net/iweinfuld/spring-integration-motivation-and-history-5020632">here</a>. And yes I now know how 'coffee' is related to 'Spring Integration'. The way these things were explained, everything simply sunk into my brain.</p>
<p>But if it had to be just the presentation, I would'nt have probably taken the pain to write down my experience on paper. After the basic concepts were explained to us, we were told to find out the answer to one question (and yes, we had access to the internet!  :-)  ) while Iwein grabbed a cup of coffee. Everyone quickly googled <strong>"What is Peer Instruction?"</strong> and got to know the methodology that was to be used in the rest of the session. Iwein has already put up a blog about this methodology used in the training <a href="http://iweinfuld.posterous.com/">here</a>.</p>
<p>The rest of the training was done through the medium of a case, we had a skeleton of an application ready and we were to build 3 functionalities around it.</p>
<ol>
<li>File Reading</li>
<li>Twitter Integration</li>
<li>Email Integration</li>
</ol>
<p>These were divided into small user stories and we followed scrum. We used Git for the version control so I got my hands on some 'Git' too! At the end of day one, we could finish few small user stories.</p>
<h4>Day 2: 18th Nov, 2010</h4>
<p>We assembeled in the hall and in the same groups as day 1 and continued on the user stories. We wrote unit tests for our code, made sure we have the right design in place, and also thought about performance. Iwein also made code review comments whereever he felt something was not perfect. This day we focussed on software craftsmanship along with learning Spring Integration.</p>
<p>I must mention the way Peer Instruction was used, it made the training much more engaging and fun. Also the fact that the training provided with hands-on through a realistic case and that the focus was more on getting the concepts right instead of running through the whole API is really commendable. If we could focus a little bit more on the theoritical concepts and prepared the best solutions before hand it would be what we call a 'Perfect Training'.</p>
<p>Over all for me, it was a great learning experience. I thoroughly enjoyed it.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/23/experiencing-spring-integration-with-iwein-fuld/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First look at Google BigQuery</title>
		<link>http://xebee.xebia.in/2010/11/18/first-look-at-google-bigquery/</link>
		<comments>http://xebee.xebia.in/2010/11/18/first-look-at-google-bigquery/#comments</comments>
		<pubDate>Thu, 18 Nov 2010 14:12:01 +0000</pubDate>
		<dc:creator>Rohit Garg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[bigquery]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6236</guid>
		<description><![CDATA[In this blog I would primarily be talking about the Google BigQuery API. This has been a major step in the computing world to provide database as a service on cloud computing environment. BigQuery API has been designed to analyse huge amounts of data in really less timeframe. Interface of the service is quite straightforward, [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog I would primarily be talking about the Google BigQuery API. This has been a major step in the computing world to provide database as a service on cloud computing environment. BigQuery API has been designed to analyse huge amounts of data in really less timeframe. Interface of the service is quite straightforward, and involves HTTP calls to get data from the tables.<br />
Since Google BigTable is a NoSQL oriented database, the format of BigQuery doesn't support JOINS but is able to support lots of other features like grouping, ordering, ranges, rejection and so on.</p>
<p><span id="more-6236"></span><br />
<em><strong>Overview:</strong></em></p>
<p>BigQuery API only provides a basic querying mechanism to the end users. There is no functionality that allows you to manipulate the data once uploaded into the BigTable structure. You can only append more data into the structure or fire <a href="http://code.google.com/apis/bigquery/docs/query-reference.html">SELECT</a> queries against the data. This makes BigQuery engine more of an analytics tool over trillions of rows of data.</p>
<p>BigTable is a part of Google's storage servers and can be run without the need of any additional hardware. Moreover, the API has been exposed via simple HTTP and JSON, which are easy to put in any application. One can leverage these benefits to cut down on the hardware costs of setting up high performance systems for analysis.</p>
<p>The whole process of carrying out analysis on some dataset involves two basic steps:</p>
<ol>
<li>Importing data into the BigTable structure (Through <a href="http://code.google.com/apis/storage/">Google Storage</a> and import job)</li>
<li>Running the queries against that data</li>
</ol>
<p><em><strong>Importing the data:</strong></em></p>
<p>In order to analyse your data, you should do following steps to port your data into the Google BigTable system:</p>
<ol>
<li>Ensure that you have Google Storage and BigQuery enabled account with Google.</li>
<li> Upload the data in CSV format to Google storage using their <a href="https://sandbox.google.com/storage/m/">storage manager</a> HTTP interface. Header information is not required. Only the columns of CSV must match the structure of the table as specified in subsequent steps.</li>
<li>Use <a href="http://curl.haxx.se/download.html">cURL</a> tool to get the authorization key which can be used in subsequent calls to the HTTP service exposed. Command to be executed is :<br />
<blockquote><p><em>curl -X POST -d accountType=GOOGLE -d Email=&lt;email&gt;@gmail.com -d Passwd=&lt;password&gt; -d service=ndev -d source=google-bigquery-manualimport-1 -H "Content-Type: application/x-www-form-urlencoded" https://www.google.com/accounts/ClientLogin</em></p></blockquote>
<p>This call will return an authorization key whose format is similar to :</p>
<blockquote><p>DQAAAK8AAADlegSF4xMNrCgUrxFv3NFCYbBp4KCpdhOCOioIfJ7txXrRB9FYcvDAv7ooGvmaWoDCj_<br />
SPHolxr9Q6gK8-cd4SR_QkIv3QcM_pQlVADtMWtv63hqzdz16KMZ1tDizeyOIe-vJNenAYqrjX4xVSTH2F<br />
_5Fy9fc1mXxL77BtKXFMlV0xqbX9swpqXXhk_Zqvw8K0fbBE2o6kkU3FW7NDN8IXLrhqC_VEEaKXGAD3-1JIyg</p></blockquote>
<p>Just keep a note of the key as it will be used further. Down the line, I will refer to it as <em>AUTH_KEY</em></li>
<li>Create the table using following command.<br />
<blockquote><p><em>curl -H "Authorization: GoogleLogin auth=AUTH_KEY" -X POST -H "Content-type: application/json" -d '{"data":   {"fields": [    {"type": "string", "id": "name", "mode": "REQUIRED"},    {"type": "integer", "id": "age", "mode": "REQUIRED"},    {"type":"float", "id": "weight", "mode": "REQUIRED"},    {"type": "boolean", "id": "is_magic", "mode": "REQUIRED"}    ],   "name": "&lt;bucket_name&gt;/testtable"  }}' 'https://www.googleapis.com/bigquery/v1/tables'</em></p></blockquote>
<p><strong>bucket_name</strong> is the name of bucket where you want the reference of your table to be created. Buckets are nothing but folders inside Google storage.</li>
<li>After you have successfully added the table, import process needs to be triggered to port the uploaded CSV data into the BigTable structure. Following command will do the same :<br />
<blockquote><p><em>curl -H "Authorization: GoogleLogin auth=AUTH_KEY" -X POST -H "Content-type: application/json" -d '{"data": {"sources": [{"uri": "&lt;bucket_name&gt;/&lt;data_file_name&gt;.csv"}]}}' 'www.googleapis.com/bigquery/v1/tables/&lt;bucket_name&gt;%2Ftesttable/imports'</em></p></blockquote>
<ul>
<li>Please note that <strong>testtable</strong> is the table name that you have created in step 4.</li>
<li>Response to this kind of a request is a JSON string which is of a format : {"data":"kind":"bigquery#import_id","table":"&lt;bucket_name&gt;/testtable","import":"&lt;import_id&gt;"}}</li>
<li><strong>import_id</strong> is useful in getting the current state of the import process. It also returns errors in case it has encountered any. Any errors will just fail the import process and rollback everything.</li>
</ul>
</li>
<li> To know the status of your import process, just fire the following command:<br />
<blockquote><p><em>curl -X GET https://www.googleapis.com/bigquery/v1/tables/&lt;bucket_name&gt;%2Ftesttable/imports/&lt;import_id&gt; -H "Authorization: GoogleLogin auth=AUTH_KEY"</em></p></blockquote>
</li>
</ol>
<p><em><strong>Querying the data:</strong></em></p>
<p>After the data is successfully ported, you can query the database using BigQuery. Just download the bqshell tool from <a href="http://code.google.com/p/bigquery/">here</a> and build the code with all the required dependencies. The tool works on <a href="http://www.python.org/">python</a> and has a detailed "how-to" to install it.</p>
<p>This tool has a login console in which you can specify the username and password and query the sample datasets or your own datasets that you create using cURL. This tool is a parser to the JSON responses returned from the BigQuery API and displays them in a SQL output fashion. Alternatively, you can also use <a href="http://code.google.com/apis/bigquery/docs/libraries.html#curl">cURL calls</a> to query the database and see the JSON response yourself.</p>
<p><em><strong>Conclusion :</strong></em></p>
<ul>
<li>BigQuery API shows good performance in scenarios where you have huge amounts of data that needs to be processed. Running any query on almost 28 million rows uploaded in a test data set gives back response in just 2-3 seconds. The time includes request post and response recieved times as well.</li>
</ul>
<ul>
<li>There are sample data sets provided by Google themselves, one of which contains 60 billion records and queries get executed in 4-8 seconds. For more reference, please visit the following link : http://code.google.com/apis/bigquery/docs/dataset-mlab.html</li>
</ul>
<ul>
<li>One of the drawbacks is that there is no way to insert data without the upload and import job process. One can also not delete any record from the table once inserted. In order to change the data, you will have to delete the table and do the complete import process again. One thing worth mentioning is that in case you only need to add data to an existing table, you can do so by firing another upload job for the CSV file containing additional data.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/18/first-look-at-google-bigquery/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Life in a Corporate -5, Importance of Professional Character</title>
		<link>http://xebee.xebia.in/2010/11/09/life-in-a-corporate-5-importance-of-professional-character/</link>
		<comments>http://xebee.xebia.in/2010/11/09/life-in-a-corporate-5-importance-of-professional-character/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 08:34:47 +0000</pubDate>
		<dc:creator>Vinay Aggarwal</dc:creator>
				<category><![CDATA[Human Behaviour]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6155</guid>
		<description><![CDATA[In my opinion, the following characteristics of professional behavior (positive traits) are very important in corporate life. Positive Traits: Honesty and truthfulness, polite and courteous, down to earth, ownership and accountability, self-organized and self-dependent I give a lot of emphasis to the above mentioned traits. I believe the above mentioned traits define your professional character. [...]]]></description>
			<content:encoded><![CDATA[<p>In my opinion, the following characteristics of professional behavior (positive traits) are very important in corporate life.</p>
<p><span style="text-decoration: underline;">Positive Traits</span>: Honesty and truthfulness, polite and courteous, down to earth, ownership and accountability, self-organized and self-dependent</p>
<p>I give a lot of emphasis to the above mentioned traits. I believe the above mentioned traits define your professional character. And if you have the highest quality of professional character, sky is the limit and you can do any work with ease. One of the fundamental differences between these behavioral characteristics and technical skills is that – these traits are inherent and cannot be taught to large extent. One can try to inspire a person to follow the path of honesty but only to a certain extent. If the person’s natural wiring of mind is such that it knows only vicious intentions then even best of the teacher’s can’t do much.  On the other hand, technical competency is a science which can always be learnt provided one has the aptitude to know and work with technology. Technical knowledge of respective job function (be it programming skill or any other skill like HR, sales, project management) can always be developed easily if someone has right attitude and ability to learn.  IMO, working in IT industry is not a rocket science. But still people fail, people get terminated, people develop poor quality software and develop poor relations - all of this because they miss one or more of the above mentioned positive traits.  People become so much focused on impressing the boss that they stop learning, stop developing skills, take short-cuts using below mentioned negative traits. <span id="more-6155"></span></p>
<p><span style="text-decoration: underline;">Negative Traits</span>:  Dishonesty, Lie, Back-biting, Politics, Passing the buck, Arrogance, Hypocrisy, Treating people with disrespect etc.</p>
<p>This also reminds me the message of the bollywood movie '3 Idiots' that says develop capabilities to such an extent that you don't have to chase success but success will follow you. And this cannot happen without having the highest professional character. But the problem with the modern age people and some aged project managers is that they want to achieve everything (money, power, status etc.) quickly. In the pursuit of this, they follow short-cuts that obviously mean diluting professional character. Instead of developing competency and skill, people hide incompetency by telling a lie, deception, back-biting, politics etc. These things are cleverly used as a tool for shortcut to success. These may give good returns in short-term but lost in the lust of short term success (money, power, status), people never realize when they have lost their character. They start treating work as commodity which they want to sell and showcase. They sell this commodity to impress the boss, to get best (not good but the best) rating in appraisal and maximum salary hike and to get more authority in company affairs. Actually there is no need to focus on any of these things but rather keep demonstrating your competency by doing work with honesty and above mentioned good professional traits. Your work and character will automatically speak for itself and you will get everything.</p>
<p>In my humble opinion, people should stay away from these negative traits. There is no substitute of honesty, it is still the best policy and would always remain.</p>
<p>I believe that path of honesty and truthfulness is not easy.  Indian audience would know that the Lord Rama in Ramayana had to go to exile and similarly Pandavas in Mahabharta faced many ordeals on their path of honesty and dharma.  But eventually in the long run they were the winners and history remembers them. But there are people who will always pull you back. There is always fight between clean intentions and malicious intentions. People may take these positive traits as your weakness, may take advantage of your honesty but joy of these people is always short-lived.  Even those great characters like Rama and Pandavas faced politics.</p>
<p>Another important aspect of negative professional character is hypocrisy. I have seen people saying very nice and all goodie things in front of their boss to impress him and earn his good will, but when they go back to their desk – they show very different colors.  These people also cleverly prove their innocence and helplessness in front of their boss (and also peers) to gain his sympathy and pampering. Again, in their real time actions – these people demonstrate their political intentions and hidden agenda. This kind of behavior is a pure deception or in other words of duplicity of character which is never good.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/09/life-in-a-corporate-5-importance-of-professional-character/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exploiting JSR 269 : How to Verify Annotations while Compiling</title>
		<link>http://xebee.xebia.in/2010/11/09/exploiting-jsr-269-how-to-verify-annotations-while-compiling/</link>
		<comments>http://xebee.xebia.in/2010/11/09/exploiting-jsr-269-how-to-verify-annotations-while-compiling/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 06:35:11 +0000</pubDate>
		<dc:creator>Rahul Sharma</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6112</guid>
		<description><![CDATA[The Issue Now-a-days every library that you use is Annotations based. Annotations offer a better readable approach over the traditional XML approach. But there is a problem while using annotations, you can not force a class to have some annotations in place. You can say it with XMLs by creating some abstractions but you can [...]]]></description>
			<content:encoded><![CDATA[<h3>The Issue</h3>
<p><strong> </strong>Now-a-days every library that you use is <a href="http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html">Annotations</a> based. Annotations offer a better readable approach  over the  traditional XML approach.<em><strong> But there is a problem while using  annotations, you can not force a class to have some annotations in  place.</strong></em> You can say it with XMLs by creating some abstractions but you  can not force the same with annotations, it is up to the developer to  use the required annotations. This problem orignates from the way  annotations are implemented in JDK.</p>
<p>Annotations  are basically class/method specific. With Annotations you can at best  say that if some class implements some base-class then it can have some  annotation that was used in base-class( using the <em>@<a href="http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html">inherited</a></em><a href="http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html"> </a>meta-annotation)<img title="More..." src="http://rash0208.wordpress.com/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /><span id="more-6112"></span></p>
<pre class="brush: java; title: ; notranslate">
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyMarkerAnnotation {}

@MyMarkerAnnotation
public class PlayWithAnnotation {}

class Playground extends PlayWithAnnotation{
// This class will contain MyMarkerAnnotation
}
</pre>
<p>But  you can not say sub classes of some-other-baseclass must have  some-other-Annotation and the compiler must enforce it. There can be  varried reasons why I require this, the  following are few of them :</p>
<ul>
<li>I can not use the some-other-Annotation in base-class as each  sub-class must provide its own set of parameters for the  some-other-Annotation.</li>
<li> OR  maybe the Annotation is a third-party annotation and thus I can not modify it to have @<a href="http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html">inherited </a>meta-annotation.</li>
</ul>
<p>Keeping  the same goal in mind i.e. some how enforce sub-class to must have an  annotation, mandated by its super-class, my intention was to some how   enable the JDK compiler to break the compilation process and report the  required errors.</p>
<pre class="brush: java; title: ; notranslate">
@Retention(RetentionPolicy.RUNTIME)
public @interface SecondMarkerAnnotation {}

public class SomeBaseClass {
}

public class SomeOtherSubClass extends SomeBaseClass {
}
</pre>
<pre class="brush: plain; title: ; notranslate">
Configuration : in.annotations.playground.SomebaseClass = in.annotations.SecondMarkerAnnotation

Compiler Output :
error: in.annotations.playground.SomeOtherSubClass did not contain in.annotations.SecondMarkerAnnotation annotation
</pre>
<h3>First Try : Maven Plugin</h3>
<p>In order to accomplish this I have to perform the following steps:</p>
<ul>
<li>somehow scan the whole project,</li>
<li>find the sub-classes of the provided super-class,</li>
<li>check if the sub-class contains the same annotations and then</li>
<li>some how throw errors if it does not meet the requirements.</li>
<li>all of this should work while making a build</li>
</ul>
<p>At  first I thought a maven-plugin should be an apt choice for such a task  and started building the same. With this approach finding the  annotations and running with the build were the only easier parts and  rest of the steps were pretty hard ones. After a while I found out that  the approach of a maven-plugin is not an appropriate choice for such a  task esp if you want to plug into the JDK compiler.</p>
<h3>Second Try: Using Annotation Processing API(JSR 269)</h3>
<p>With  the advent of JSR 269 i.e. the Annotation Processing API/tool in the JDK  compiler you can already pretty much get into the JDK compilation  process. But this is something that you can do with <strong>JDK 6 ONLY</strong>. So I started using the <a href="http://download.oracle.com/javase/6/docs/api/javax/annotation/processing/AbstractProcessor.html">AbstractProcesser </a>API  provided and created my custom processor that can do the same. For each  of the steps that was required there is support from the API itself :</p>
<table border="1" cellspacing="0" cellpadding="4" width="100%">
<tbody>
<tr valign="TOP">
<td width="50%" align="center">Steps Required</td>
<td width="50%" align="center">Support Offered</td>
</tr>
<tr valign="TOP">
<td width="50%">Scan the whole project</td>
<td width="50%">The JDK itself scans the whole project and  with the use of  @<a href="http://download.oracle.com/javase/6/docs/api/javax/annotation/processing/SupportedAnnotationTypes.html">SupportedAnnotationTypes</a>("*") the Annotation Processor API can give you every class in the project that is complied.</td>
</tr>
<tr valign="TOP">
<td width="50%">Find the required sub-classes</td>
<td width="50%">Seems like a simple Reflection stuff but the API does  not offer simple class objects with which you can work instead you have  implement the <a href="http://download.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html">ElementVisitor </a>Api for the same.</td>
</tr>
<tr valign="TOP">
<td width="50%">Check if the class contains the same annotations</td>
<td width="50%">Once you are in the <a href="http://download.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html">ElementVisitor </a>API this is  simple Reflection stuff. You can check the annotations of the class.</td>
</tr>
<tr valign="TOP">
<td width="50%">Throw errors if it does not meet the requirements</td>
<td width="50%">Here again the  Annotation Processor API offers the <a href="http://download.oracle.com/javase/6/docs/api/javax/annotation/processing/Messager.html">Messager </a>API that can  be used to report errors or other info. The errors when reported will break the build process.</td>
</tr>
<tr valign="TOP">
<td width="50%">Process while making a build</td>
<td width="50%">With Apt tool you can run the required the Annotation  Processors manually with the java compiler. But if you  package the Jar  file correctly i.e. having a javax.annotation.processing.Processor file  in META-INF/services folder then the compiler would automatically invoke  it every time.</td>
</tr>
</tbody>
</table>
<p>The  only thing that is required is that you need to pass some configuration  to the implemented AnnoationProcesser. Here also the API provides full  support, you can pass arguments required for Annotation processing using  the -A options with the compiler e.g.    javac  -AannotationOption1=value1 -Aannotationoption2=value2.  Also you will be  required to put  @<a href="http://download.oracle.com/javase/6/docs/api/javax/annotation/processing/SupportedOptions.html">SupportedOptions</a>(value  = { "annoationOption1","annotationOption2"})  on your Processor else  you may get  a message that the options are not required by any  processors.</p>
<p>Using  the above mentioned APIs I created   AnnotationVerifier and made a jar  file that can be added to the classpath. You have to pass a mapping to  the AnnotationVerifier that can specify which class file will map to  which annotations. The compiler would call the verifier, that would  assert if the sub-classes contain the required annotations.</p>
<pre class="brush: java; title: ; notranslate">
@SupportedAnnotationTypes(&quot;*&quot;)
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedOptions(value = { &quot;AnnotationVerifier.Annotations&quot;, &quot;AnnotationVerifier.Baseclasses&quot;,
        &quot;AnnotationVerifier.ClassAnnotation.Mappings&quot; })
public class AnnotationVerifier extends AbstractProcessor {
    MessagerWrapper customMessager = new MessagerWrapper();

    @Override
    public boolean process(Set&lt;? extends TypeElement&gt; annotations,
            RoundEnvironment roundEnv) {
        if (!roundEnv.processingOver()) {
            ConfigurationLoader configurationLoader = new AptOptionsConfigurationLoader(
                    customMessager, processingEnv.getOptions());
            List&lt;AnnotationBaseclassMapper&gt; processOptions = configurationLoader
                    .loadConfiguration();
            if (processOptions == null) {
                return false;
            }
            Set&lt;? extends Element&gt; elements = roundEnv.getRootElements();
            for (Element element : elements) {
                if (element.getKind() == ElementKind.CLASS) {
                    ClassVisitor v = new ClassVisitor(customMessager);
                    element.accept(v, processOptions);
                }
            }
        }
        return false;
    }

    class MessagerWrapper {
        void printNote(String msg) {
            print(Kind.NOTE, msg);
        }

        void printError(String msg) {
            print(Kind.ERROR, msg);
        }

        private void print(Kind kind, String msg) {
            processingEnv.getMessager().printMessage(kind, msg);
        }
    }
}
</pre>
<pre class="brush: java; title: ; notranslate">
class ClassVisitor implements
        ElementVisitor&lt;Object, List&lt;AnnotationBaseclassMapper&gt;&gt; {
    private MessagerWrapper messager;

    public ClassVisitor(MessagerWrapper messager) {
        this.messager = messager;
    }

    @Override
    public Object visitType(TypeElement e,
            List&lt;AnnotationBaseclassMapper&gt; mapping) {
        List&lt;? extends TypeMirror&gt; extendingInterfaces = e.getInterfaces();
        Set&lt;Class&gt; annotationSet = new HashSet&lt;Class&gt;();
        for (TypeMirror interfaceType : extendingInterfaces) {
            annotationSet.addAll(getAnnotationMappingForType(interfaceType
                    .toString(), mapping));
        }
        annotationSet.addAll(getAnnotationMappingForType(e.getSuperclass()
                .toString(), mapping));
        checkForAnnotations(e, annotationSet);
        return null;
    }

    private void checkForAnnotations(TypeElement e,
            Collection&lt;Class&gt; annotationSet) {
        List&lt;? extends AnnotationMirror&gt; containedAnnotations = e
                .getAnnotationMirrors();
        MessageFormat errorString = new MessageFormat(
                &quot;{0} did not contain {1} annotation&quot;);
        String className = e.toString();
        for (Class verifyAnnotation : annotationSet) {
            boolean foundAnnotation = false;
            for (AnnotationMirror availableAnnotation : containedAnnotations) {
                String typeOfAnnoataion = availableAnnotation
                        .getAnnotationType().toString();
                if (typeOfAnnoataion.equalsIgnoreCase(verifyAnnotation
                        .getName())) {
                    foundAnnotation = true;
                    break;
                }
            }
            if (!foundAnnotation) {
                messager.printError(errorString.format(new Object[] {
                        className, verifyAnnotation }));
            }
        }
    }

    private Collection&lt;Class&gt; getAnnotationMappingForType(String className,
            final List&lt;AnnotationBaseclassMapper&gt; mapping) {
        Set&lt;Class&gt; annotationNames = new HashSet&lt;Class&gt;();
        for (AnnotationBaseclassMapper annotationBaseclassMapper : mapping) {
            if (className.equalsIgnoreCase(annotationBaseclassMapper.baseClass
                    .getName())) {
                annotationNames.add(annotationBaseclassMapper.annotation);
            }
        }
        return annotationNames;
    }

   // Other methods

}
</pre>
<p>As I did not get class object for matching and worked with <a href="http://download.oracle.com/javase/6/docs/api/javax/lang/model/element/Element.html">Element</a>,  so I was not able to get super-class/interfaces beyond the direct  super-class/interface and thus could assert for immediate sub-classes  only.</p>
<h3>Conclusion</h3>
<p>By using the Annotation Processing API available in JDK 6 I have pluged into the java compilation process to check is a perticular annotation is present on a set of classes or not. You can also perform some other checks  by following the similar approach, it  is not something annotation specific.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/09/exploiting-jsr-269-how-to-verify-annotations-while-compiling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Agile Testing &#8211; Incremental Functional Test Approach</title>
		<link>http://xebee.xebia.in/2010/11/03/agile-testing-incremental-functional-test-approach/</link>
		<comments>http://xebee.xebia.in/2010/11/03/agile-testing-incremental-functional-test-approach/#comments</comments>
		<pubDate>Wed, 03 Nov 2010 14:12:30 +0000</pubDate>
		<dc:creator>ShriKant Vashishtha</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Testing]]></category>
		<category><![CDATA[agile testing]]></category>
		<category><![CDATA[distributed agile]]></category>
		<category><![CDATA[xebia india]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=6102</guid>
		<description><![CDATA[Software development is all about incremental functional development. However we find a great impedance mismatch between development and testing synchronization. Though we talk about continuous integration and verification, most of the user stories come for verification only at the end of sprint which pose a major challenge in front of the testers just because of [...]]]></description>
			<content:encoded><![CDATA[<p>Software development is all about incremental functional development.</p>
<p>However we find a great impedance mismatch between development and testing synchronization. Though we talk about continuous integration and verification, most of the user stories come for verification only at the end of sprint which pose a major challenge in front of the testers just because of mismatch between the time available and amount of work to test.</p>
<p>To this point, developers may argue that they cannot give unfinished feature to the testers as they broke their work (user-story) according to technical subtasks. So for a developer Controller class has been written but Service still needs to be written. So tester may not be able test the technical tasks. Tester is more interested towards functional part completion instead of unit tests. This results in a impedance mismatch between developers and testers.</p>
<p><span id="more-6102"></span></p>
<pre><a rel="attachment wp-att-9704" href="http://xebee.xebia.in/2010/11/03/agile-testing-incremental-functional-test-approach/tester-at-the-end/"><img class="alignncenter size-medium wp-image-9704 aligncenter" title="tester-at-the-end" src="http://xebee.xebia.in/wp-content/uploads/2010/11/tester-at-the-end-300x225.png" alt="" width="500" height="375" /></a></pre>
<p>In our project, as a team we agreed in retrospectives that we will push the functional features as soon as they are finished but eventually it doesn't happen. We come back to the square one and the same problem is raised again in next retrospective.</p>
<p>So what do you do in this kind of situation?</p>
<p>Recently <a title="Vikrant" href="http://in.linkedin.com/pub/vikrant-manchanda/1b/369/8bb" target="_blank">Vikrant</a> our lead tester came out with a very good idea.</p>
<p>The argument was - why don't we break user-stories into functional subtasks also apart from breaking them into technical tasks. That way it's not either-or case but we'll have both functional and technical tasks. Developers then are also forced to think in terms of functional subtasks and are able to provide functionality in small chunks to testers.</p>
<p>Let's see how it works in real action.</p>
<p>As soon as, a developer finishes a functional subtask, he moves it to "Ready for Test" status in JIRA which indicates it's available for tester to test. This way testers are able to to test the user stories in incremental fashion. When team breaks the user stories into functional subtasks, both developer and tester sit together, collaborate and agree upon the functional division of the story.</p>
<p>This experiment worked pretty well for our team. Though we still see some areas of improvement, it enabled us to fix to the problem we had in our so many projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/03/agile-testing-incremental-functional-test-approach/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>HTML5 &#8211; Multithreading in JavaScript with Web Workers</title>
		<link>http://xebee.xebia.in/2010/11/02/multithreading-in-javascript-with-web-workers/</link>
		<comments>http://xebee.xebia.in/2010/11/02/multithreading-in-javascript-with-web-workers/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 06:32:42 +0000</pubDate>
		<dc:creator>Robin Nagpal</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Web Workers]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5529</guid>
		<description><![CDATA[Web Workers defines an API that can be used for running scripts in background threads. In traditional browsers javascript was capable of running in a single thread, due to which it was difficult to run background tasks. Also the capabilities and performance of client side applications were limited. However, there are some asynchronous functions like [...]]]></description>
			<content:encoded><![CDATA[<p><em>Web Workers</em> defines an API that can be used for running scripts in background threads. In traditional browsers javascript was capable of running in a single thread, due to which it was difficult to run background tasks. Also the capabilities and performance of client side applications were limited. However, there are some asynchronous functions like "setTimeout" and "setInterval" which provide nice work around for running background tasks.<br />
<span id="more-5529"></span><br />
I have divided this blog into two parts. First one explains the single threaded model of traditional browsers and the second one explains how to use <em>Web Workers</em>. You can skip the first section, if you have good hold on javascript.</p>
<p><strong>Single Threaded Model</strong><br />
The way javascript handles various asynchronous ajax calls or various timer functions, it makes us feel that javascript runs in multiple threads. Now, how does browser handle the UI events when it is executing a particular block of code, or how does browser handle the asynchronous timer and ajax calls when it just has a single thread for execution. The answer to all these questions lies in the way browser queues up various functions for execution.</p>
<p>Let us take an example of the following script</p>
<pre class="brush: jscript; title: ; notranslate">
function init(){
	takes 5 ms to be executed
	mouseClickEvent occurs
	takes 5 ms
	setInterval(timerTask,&quot;10&quot;);
	takes 5 ms
}

function handleMouseClick(){
      takes 8 ms to be executed
}

function timerTask(){
      takes 2 ms to be executed
}
</pre>
<p>Figure below shows the execution of the above script. Please pay extra attention to this figure as it contains a lot of information<br />
<a href="http://xebee.xebia.in/wp-content/uploads/2010/10/web-workers1.png"><img class="alignleft size-full wp-image-5909" title="web workers" src="http://xebee.xebia.in/wp-content/uploads/2010/10/web-workers1.png" alt="" width="536" height="370" /></a></p>
<p><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br />
Let us say that at 0 ms <em>init()</em> function starts executing and during the execution of <em>init()</em> function, a mouse click event occurs at 5ms. Now, as the main thread is already executing the <em>init()</em> function and is capable of executing just a single block of code at a time, it queues up <em>handleMouseClick()</em> function next in the execution queue. At  10 ms <em>init()</em> function sets a timer which will execute every 10 ms. First execution of the timer task is scheduled at 20 ms, second at 30 ms and so on. The execution of <em>init()</em> function takes 15 ms and after its completion, <em>handleMouseClick()</em> being next in the queue starts executing i.e. starts executing at 15ms.  Execution of <em>handleMouseClick()</em> function takes 8 ms i.e. it completes at 23 ms and as <em>timerTask()</em> function was scheduled to run at 20ms, <em>timerTask()</em> function gets queued up in execution queue and is executed after the <em>handleMouseClick()</em> completes. Since there is no other function present in the execution queue that need to be run, <em>timerTask()</em> function runs at its scheduled time i.e. 30 ms , 40 ms and so on.</p>
<p><strong>Web Workers</strong><br />
<em>Web Workers</em> allows you to load your script dynamically and run it in background thread. Creating a worker is simple. All you have to do is,  call the constructor and pass the URI of the script you want to execute as an argument.  Workers are relatively heavy weight and are not intended to be used in large number.</p>
<pre class="brush: jscript; title: ; notranslate">
// Creates a Web Worker
 var worker = new Worker(&quot;worker.js&quot;);
</pre>
<p>Workers don't have access to the DOM i.e. you don't have direct access to the 'parent' page. However, Web Workers API do provide you with methods like "onmessage" and "postmessage"  which let you communicate with the main thread.</p>
<ol>
<li> <strong>onmessage</strong> :  method used for receiving messages sent from the worker, also can be used in worker for  receiving messages sent from main thread.</li>
<li><strong>postmessage</strong> : method used for sending messages from worker to the main thread, also can be used in main thread for sending messages to worker.</li>
</ol>
<p>Lets take an example and see how exactly these methods can be used for communicating through messages</p>
<p>Here is the main script that created a new worker. In worker's <em>onmessage</em> event handler, we log all the messages received from the worker, i.e. this event handler is called when <em>postmessage()</em> function is called from the worker. This script also sets a timer, which calls the <em>sendMsgToWorker()</em> function every 5 sec.</p>
<pre class="brush: jscript; title: ; notranslate">

var worker = new Worker('worker.js');
worker.onmessage = function(e){
	console.log(e.data);
}
function sendMsgToWorker(){
	worker.postMessage(&quot;Sent  Message  From main &quot;);
}
setInterval(sendMsgToWorker,&quot;5000&quot;);

&amp;lt;/script&amp;gt;
</pre>
<p>Lets have a look at  "worker.js" script.</p>
<pre class="brush: jscript; title: ; notranslate">
onmessage = function(event) {
     var message = &quot;In worker on message method  :&quot; + event.data;
     postMessage(message);
};
function sendMsgToMain(){
     postMessage(&quot;Sent  Message From worker&quot;);
}
// Call sendMsgToMain method again after 5seconds
setInterval(sendMsgToMain,&quot;5000&quot;);
</pre>
<p>When we load the page containing the main script, the logs shown on the browser console are as follows</p>
<pre class="brush: plain; title: ; notranslate">

In worker on message method : Sent Message From main
Sent Message From worker
In worker on message method : Sent Message From main
Sent Message From worker
In worker on message method : Sent Message From main
Sent Message From worker
............
</pre>
<p>In this example, the main thread starts a new thread and instantiates a timer which calls <em>sendMsgToWorker()</em> function every 5 seconds. <em>sendMsgToWorker()</em> function sends a message i.e. <em>"Sent Message From main"</em> to worker by calling <em>postmessage</em> function on worker object. The worker receives this message in the <em>onmessage</em> callback function(in "worker.js" script) which prefixes the message with <em>"In worker on message method :"</em> and sends it back to the main thread using <em>postMessage()</em> function of worker API. Also, worker thread instantiates a timer which calls <em>sendMsgToMain()</em> function every 5 seconds. <em>sendMsgToMain()</em> sends a message i.e. <em>"Sent Message From worker"</em> to the main thread using <em>postmessage()</em> function. Messages sent by calling <em>postmessage</em> in 'worker.js' are received by <em>worker.onmessage</em> callback function(in main script) and are then logged to the console.</p>
<p>So, now there are two threads that run forever. First one is the main thread that receives messages sent from worker and logs them to the console and also sends a message every 5 seconds to the worker. Second thread, is the worker thread which sends the received messages from the main thread, back to the main thread and also sends a message every 5 seconds.</p>
<p>At last I would like to mention the objects and functions that can be used inside worker</p>
<p>Functions that can be called from Web Workers are</p>
<ul>
<li><strong>importScripts()</strong>: used to load external Javascript for use in the worker</li>
<li><strong>setTimeout()</strong> and <strong>setInterval()</strong>: used for setting timer tasks</li>
<li><strong>close()</strong>: stops the worker immediately</li>
</ul>
<p>Objects that are available in Web Workers are</p>
<ul>
<li>navigator</li>
<li>location</li>
<li>All javascript objects, like Array, Date, etc</li>
<li>XMLHttpRequest</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/02/multithreading-in-javascript-with-web-workers/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Data transmission over the network with Spring Integration</title>
		<link>http://xebee.xebia.in/2010/11/01/data-transmission-over-the-network-with-spring-integration/</link>
		<comments>http://xebee.xebia.in/2010/11/01/data-transmission-over-the-network-with-spring-integration/#comments</comments>
		<pubDate>Mon, 01 Nov 2010 10:13:30 +0000</pubDate>
		<dc:creator>Rohit Garg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[Spring Integration]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5353</guid>
		<description><![CDATA[Simple and basic steps and options that will help you to implement Network based messaging using Spring integration framework.]]></description>
			<content:encoded><![CDATA[<p>Spring Integration is a quite useful framework which provides asynchronous messaging capabilities to a system. Unlike traditional frameworks like JMS, this framework can be plugged into any application. I will not be going into the details of messaging and '<strong><em>How messaging works!</em></strong>' but an overview should be a good start.</p>
<p><span id="more-5353"></span></p>
<p>Messaging is a mechanism to invoke some actions asynchronously. Message passing helps to de-couple the logic from infrastructure and can be applied to almost every system. Sending across a communication to a system or more appropriately a <em>message handler</em> is called messaging.</p>
<p>There are two types of message handling implementations in Spring Integration framework - Queue channel based and Direct channel. In case of Queue based message handling, a pollable queue is placed after each message generator and one or more pollers are attached to that queue for handling and processing messages whereas in case of direct message handling, our message handler is attached to the direct channel which gets called as soon as the message is published to the channel.</p>
<p>Spring Integration framework can also be used to send data across the network. Think of a scenario where a file needs to be sent to a receiver and there is no limit to the size of that file. The only possible solution to reliably and quickly transmit that file over to the other end could be splitting it into number of messages and sending them across. Spring integration framework facilitates message transmission functionality by providing the necessary API to transmit Messages over the network in a reliable manner,</p>
<p>There are two base classes provided in spring integration framework to achieve this task - <strong>AbstractInternetProtocolSendingMessageHandler</strong> and <strong>AbstractInternetProtocolReceivingChannelAdapter</strong>. For the details of API, one must refer to the <a href="http://static.springsource.org/spring-integration/docs/2.0.0.M5/javadoc-api/org/springframework/integration/ip/tcp/package-summary.html">package summary</a> provided.</p>
<p><em><strong>How to use it??</strong></em></p>
<p>To add a simple TCP message handler/ TCP message receiver, the following snippets can be added to the <em>applicationContext.xml</em> file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;ip:inbound-channel-adapter protocol=&quot;tcp/udp&quot;
     channel=&quot;outputChannel&quot;
     close=&quot;false&quot;
     custom-socket-reader-class-name=&quot;CustomClass&quot;
     id=&quot;inbound&quot;
     local-address=&quot;localIpAddressForMultiHomeServers&quot;
     message-format=&quot;length-header&quot;
     pool-size=&quot;noOfThreads&quot;
     port=&quot;portNumber&quot;
     receive-buffer-size=&quot;bufferSize&quot;
     using-direct-buffers=&quot;true/false&quot;
     using-nio=&quot;true/false&quot; /&gt;</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;ip:outbound-channel-adapter protocol=&quot;tcp/udp&quot;
     channel=&quot;inputChannel&quot;
     custom-socket-writer-class-name=&quot;CustomClass&quot;
     host=&quot;hostname&quot;
     id=&quot;outbound&quot;
     local-address=&quot;localIpAddressForMultiHomeServers&quot;
     message-format=&quot;length-header&quot;
     port=&quot;portnumber&quot;
     using-direct-buffers=&quot;true/false&quot;
     using-nio=&quot;true/false&quot;/&gt;</pre>
<p><em><strong>Description of tags</strong></em></p>
<p>An inbound channel adapter is something that is used to receive the data from some sender and convert it to a <em>Message</em> object which would then be sent to the OutputChannel for further processing. It is an instance of <strong>AbstractInternetProtocolReceivingChannelAdapter's</strong> implementation depending upon the protocol specified.</p>
<p>On the contrary, an outbound channel adapter is supposed to send whatever is present on the InputChannel to some listener identified by hostname:portNumber. This is an instance of <strong>AbstractInternetProtocolSendingMessageHandler's</strong> implementation.</p>
<p>Besides, each handler-adapter pair implementation also uses an underlying <strong>SocketWriter-SocketReader</strong> pair as well.</p>
<p><a rel="attachment wp-att-5404" href="http://xebee.xebia.in/2010/11/01/data-transmission-over-the-network-with-spring-integration/springnetworkmessaging-2/"><img class="alignnone size-full wp-image-5404" title="SpringNetworkMessaging" src="http://xebee.xebia.in/wp-content/uploads/2010/10/SpringNetworkMessaging1.jpg" alt="" width="679" height="307" /></a></p>
<p>There are different <strong>message_formats</strong> via which, one can convert the Message object to byte data, namely :-</p>
<ul>
<li> FORMAT_LENGTH_HEADER - Sends message length in header first and then the byte message.</li>
<li> FORMAT_STX_ETX - Sends a special bit pattern STX, then data followed by ETX bit pattern.</li>
<li> FORMAT_CRLF - Starts sending a message and when its complete, sends a CR_LF bit pattern.</li>
<li> FORMAT_JAVA_SERIALIZED - Sends data after serializing the object using ObjectOutputStream.</li>
<li> FORMAT_CUSTOM - Left as an exercise for the reader <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</li>
</ul>
<p>Hint: You can add your own implementation of NetSocketWriter/NetSocketReader class in case you want to use FORMAT_CUSTOM.</p>
<p>In case someone doesn't know the destination beforehand, or maybe the port to listen to on the local machine, objects of above mentioned API can be created and parameters can be set dynamically. Finally, these objects can be registered to a ConfigurableApplicationContext for making them running.</p>
<p>These classes have four implementation classes each, two for TCP and two for UDP protocols. For TCP the two classes are segregated as:</p>
<p>1. <strong>TcpNetSendingMessageHandler</strong> and <strong>TcpNetReceivingChannelAdapter</strong> pair - This pair works over TCP simple Socket based implementation and does the usual socket stuff like blocking reads over streams, handling EOF when stream is closed. Both the classes use a SocketFactory class to create an instance of <strong>NetSocketWriter</strong> and a <strong>NetSocketReader</strong> respectively which follow the same protocol. You can choose to implement custom logic for sending data by adding a custom implementation to each of the <strong>NetSocketWriter</strong> and <strong>NetSocketReader</strong> classes and implement the methods <em>writeCustomFormat</em> and <em>assembleDataCustomFormat</em> respectively.</p>
<p>2. <strong>TcpNioSendingMessageHandler</strong> and <strong>TcpNioReceivingChannelAdapter</strong> pair - This pair works almost the same way as the above mentioned apart from the fact that this pair uses NioSocketWriter and NioSocketReader pair. It does have an additional capability to use direct buffers for channels which enhances the speed many folds. Although the NIO based IO is a little slow, its never blocking. So there might be some performance concerns on the system as well as it will always be executing code to read from the streams even though there is nothing present. Please note that FORMAT_JAVA_SERIALIZED is not supported by this kind of pair. Rest all formats work fine. Also, the hint in this implementation changes to <strong>NioSocketWriter/NioSocketReader</strong> pair.</p>
<p>For UDP, the pairs are not used much because most of the network firewalls have security issues using UDP protocol. Moreover its not a reliable protocol anyways. The pairs for sending messages over UDP are <strong>UnicastSendingMessageHandler-UnicastReceivingChannelAdapter</strong> and <strong>MulticastSendingMessageHandler-MulticastReceivingChannelAdapter</strong>. This system is an ACK driven setup and relies on the successful reception of ACK message from the receiver. Reliability can be added through code by enforcing a check for successful reception of ACK message else the message goes to error handler in case the TTL(Time To Live) is expired.</p>
<p>The UDP attributes like multicast and multicast-address have not been added to the tags. One more attribute is there in case UDP is used which is check-length. It enforces a check for length of the message. Also, in case of outbound-adapter, ack message related attributes like acknowledge, ack-host, ack-port, ack-timeout can also be added to the tag.</p>
<p><em><strong>Tips and tricks:</strong></em></p>
<p>There were some scenarios where certain tweaks were really helpful. I would like to list down some which could be encountered most of the times when someone uses this framework.</p>
<ol>
<li>You can build your own mechanism to perform cleanup like closing of the socket after all the messages have been sent. This helps to transfer messages faster as each time making/breaking a connection takes CPU and time. To do this, a custom implementation of SocketWriter needs to be created and put into the object of your AbstractInternetProtocolSendingMessageHandler's implementation which will hold the logic of closing the connection after sending all the data. By default the connection always remains open.</li>
<li>While serializing an object through FORMAT_JAVA_SERIALIZED, please make sure that you don't reuse the existing object by just changing the state of that object. Java will not serialize new bytes for that object as there is a separate API called <strong>ObjectOutputStream.writeUnshared</strong> for performing that task. Making your classes immutable should help a lot here.</li>
<li>The framework will not send the MessageHeaders set on the message to the other end. So, some custom logic needs to be built in case headers are needed on the receiver. Simple trick to do that will be just make a wrapper class which contains both, message and header objects and send that wrapper to the other side.</li>
<li>While using ConfigurableApplicationContext for building the logic, you will have to add a <strong>TaskScheduler</strong> object to the adapter. That object is actually never used. Instead, the Adapter builds its own <strong>ThreadPoolTaskScheduler</strong> and its pool size can be set using <strong>TcpNetReceivingChannelAdapter.setPoolSize</strong>. That means in case you set a ThreadPoolTaskScheduler as the TaskScheduler in TcpNetReceivingChannelAdapter, don't expect its pool size to work.</li>
</ol>
<p><em><strong>Conclusion:</strong></em></p>
<ul>
<li>Sending data across network is very common in distributed systems. Having a framework which takes care of almost all of the sender/receiver things helps a lot.</li>
<li>Spring is always keen to help the developers reduce boiler plate code so using it in any project is always a fair deal.</li>
<li>Spring Integration is a lightweight and standalone implementation of messaging just like JMS on most of the enterprise servers. It can be used with or without a server as it only needs a couple of jars.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/11/01/data-transmission-over-the-network-with-spring-integration/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Working with GeoLocations</title>
		<link>http://xebee.xebia.in/2010/10/28/working-with-geolocations/</link>
		<comments>http://xebee.xebia.in/2010/10/28/working-with-geolocations/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 04:40:58 +0000</pubDate>
		<dc:creator>Robin Nagpal</dc:creator>
				<category><![CDATA[Location Based Services]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[Latitude]]></category>
		<category><![CDATA[Longitude]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5653</guid>
		<description><![CDATA[Are you looking for an API that can perform the following GeoLocation functions Find distance between two points Find extreme points i.e. points with min/max latitude and longitude from a center point, for a given distance Find point of interest near you These days we use GeoLocation related services in almost all the applications and [...]]]></description>
			<content:encoded><![CDATA[<p>Are you looking for an API that can perform the following GeoLocation functions</p>
<div style="text-align: left; margin-left: 130px; float: center;">
<ul>
<li>Find distance between two points</li>
<li>Find extreme points i.e. points with min/max latitude and longitude from a center point, for a given distance</li>
<li>Find point of interest near you</li>
</ul>
</div>
<p>These days we use GeoLocation related services in almost all the applications and sometimes we don't want to be dependent on third party GeoLocation API's for doing some simple operations as mentioned above. For these purposes I tried to use sample code available at  different sites, but some of them gave wrong results and some of them did not suit our requirements. So, I decided to write it myself.</p>
<p><span id="more-5653"></span></p>
<p>In this blog I am not going to explain the trigonometric formulae for performing the above operations, but will present you with Java code that you can use. Before I show the code for performing the above listed operations, I  would like to explain some basic terms.</p>
<p><strong>Latitude</strong>- location of a place on Earth (or other planetary body) north or south of the equator. <strong>Lines of Latitude</strong> are the imaginary horizontal lines running east-to-west (or west to east) on maps either north or south of the equator ranging from 0° at the equator to +90° for the North Pole and −90° for the South Pole</p>
<p><strong>Longitude </strong>- An east-west measurement of position on Earth, measured from a vertical plane running through the polar axis and the prime meridian, recorded in degrees, minutes and seconds ranging from 0 degrees at the prime meridian to 180 degrees west and east.</p>
<p><strong>Geocoding </strong>- process of finding associated geographic coordinates( latitude and longitude) from other geographic data, such as street addresses, city name, state or zip codes( postal codes)</p>
<p><strong>Reverse Geocoding </strong>- finding an associated textual location such as a street address, city name ,state, zip code etc from geographic coordinates.</p>
<p>To perform the above mentioned operations like finding distance between points, points in a given radius etc you need latitude and longitude of the center point. As clear from the geocoding definition, you can find latitude and longitude corresponding to an address by using any third party Geocoding API. I have used google geocoding api's which give very good results.</p>
<ol>
<li><strong>Distance between two Points : </strong> Using the below function you can find distance between two points.
<pre class="brush: java; title: ; notranslate">
private static double getDistanceBetweenPoints(Point p1, Point p2,
           String unit) {
double theta = p1.longitude - p2.longitude;
double dist = Math.sin(deg2rad(p1.latitude))
        * Math.sin(deg2rad(p2.latitude))
        + Math.cos(deg2rad(p1.latitude))
        * Math.cos(deg2rad(p2.latitude)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit.equals(&quot;K&quot;)) {
     dist = dist * 1.609344;
} else if (unit.equals(&quot;M&quot;)) {
     dist = dist * 0.8684;
}
     return (dist);
}
</pre>
<p>The distance returned by this method depends upon the units passed. If you want to get distance in Kilometers pass "K" as the argument or if you want distance in Miles pass "M".</li>
<li><strong>Extreme points :</strong> To find the extreme points you need to know the maximum latitude and longitude difference in degrees corresponding to distance. Using these differences you can determine the maximum and minimum, latitude and longitude from center point. You just have to add or subtract these latitude/longitude differences from the center point and you will get the extreme points.<br />
Latitude difference for a distance from a point</p>
<pre class="brush: java; title: ; notranslate">
	private static double getExtremeLatitudesDiffForPoint(Point p1,
			double distance) {
		double latitudeRadians = distance / EARTH_RADIUS_KM;
		double diffLat = rad2deg(latitudeRadians);
		return diffLat;
	}
</pre>
<p>Longitude difference for a distance from a point</p>
<pre class="brush: java; title: ; notranslate">
	private static double getExtremeLongitudesDiffForPoint(Point p1,
			double distance) {
		double lat1 = p1.latitude;
		lat1 = deg2rad(lat1);
		double longitudeRadius = Math.cos(lat1) * EARTH_RADIUS_KM;
		double diffLong = (distance / longitudeRadius);
		diffLong = rad2deg(diffLong);
		return diffLong;
	}
</pre>
<p>Extreme Points</p>
<pre class="brush: java; title: ; notranslate">
	private static Point[] getExtremePointsFrom(Point point, Double distance) {
		double longDiff = getExtremeLongitudesDiffForPoint(point, distance);
		double latDiff = getExtremeLatitudesDiffForPoint(point, distance);
		Point p1 = new Point(point.latitude - latDiff, point.longitude
				- longDiff);
		p1 = validatePoint(p1);
		Point p2 = new Point(point.latitude + latDiff, point.longitude
				+ longDiff);
		p2 = validatePoint(p2);

		return new Point[] { p1, p2 };
	}
</pre>
<p>This method will return an array of two extreme points corresponding to center point and the distance from the center point. These extreme points are the points with max/min latitude and longitude.</li>
<li><strong>Find point of interest near you :</strong> If you are using MySql you can use the below query to find all the points within a particular radius.Suppose you have an address table which has all the points of interest, along with latitude and longitude for each point, query to find all the points inside a given radius is
<pre class="brush: sql; title: ; notranslate">
select *,3956*2*ASIN(SQRT(POWER(SIN((37.804372-abs(dest.latitude))*pi()/180/2 ), 2) + COS(37.804372*pi()/180)*COS(abs(dest.latitude) *pi()/180)*POWER(SIN((-122.270803-dest.longitude)*pi()/180/2 ),2))) as distance from address dest having distance &lt;100 order by distance;
</pre>
<p>Let us assume you have some points present in your database and you want to find all the points within 10 miles of distance from the center point, you can execute the above query against the database and get the relevant points. The points returned will lie between a circle of 10 miles radius drawn from the center point.<br />
<a rel="attachment wp-att-5166" href="http://xebee.xebia.in/?attachment_id=5166"><img class="size-full wp-image-5166 alignleft" title="within-radius" src="http://xebee.xebia.in/wp-content/uploads/2010/10/within-radius3.png" alt="" width="400" height="272" /></a><br />
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br />
The execution of the above query will be time consuming if you have lot of points in your database, as it has lot of operations in it. In this case it would be advisable to find the extreme points and use the latitude/longitude of these points to get all the points lying within the latitude and longitude ranges of extreme points i.e. find the points between the max and min latitude/longitude. Now you will have a simple 'between' clause in your sql query, rather than the big computation discussed in previous case.</p>
<p><a rel="attachment wp-att-5245" href="http://xebee.xebia.in/?attachment_id=5245"><img class="alignleft size-full wp-image-5245" title="within-extremepoints" src="http://xebee.xebia.in/wp-content/uploads/2010/10/within-extremepoints.png" alt="" width="393" height="336" /></a><br />
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br />
Now using the extreme points you will get all the points that are in the square, with side length of square equal to distance and is located at the center from which you want your points. You can now find the distance of  these points from center and filter out the results whose distance is greater than given distance.</li>
</ol>
<p>I have also attached the java file which contains all these functions.<br />
<a href="http://www.sendspace.com/file/yv0lki" target="_blank">GeoLocationService.java</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/28/working-with-geolocations/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Working with Git</title>
		<link>http://xebee.xebia.in/2010/10/25/working-with-git/</link>
		<comments>http://xebee.xebia.in/2010/10/25/working-with-git/#comments</comments>
		<pubDate>Mon, 25 Oct 2010 05:28:16 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[GIT]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5843</guid>
		<description><![CDATA[A video blog / screencast to help you get started with Git.]]></description>
			<content:encoded><![CDATA[<p>A video blog / screencast to help you get started with Git.</p>
<div id="media">
            <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="640" height="379" id="csSWF"><param name="movie" value="http://xebee.xebia.in/wp-content/uploads/2010/10/git-1-perfect-1_controller.swf" /><param name="quality" value="best" /><param name="bgcolor" value="#1a1a1a" /><param name="allowfullscreen" value="true" /><param name="scale" value="showall" /><param name="allowscriptaccess" value="always" /><param name="flashvars" value="autostart=false&thumb=http://xebee.xebia.in/wp-content/uploads/2010/10/FirstFrame.png&thumbscale=45&color=0x000000,0x000000" /><!--[if !IE]>--><br />
                <object type="application/x-shockwave-flash" data="http://xebee.xebia.in/wp-content/uploads/2010/10/git-1-perfect-1_controller.swf" width="640" height="379"><param name="quality" value="best" /><param name="bgcolor" value="#1a1a1a" /><param name="allowfullscreen" value="true" /><param name="scale" value="showall" /><param name="allowscriptaccess" value="always" /><param name="flashvars" value="autostart=false&thumb=http://xebee.xebia.in/wp-content/uploads/2010/10/FirstFrame.png&thumbscale=45&color=0x000000,0x000000" /><!--<![endif]--><br />
                 <!--[if !IE]>--><br />
                </object><br />
                <!--<![endif]--><br />
            </object>
        </div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/25/working-with-git/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Creating table renderers in JavaFx</title>
		<link>http://xebee.xebia.in/2010/10/22/creating-renderers-in-javafx/</link>
		<comments>http://xebee.xebia.in/2010/10/22/creating-renderers-in-javafx/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 12:46:47 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[cell]]></category>
		<category><![CDATA[font]]></category>
		<category><![CDATA[header]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[renderer]]></category>
		<category><![CDATA[table]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5779</guid>
		<description><![CDATA[In this post, you'll learn to create your custom renderer for a cell or a header of a table in JavaFx. A table which is apparently a swing JTable wrapped in a node of JavaFx using SwingComponent class. In the following application I'll not only use these renderers, but will also provide solution to the [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;">In this post, you'll learn to create your custom renderer for a cell or a header of a table in JavaFx.</span></p>
<p><span style="color: #000000;">A table which is apparently a swing JTable wrapped in a node of JavaFx using SwingComponent class.<br />
</span></p>
<p><span style="color: #000000;">In the following application I'll not only use these renderers, but will also provide solution to the problems of spacing and sizing which inherently appears when you try to use JTable in ScrollPane.</span></p>
<p style="text-align: left;"><span id="more-5779"></span></p>
<p style="text-align: left;">The Output of the application would be.</p>
<p><a rel="attachment wp-att-5781" href="http://xebee.xebia.in/2010/10/22/creating-renderers-in-javafx/cellrendererdemo/"><img class="alignleft size-full wp-image-5781" title="cellrendererDemo" src="http://xebee.xebia.in/wp-content/uploads/2010/10/cellrendererDemo.jpg" alt="" width="467" height="157" /></a></p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p><span style="color: #000000;">The following TableRendererDemo.java class has been used here to create the table contents as shown in the figure above.<br />
</span></p>
<p><span style="color: #000000;">
<pre class="brush: javafx; title: ; notranslate">
package tablerenderersdemo;

import java.awt.Dimension;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public class TableRendererDemo {
    JTable table;
TableColumn tcol;

Public DefaultTableModel TableCreater(){
    String data[][] = {{&quot;Karan&quot;, &quot;JavaFx&quot;, &quot;5&quot;},
{&quot;Saurabh&quot;, &quot;&lt;htmI&gt;&lt;font color='green'&gt;&lt;b&gt;Android&lt;/b&gt;&lt;/font&gt;&lt;/htmI&gt;&quot;, &quot;6&quot;},
{&quot;Guneet&quot;, &quot;Gigaspaces&quot;, &quot;5&quot;}, {&quot;Richa&quot;, &quot;Flex&quot;, &quot;5&quot;},{&quot;Rajneesh&quot;, &quot;Testing&quot;, &quot;5&quot;},
{&quot;Paritosh&quot;, &quot;&lt;htmI&gt;&lt;font color='red'&gt;Java&lt;/font&gt;&lt;/htmI&gt;&quot;, &quot;5&quot;}};
String col[] = {&quot;Name&quot;, &quot;Speciality&quot;, &quot;Availability Floor&quot;};
DefaultTableModel model = new DefaultTableModel(data, col);
return model;
}

public Dimension getTableDimensions() {
return new Dimension(450, 100);
}
}
</pre>
<p></span>And here are the two renderers files for cell and header styling respectively where we have overridden the implementation of  method <strong>getTableCellRendererComponent.</strong></p>
<p><span style="text-decoration: underline;">Implementation of CellRenderer:</span><strong><span style="text-decoration: underline;"><span style="color: #000000;"><span style="color: #000000;"> </span></span></span></strong><span style="color: #000000;"><span style="color: #000000;"> </span></span></p>
<pre class="brush: javafx; title: ; notranslate">
&lt;pre&gt;
&lt;pre&gt;package tablerenderersdemo;

import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * A custom implementation of DefaultTableCellRenderer
 *
 */
public class CellRenderer extends DefaultTableCellRenderer {

public CellRenderer() {
        super();
}
    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object obj, boolean isSelected, boolean hasFocus, int row, int column) {
        Component cell = super.getTableCellRendererComponent(
                table, obj, isSelected, hasFocus, row, column);
        if (isSelected) {
            cell.setBackground(Color.green);
        } else {
            if (row % 2 == 0) {
                cell.setBackground(Color.cyan);
            } else {
                cell.setBackground(Color.blue);
            }
        }
        return cell;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void setValue(Object value) {
        if (value == null) {
            value = &quot;&quot;;
        }
        setText(value.toString());

    }
}
</pre>
<p><span style="text-decoration: underline;">Implementation of HeaderRenderer<strong>:<span style="color: #000000;"><span style="color: #000000;"> </span></span></strong></span></p>
<pre class="brush: javafx; title: ; notranslate">
package tablerenderersdemo;

import java.awt.Color;
import java.awt.Component;
.
.
public class HeaderRenderer extends JLabel implements TableCellRenderer {

public HeaderRenderer() {
        setOpaque(true);
        setForeground(UIManager.getColor(&quot;TableHeader.foreground&quot;));
        setBackground(Color.lightGray);
        setBorder(UIManager.getBorder(&quot;TableHeader.cellBorder&quot;));
    }

  @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setText((String) value);
        setFont(new Font(&quot;sansserif&quot;, Font.BOLD, 14));
        return this;
    }

}&lt;/pre&gt;
</pre>
<p>Now in our main class of the application which is Main.Fx, first we'll create a Java Swing JTable using DefaultTableModel and assign headerRenderer through the column model of the table and a cellRenderer to the desired column of the table by referring it through the index number of the table. We have also used the autoResizeMode to "JTable.AUTO_RESIZE_ALL_COLUMNS" so that When the width of a column is changed,  the widths of all other columns are changed  keeping the width of the entire table same. "setPreferredScrollableViewportSize" method ensures that there is no spacing left towards right of the table, leaving a gap between the table and the scrollpane.</p>
<p><span style="text-decoration: underline;"><strong>Main.fx</strong></span></p>
<pre class="brush: javafx; title: ; notranslate">
import javafx.scene.Scene;
.
.

public class Main {
public static var scrollPane:JScrollPane;
public function TableRenderer(){
var tableRenderer:TableRendererDemo = new TableRendererDemo();
var model:DefaultTableModel = tableRenderer.TableCreater();
var jTable:JTable = new JTable(model);
var headerRenderer:HeaderRenderer = new HeaderRenderer();
var cellrenderer:CellRenderer = new CellRenderer();

for(i in  [0..jTable.getColumnModel().getColumnCount()-1 step 1]){
jTable.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);
}

jTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
var column:TableColumn  = jTable.getColumnModel().getColumn(2);
column.setCellRenderer(cellrenderer);
jTable.setPreferredScrollableViewportSize(tableRenderer.getTableDimensions());
scrollPane = new JScrollPane(jTable);
}

}

function run(){
var design = Main {};
design.TableRenderer();
var scrollView = ScrollView {
hbarPolicy: ScrollBarPolicy.NEVER;
vbarPolicy: ScrollBarPolicy.ALWAYS;
node: SwingComponent.wrap(design.scrollPane);
layoutInfo: LayoutInfo {
width: 450;
height: 120;
}
}

Stage {
title: &quot;Table Rendering demo..&quot;
scene: Scene {
width: 450; height: 120;
content: [scrollView];
}
}
}
</pre>
<p><span style="color: #000000;"><br />
</span>Save and run this file , and/or change the renderers to add images/styles as per your requirement.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<p>package tablerenderersdemo;</p>
<p>import javafx.stage.Stage;<br />
import javafx.scene.Scene;<br />
import javax.swing.JTable;<br />
import javafx.scene.control.ScrollView;<br />
import javafx.scene.control.ScrollBarPolicy;<br />
import javafx.ext.swing.SwingComponent;<br />
import javafx.scene.layout.LayoutInfo;<br />
import javax.swing.JScrollPane;<br />
import tablerenderersdemo.TableRendererDemo;<br />
import javax.swing.table.DefaultTableModel;<br />
import javax.swing.table.TableColumn;</p>
<p>/**<br />
* @author richa<br />
*/<br />
public class Main {<br />
public static var scrollPane:JScrollPane;<br />
public function TableRenderer(){<br />
var tableRenderer:TableRendererDemo = new TableRendererDemo();<br />
var model:DefaultTableModel = tableRenderer.TableCreater();<br />
var jTable:JTable = new JTable(model);<br />
var headerRenderer:HeaderRenderer = new HeaderRenderer();<br />
var cellrenderer:CellRenderer = new CellRenderer();</p>
<p>for(i in  [0..jTable.getColumnModel().getColumnCount()-1 step 1]){<br />
jTable.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);<br />
}<br />
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);<br />
var column:TableColumn  = jTable.getColumnModel().getColumn(2);<br />
column.setCellRenderer(cellrenderer);<br />
jTable.setPreferredScrollableViewportSize(tableRenderer.getTableDimensions());</p>
<p>scrollPane = new JScrollPane(jTable);<br />
}</p>
<p>}</p>
<p>function run(){<br />
var design = Main {};<br />
design.TableRenderer();<br />
var scrollView = ScrollView {<br />
hbarPolicy: ScrollBarPolicy.NEVER;<br />
vbarPolicy: ScrollBarPolicy.ALWAYS;<br />
node: SwingComponent.wrap(design.scrollPane);<br />
layoutInfo: LayoutInfo {<br />
width: 450;<br />
height: 120;<br />
}<br />
}</p>
<p>Stage {<br />
title: "Table Rendering demo.."<br />
scene: Scene {<br />
width: 450;<br />
height: 120;<br />
content: [scrollView];<br />
}<br />
}<br />
}</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/22/creating-renderers-in-javafx/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Building a Hadoop Cluster using VirtualBox</title>
		<link>http://xebee.xebia.in/2010/10/21/building-a-hadoop-cluster-using-virtualbox/</link>
		<comments>http://xebee.xebia.in/2010/10/21/building-a-hadoop-cluster-using-virtualbox/#comments</comments>
		<pubDate>Thu, 21 Oct 2010 04:01:36 +0000</pubDate>
		<dc:creator>Ravindra</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[Virtualization]]></category>
		<category><![CDATA[hadoop]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5439</guid>
		<description><![CDATA[Getting a few spare machines to start learning a NoSQL database or distributed software in early stages looks like an overkill($$). This blog post addresses creating a Ubuntu based Virtual machine for running Hadoop and automation of virtual machine (VM) creation from a given disk images using VirtualBox. While starting with NoSQL group at Xebia we decided [...]]]></description>
			<content:encoded><![CDATA[<p>Getting a few spare machines to start learning a NoSQL database or distributed software in early stages looks like an overkill($$). This blog post addresses creating a Ubuntu based Virtual machine for running <a title="Apache Hadoop" href="http://hadoop.apache.org/">Hadoop</a> and automation of virtual machine (VM) creation from a given disk images using <a title="VirtualBox" href="http://www.virtualbox.org/">VirtualBox</a>.</p>
<p>While starting with NoSQL group at Xebia we decided to initially use virtual machines to host HBase, Hadoop etc, so that it is relatively easy for a new person to get started. Actual cluster deployment helps to learn about a *real world* deployment, and we could use this process setup an office wide cluster to run an actual map-reduce job on the office laptops. Creating a new Virtual Machine takes some time and is repetitive task which can be automated.</p>
<p>If you are already familiar with VirtualBox then you could jump to <a href="post.php?post=5439&amp;action=edit&amp;message=10#automation">Automation</a> directly.</p>
<p><span id="more-5439"></span></p>
<p><strong>Creating a Guest OS Disk</strong></p>
<p>The exercise started out with choosing a small OS (of course *nix based) with just a command line interface. We wanted the OS drive to be as compact as possible. We shortlisted following 3 OS distros for testing.</p>
<p>1. TinyCore<br />
2. DamnSmallLinux<br />
3. Ubuntu-Mini<br />
4. Ubuntu-Server</p>
<p><strong>Why Ubuntu-Server</strong></p>
<p>TinyCore actually is a tiny installation, only problem faced was comfort level with the softwares available in its repositories (which is not as vast as the apt repositories).</p>
<p>Damn Small Linux needed a bit more analysis in terms of installing applications (ssh, java),<br />
so it is on hold now.</p>
<p>Ubuntu-Mini installation fetched everything for apt repositories and basically became a ubuntu-server.</p>
<p>Finally Ubuntu-server was tried trusting that the OS settings are optimized for server operation.  The choice of OS is open and basically an expert could build his/her own tiny linux distribution.</p>
<p><strong>Create a Virtual Machine:</strong><br />
I created the first virtual machine manually. You could follow the instructions on (http://www.online-tech-tips.com/cool-websites/free-virtual-machine-software/) to install ubuntu (Virtual box now has a Ubuntu option in OS Type dropdown). You will have to mount the Ubuntu ISO server image in the CD drive.</p>
<p>Keep the RAM size to 512M and disk space size to ~1.5 - 2 GB.</p>
<p><strong>Setting up the machine.</strong></p>
<p>Once Ubuntu is installed, adding a ssh server is as easy as<br />
apt-get install openssh-server openssh-client.<br />
You can setup a passwordless ssh login using instruction at the link (http://www.debian-administration.org/articles/152)</p>
<p>Java need to be installed on the machine as well. Most of the NoSQL servers recommend sun-jre for now. You will have to download the installer from Sun/Oracle site. You could refer to following steps.</p>
<pre class="brush: plain; title: ; notranslate">
    ssh-add ~/xebia/id_dsa
    scp jre-6u21-linux-i586.bin xebia@192.168.56.101:
    ssh xebia@192.168.56.101 'chmod u+x jre*;./jre-6u21-linux-i586.bin;ln -s jre-6u21-linux-i586 jre'
</pre>
<p><strong>Network Setup</strong></p>
<p>VirtualBox provides 4 types of networking (detailed in its help). For now, we are going to use Host Networking as we want to have a network between the VMs and host.</p>
<p>This completes the basic setup of the Guest OS.</p>
<p><strong>Hadoop on a New drive.</strong></p>
<p>It is desirable to have a basic OS image and an additional hardware disk image. This gives an option to use the same OS image with some other softwares.</p>
<p>Following steps show how to mount and configure a new drive in the OS.</p>
<pre class="brush: plain; title: ; notranslate">
// Manually create a 1 GB drive using VirtualBox Virtual Media Manager and attach it to the VM.
// new disk should be /dev/sdb
fdisk /dev/sdb
mkfs -t ext4 /dev/sdb1
tune2fs -m 1 /dev/sdb1

// create an entry in fstab to mount this drive automaticallly (/media/hadoop)
</pre>
<p>I have setup access to the VM from my Host Ubuntu machine so that i do not have to live with the flickering display of the VM. Following script automates installation of hadoop on the just mounted drive.</p>
<pre class="brush: plain; title: ; notranslate">
    scp hadoop* xebia@$&lt;VM IP&gt;:/media/hadoop/
    ssh xebia@$&lt;VM IP&gt; 'cd /media/hadoop;gunzip hadoop.tar.gz;tar xvf hadoop.tar'
    ssh xebia@$&lt;VM IP&gt; 'cd /media/hadoop;ln -s hadoop-* hadoop'
</pre>
<p>Hadoop config is modified to refer to java installation and modify core-site.xml, hdfs-site.xml, mapred-site.xml.<br />
Later "slaves" file in conf need to be modified to refer to other VMs.</p>
<p><strong>Automation</strong><br />
The above process is lengthy and i did not want to do this for every VM. VirtalBox provides a command line interface to perform all activities that are done from UI. And now we had two disk images (Guest OS and Hadoop install) which can be sort of reused for every VM. See the following annotated script for details.</p>
<pre class="brush: plain; title: ; notranslate">
#!/bin/bash

# Path to already created disk images
cd ~/.VirtualBox/HardDisks
OS_IMAGE=ubuntu-mini2.vdi
HADOOP_DISK=hadoop-disk.vdi

#ARGS is new VM name

vmname=&quot;$1&quot;
VB=VBoxManage

if [ -z &quot;$vmname&quot; ]; then
        echo &quot;Provide a VM Name&quot;; exit -1;
fi

# Does as it says .. clones the disks.
function clonedisks() {
  if [ -f &quot;${vmname}.vdi&quot; ]; then
    echo &quot;Disk image exists... ${vmname}.vdi&quot;;
    exit -1;
  fi
  echo &quot;Cloning disks...${vmname}&quot;;
  $VB clonehd $OS_IMAGE ${vmname}.vdi --remember
  $VB clonehd $HADOOP_DISK ${vmname}-hadoop.vdi --remember
}

# Created a Virtual Machine
function createVM() {
  $VB createvm --name ${vmname} --ostype &quot;Ubuntu&quot; --register
}

function configureVM() {
# Machine settings
  $VB modifyvm ${vmname} --memory 512
  $VB modifyvm ${vmname} --vram 12
  $VB modifyvm ${vmname} --cpus 1
  $VB modifyvm ${vmname} --boot1 disk

# Configures the network
  $VB modifyvm ${vmname} --nic1 hostonly
  $VB modifyvm ${vmname} --nictype1 82540EM
  $VB modifyvm ${vmname} --hostonlyadapter1 vboxnet0

# Attached the two hard drives
  $VB storagectl ${vmname} --name &quot;${vmname}-sata&quot; --add sata --controller IntelAhci --sataportcount 2
  $VB storageattach ${vmname} --storagectl &quot;${vmname}-sata&quot; --port 1 --device 0 --type hdd --medium ${vmname}.vdi
  $VB storageattach ${vmname} --storagectl &quot;${vmname}-sata&quot; --port 2 --device 0 --type hdd --medium ${vmname}-hadoop.vdi

# fix the VMs hostname
   $VB guestcontrol execute hello /bin/ls --username xebia --password xebia123 --verbose --wait-for stdout

}

function start() {
    VBoxHeadless --startvm ${vmname} --vrdp=off
}

clonedisks
createVM
configureVM
#start
</pre>
<p>With the new VM setup do not forget to add its IP/hostname to 'slaves' file.</p>
<p><strong>Open Issues:</strong><br />
Since we are using the OS disk image every host has the same name which creates a problem. I am fixing this manually at present by editing /etc/hosts and /etc/hostname.<br />
This can be fixed by installing Guest Additions in the OS image and automating the process(in progress).</p>
<p>Armed with the 3 machine hadoop cluster i was able to run the sample map reduce task. This cluster would not run the job faster but at least it gives an ability to do a distributed install on your local machine and ability to "scale out".</p>
<p>Do let me know your feedback/questions/suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/21/building-a-hadoop-cluster-using-virtualbox/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Android UI development tools</title>
		<link>http://xebee.xebia.in/2010/10/20/android-ui-development-tools/</link>
		<comments>http://xebee.xebia.in/2010/10/20/android-ui-development-tools/#comments</comments>
		<pubDate>Wed, 20 Oct 2010 18:49:11 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[development tools]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5766</guid>
		<description><![CDATA[Today I had a pleasure of attending one of Google's Android Developer Conference by Rajdeep Dua ,Thanks to Rajdeep Dua I came to know some of android tools (by Google as well as third party not integrated with IDE)  available in the market to enhance UI application development. Before we start looking through the list of [...]]]></description>
			<content:encoded><![CDATA[<div><span style="font-family: arial; line-height: normal; font-size: small; "> Today I had a pleasure of attending one of Google's Android Developer Conference by Rajdeep Dua ,Thanks to Rajdeep Dua I came to know some of android tools (by Google as well as third party not integrated with IDE)  available in the market to enhance UI application development.</span></div>
<div><span style="font-family: arial; line-height: normal; font-size: small; "><br /></span></div>
<div><span style="font-family: arial; line-height: normal; font-size: small; "> Before we start looking through the list of tool. Please do have a look at the  <a title="UI Guidelines" href="http://developer.android.com/guide/practices/ui_guidelines/index.html" target="_blank">Android UI Guidelines</a>. If you publish your application on the android App market and would like your application to appear in the featured list you will have to meet the UI guidelines are drawn by above link.Hence do follow the UI guidelines while making your android application if you want Android market guys to consider your application in features list.<span id="more-5766"></span></span></div>
<div><span style="font-family: arial; line-height: normal; font-size: small; "><br /></span></div>
<div><span style="font-family: arial; line-height: normal; font-size: small; ">Okay , So lets start exploring the available tools. If you have just started learning android using eclipse IDE making a nice UI is not easy using the basic design mode.<a title="DroidDraw" href="http://www.droiddraw.org/" target="_blank">DroidDraw</a> is the alternative to making good and fast graphical user interfaces. DroidDraw is available for (Windows , Mac , Linux) .It helps you to easily create the UI and generate the required xml file.If you would like to quick test your UI as how it looks on the android phone without integrating the code with you core application use <a title="AnDroidDraw" href="http://www.droiddraw.org/androiddraw.html" target="_blank">Androiddraw </a>application.</span></div>
<div><span style="font-family: arial; line-height: normal; font-size: small; "><br /></span></div>
<div><span style="font-size: small;">Well that was droid draw to develop the UI faster. If you have gone through the UI Guidelines they are pretty strict to some extend. I will be difficult to cope up with it all the time.However we have a solution to that also. The next thing we are going to talk about is the<a href="http://code.google.com/p/android-ui-utils/" target="_blank"> Android UI Utils</a> . Android UI utils is the project currently present in google code. We are going to discuss two things Android Asset Studio and UI Prototyping Stencils.</span></div>
<div><span style="font-size: x-small;"><span style="font-size: x-small;"><br /></span></span></div>
<div><span style="font-size: small; "> <a href=" http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html " target="_blank">Android Asset Studio</a> is the Utility developed to help programmers create icons easily. Its a pretty handy tool to create different icons with all the variation like (hdpi , ldpi  ,mdpi) .Using this tool you can generate all kind of icons tab, menu launcher and notification icons.</span></div>
<div><span style="font-size: small; "><br /></span></div>
<div><span style="font-size: small; ">Next is a UI Prototyping Stencil (<a href="http://pencil.evolus.vn/en-US/Home.aspx" target="_blank">Pencil 1.2</a>) , its currently available as a add on in Firefox as well as a standalone .Its a free open source tool used to create quick GUI prototyping images.Pencil provides the rich set of android UI components avaliable for drag and drop to create a fast UI prototyping.</span></div>
<div><span style="font-size: small; "><br /></span></div>
<div><span style="font-size: small; ">Apart from the above mentioned tools you should also use draw9patch to avoid inappropriate scaling of the images.<a href="http://developer.android.com/guide/developing/tools/draw9patch.html" target="_blank">Draw9Patch</a> program is avaliable in android-sdk-windows\tools directory .A simple png file can be loaded into the application and after applying appropriate patches can be exported to get a NinePatch graphics.</span></div>
<div><span style="font-size: x-small;"><br /></span></div>
<div><span style="font-size: small; ">Well that is not all, the last one is a Android NDK (<a href="http://developer.android.com/sdk/ndk/index.html" target="_blank">Native Development Kit</a>). Android NDK is a companion tool that you will have to download if you wish to build performance critical portions of the app in native code. Android NDK helps in embedding the components coded in Native code with Android SDK.</span></div>
<div><span style="font-size: small; "><br /></span></div>
<div>Well these are the few tools that i came across today that i wasn't aware. Please do leave a comment if you know few more.</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/20/android-ui-development-tools/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Flex :  Increase your productivity while working on a bigger application</title>
		<link>http://xebee.xebia.in/2010/10/12/flex-increase-your-productivity-while-working-on-a-bigger-application/</link>
		<comments>http://xebee.xebia.in/2010/10/12/flex-increase-your-productivity-while-working-on-a-bigger-application/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 20:40:52 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[compiling]]></category>
		<category><![CDATA[conditional]]></category>
		<category><![CDATA[flex conditional compiling]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5524</guid>
		<description><![CDATA[Once the project starts growing you repeatably spend your time performing same actions e.g. Login ,  fill form,etc . Lets consider following use case I have to add two new validation in the current form which takes more than 5-6 inputs fields. Also to open the form i will have to perform 4-5 steps like [...]]]></description>
			<content:encoded><![CDATA[<p>Once the project starts growing you repeatably spend your time performing same actions e.g. Login ,  fill form,etc . Lets consider following use case  I have to add two new validation in the current form which takes more than 5-6 inputs fields. Also to open the form i will have to perform 4-5 steps like  login , go to settings page , click on link , click on create button and wait for the form to open , fill all the fields and once you are done with all the required fields fill the two new fields and validate.<br /> Whoops there is a error, something didn't work while saving the form try again <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .This approach can be pretty nasty as you spend a lot of developer time doing the repetitive steps<span id="more-5524"></span></p>
<p>One of the approach is you hard code field (username , password) the values inside the form and once the application starts click on appropriate buttons and continue with you test. This approach might work for some but is a little dangerous, last thing you wanna know is that the username and password is committed into the code.</p>
<p>We had a similar condition , while working we had to go deep down to a particular container follow the same inputs repeatably and then continue our work.<br /> This is where flex conditional compiling came to rescue.Using flex conditional compiling we could add in all the code that we did not want<br /> to go to production and still have it in the Application. In the example below we will see a simpler way to add flex conditional compiling code.</p>
<p>In Flex , you can pass additional constants during compile time using the  -define as  compiler argument. Following is the syntax you add to your compiler</p>
<pre>
<pre class="brush: java; title: ; notranslate">

-define=NAMESPACE::variable,value
</pre>
</pre>
<p>Where the namespace can be anything like DEBUG , RELEASE and value of the variable can be Boolean, String, or Number, or an expression that can be evaluated in  ActionScript at compile  time.In the below example we are going to create a namespace DEBUG and pass the variable insertCode as BooleanOnce you have passed the variable as compiler argument this can be further used in the flex code using&lt;/p&gt;</p>
<pre>
<pre class="brush: java; title: ; notranslate">DEBUG::insertCode</pre>
</pre>
<p>In flex to allow a block</p>
<pre>
<pre class="brush: java; title: ; notranslate">
    { 

    }
 </pre>
</pre>
<p>to be complied or not is decided by the  evaluating expression before the block. If the expression evaluated to be true the block is add to the compile code</p>
<pre>
<pre class="brush: java; title: ; notranslate">

expression{

}
</pre>
</pre>
<p>Below is the example showing how I use conditional compiling to speedup the application development. Click on this link  <a href="http://xebee.xebia.in/wp-content/uploads/2010/10/ConditionalCompiling.zip">ConditionalCompiling</a> to download the project and check it out.</p>
<p>Following is the video demonstrating the use of conditional compiling</p>
<p>Video tutorial <a href="http://xebee.xebia.in/wp-content/uploads/2010/10/Flex_Conditional_Compiling.swf">Flex_Conditional_Compiling</a></p>
<p>Please do let me know your reviews for the blogs.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/12/flex-increase-your-productivity-while-working-on-a-bigger-application/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Seam-ing Flex for Cairngorm Lovers</title>
		<link>http://xebee.xebia.in/2010/10/11/seam-ing-flex-for-cairngorm-lovers/</link>
		<comments>http://xebee.xebia.in/2010/10/11/seam-ing-flex-for-cairngorm-lovers/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 16:07:31 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5610</guid>
		<description><![CDATA[Seam, Flex, Flamingo, Cairngorm - Looking for a combination of these techie stuff. In this blog, i will talk about how to write Flamingo-specific code using Cairngorm. Talking about these four technologies individually – Flex – SDK released by Adobe Systems for the development and deployment of cross-platform RIA. Seam – Web application framework developed [...]]]></description>
			<content:encoded><![CDATA[<p>Seam, Flex, Flamingo, Cairngorm - Looking for a combination of these techie stuff. In this blog, i will talk about how to write Flamingo-specific code using Cairngorm. Talking about these four technologies individually –</p>
<p><a href="http://www.adobe.com/products/flex/?sdid=GXZOB" target="_blank"><span style="text-decoration: underline;">Flex</span></a> – SDK released by Adobe Systems for the development and deployment of cross-platform RIA.</p>
<p><a href="http://seamframework.org/" target="_blank"><span style="text-decoration: underline;">Seam</span></a> – Web application framework developed by JBoss.</p>
<p><a href="http://www.exadel.com/web/portal/flamingo" target="_blank"><span style="text-decoration: underline;">Flamingo</span></a> – Integration library and framework for building Flex/JavaFX based user interfaces for your JBoss Seam/Spring Framework applications.</p>
<p><a href="http://opensource.adobe.com/wiki/display/cairngorm/Cairngorm" target="_blank"><span style="text-decoration: underline;">Cairngorm</span></a> – Open source framework for application architecture in Adobe Flex.</p>
<p>Writing code in Flex as per Cairngorm would not  be an alarming task, unless it includes Flamingo's API. Flamingo allows  your Flex application to interact with Seam. We use RemoteObject class  in Flex to call JAVA methods on the server-side. Giving it a proper  destination allows a Flex application to talk to Java methods (that  obviously requires some more configurations). Unfortunately routine  RemoteObject is not a good option to choose while talking to Seam.  Before presenting the 'good' option lets try to understand why we need  something more that a RemoteObject. Seam based applications are not just  simple Java files, but they have a concept of Session-based objects.</p>
<p><em><span id="more-5610"></span></em>Flamingo actually extends RemoteObject, and make it's own – 'SeamRemoteObject'. Lets have a look at it:</p>
<pre class="brush: java; title: ; notranslate">
public dynamic class SeamRemoteObject extends RemoteObject {

public override function getOperation(name:String):AbstractOperation {
    var o:Object = _operations[name];
    var op:AbstractOperation = (o is AbstractOperation) ? AbstractOperation(o) : null;
    if (op == null)
        {
           op = new SeamOperation(this, name);
           _operations[name] = op;
           op.asyncRequest = asyncRequest;
        }
    return op;
    }
}
</pre>
<p>If you look at 'getOperation', you can sense what Flamingo does. Flamingo override this method and make the simple operation as a 'SeamOperation'. Now here comes the advantage. SeamOperation overrides the 'invoke' method and returns a seam-specific IMessage and AsyncToken object.</p>
<pre class="brush: java; title: ; notranslate">
mx_internal override function invoke(msg:IMessage, token:AsyncToken=null):AsyncToken {
    msg.headers[CONVERSATION_TAG] = SeamRemoteObject.getConversationId();
    return super.invoke(msg, token);
}
</pre>
<p>As we can see, 'msg' stores the conversation id through SeamRemoteObject. Also, inside the constructor of the same class, they add an listener for handling the Result:</p>
<p>Inside the result handler, SeamRemoteObject then call it's static method, 'setConversationId()' -</p>
<pre class="brush: java; title: ; notranslate">
SeamRemoteObject.setConversationId(event.message.headers[CONVERSATION_TAG] != null ? event.message.headers[CONVERSATION_TAG] : &quot;&quot;);
</pre>
<p>Getting back to Flex – The main classes that we need to focus upon are Services and Delegate. As per Cairngorm, 'service' class should contain the server side calls. While using Flamingo, instead of Flex's RemoteObject, we would use SeamRemoteObject to make the call. So the code would be -</p>
<pre class="brush: java; title: ; notranslate">
&lt;flamingo:SeamRemoteObject id=&quot;seamRemoteObject&quot;
    	destination=&quot;destination&quot;/&gt;
</pre>
<p>Don't forget to include the namespace for flamingo.</p>
<p>That's all you need to do in Services class, now coming to Delegate class – As usual, you would have a public method inside, where you would call the Java method. We can have a variable of type RemoteObject, and instantiate it in the constructor. Writing the next step as a part of cairngorm-routine,</p>
<pre class="brush: java; title: ; notranslate">
this.service = ServiceLocator.getInstance().getRemoteObject(&quot;seamRemoteObject&quot;);
</pre>
<p>Now if you look carefully at the above line, ServiceLocator.getInstance().getRemoteObject() would return a value of type SeamRemoteObject, but our variable 'service' is of type RemoteObject. To avoid the 'known' error, we just need to typecast the return value of type RemoteObject. The code would be -</p>
<pre class="brush: java; title: ; notranslate">
this.service =  RemoteObject(ServiceLocator.getInstance().getRemoteObject(&quot;seamRemoteObject&quot;));
</pre>
<p>You can then call the Java method through the 'service' variable -</p>
<pre class="brush: java; title: ; notranslate">
var token:AsyncToken = service.javaMethod();
token.addResponder(responder);
</pre>
<p>After this, you can carry with the normal Cairngorm procedure, i.e. control would reach either the result/fault inside the Command class.</p>
<p>I know it's a vast topic to discuss, so feel free to pour in your comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/11/seam-ing-flex-for-cairngorm-lovers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FLEX: Modular Application Development Using Cairngorm Architecture</title>
		<link>http://xebee.xebia.in/2010/10/11/flex-modular-application-development-using-cairngorm-architecture/</link>
		<comments>http://xebee.xebia.in/2010/10/11/flex-modular-application-development-using-cairngorm-architecture/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 12:51:26 +0000</pubDate>
		<dc:creator>Karan Nangru</dc:creator>
				<category><![CDATA[Cairngorm]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flex Architectures]]></category>
		<category><![CDATA[Flex Module]]></category>
		<category><![CDATA[cairngorm]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5590</guid>
		<description><![CDATA[Delimiting the scope of work involved in merging Cairngorm based Flex Modules and Applications.....]]></description>
			<content:encoded><![CDATA[<p>Over the past few years, Cairngorm architecture has been hugely embraced for developing enterprise Flex applications. While there are a lot of sources available online that demonstrate building flex applications using Cairngorm Architecture, not many serve the cause if you intend to develop <em>Modular Flex Applications using Cairngorm Architecture.</em></p>
<p><strong>Brief description of Flex Modules:</strong><br />
<em>Flex Modules are code functionality compiled to dynamically-loadable SWF files that can be loaded and unloaded by an application at run-time.<br />
Modules let you split your application into several pieces, or modules. The main application, or loader, can dynamically load other modules that it requires, when it needs them. It does not have to load all modules when it starts, nor does it have to load any modules if the user does not interact with them. </em></p>
<p><em><span id="more-5590"></span><br />
</em></p>
<p><strong>Pictorial description of Cairngorm Architecture:</strong></p>
<div id="attachment_29" class="wp-caption alignnone" style="width: 624px"><a href="http://karannangru.files.wordpress.com/2010/10/cairngormarchitecture.png"><img class="size-full wp-image-29" title="CairngormArchitecture" src="http://karannangru.files.wordpress.com/2010/10/cairngormarchitecture.png" alt="Cairngorm Architecture" width="614" height="446" /></a><p class="wp-caption-text">Cairngorm Architecture</p></div>
<p><em>Consider the following scenario: </em>Your team is working on a flex project that is part of the bigger picture(a baseline Flex Application). You might develop your project using an 'independent cairngorm architecture(One that does not interact with the bigger picture)'. <em>Concisely, you are developing a flex module that will be called from a flex application.</em><br />
In such scenarios, if the module does not have much dependency on the parent application then the module-application integration is many a times postponed till the module starts bearing the fruits, thereby delaying the bitter task of merging architectures(This should generally be a task that should be initiated as soon as you analyze the module design).</p>
<p><strong>While merging Flex Modules and Application that are independently designed using Cairngorm Architecture, following classes should be paid attention to and handled as follows:</strong></p>
<ul>
<li><em>Controller</em>:</li>
</ul>
<p><em>'The Controller is the most sophisticated part of the Cairngorm architecture. The Controller layer is implemented as a singleton FrontController. The FrontController instance, which receives every View-generated event, dispatches the events to the assigned Command class based on the event's declared type.'</em><br />
Modules can use the controller of the base class. In such a case, all commands of the module need to be registered with the main controller at the time of module load, and, should thereby be removed when the module is unloaded.</p>
<pre class="brush: java; title: ; notranslate">
package xyz
{
import com.adobe.cairngorm.control.FrontController;
import mx.collections.ArrayCollection;
import .......control.*;
import .......commands.*;
import .......CommandDesc;

public class BaseApplicationController extends FrontController
{
public function BaseApplicationController()
{
initialiseCommands();
}

public function initialiseCommands() : void
{
//Add all the application level commands
addCommand( baseEventName1, baseCommandClass1 );
addCommand( baseEventName2, baseCommandClass2 );
addCommand( baseEventName3, baseCommandClass3 );
addCommand( baseEventName4, baseCommandClass4 );

}

//Add all module level commands
public function addCommands(commandList:ArrayCollection):void{
for(var i:int=0;i
var commDes:CommandDesc =commandList.getItemAt(i) as CommandDesc;
this.addCommand(commDes.getEventName(),commDes.getCommand());
}
}

//Remove all module level commands
public function removeCommands(commandList:ArrayCollection):void{
for(var i:int=0;i
var commDes:CommandDesc =commandList.getItemAt(i) as CommandDesc;
this.removeCommand(commDes.getEventName());
}
}

}
}
</pre>
<p>Where CommandDesc.as contains the module level event name and the corresponding Command class:</p>
<pre class="brush: java; title: ; notranslate">
package abc
{
	import com.adobe.cairngorm.commands.Command;

	public class CommandDesc
	{
		private var eventName:String;
		private var command:Class;

		public function getEventName():String{
			return eventName;
		}
		public function setEventName(eventName:String):void{
			this.eventName = eventName;
		}
		public function getCommand():Class{
			return command;
		}
		public function setCommand(command:Class):void{
			this.command = command;
		}
	}
}
</pre>
<ul>
<li><em>Model:</em></li>
</ul>
<p><em>'In a Cairngorm Model, related data are stored in Value Objects (VOs), while simple variables can be stored as direct properties of the ModelLocator class. A static reference to the ModelLocator singleton instance is used by the View layers to locate the required data.'</em><br />
The modelLocator directive is such,that, its always better not to merge modelLocator implementations of the module and the application (since modelLocator contain a lot of contextual information)</p>
<p><em>Following is a change that needs to be incorporated on the module side, as well as the application side:</em><br />
Since modelLocator is singleton, we should create a modelLocator implementation in the interface gateway(generally compiled as a SWC) that is used for the application-modules interaction. Since this interface is used by the application SWF to communicate with all module's SWF that it needs to use, a singleton modelLocator in the interface is maintainable and can contain various modules and the application specific modelLocator. (I will soon be posting a blog on modular interaction using SWC gateway interfaces).</p>
<p>Interface level ModelLocator that should implement com.adobe.cairngorm.model.ModelLocator:</p>
<pre class="brush: java; title: ; notranslate">
package externalInterface
{
	import com.adobe.cairngorm.model.ModelLocator;

	public class InterfaceModelLocator implements com.adobe.cairngorm.model.ModelLocator
	{
		public static var interfaceModelLocator:InterfaceModelLocator;
		private var _modelMap:Object = new Object();

		public function addModel(key:String, model:Object):void{
			_modelMap[key] = model;
		}

		public function getModel(key:String):Object{
			return _modelMap[key];
		}

		public function deleteModel(key:String):void{
			_modelMap[key] = null;
		}

		public function InterfaceModelLocator(){
			if(interfaceModelLocator != null){
	         	throw new Error( &quot;Only one ModelLocator instance should be instantiated&quot; );
			}
		}

		public static function getInstance():InterfaceModelLocator{
	      	if ( interfaceModelLocator == null )
	      	{
	      		interfaceModelLocator = new InterfaceModelLocator();
	      	}
	      	return interfaceModelLocator;
		}
	}
}
</pre>
<p>Application level ModelLocator that should use the interface level ModelLocator:</p>
<pre class="brush: java; title: ; notranslate">
[Bindable]
public class ApplicationModelLocator extends InterfaceModelLocator
{
private static var modelLocator : ApplicationModelLocator;

public static function getInstance() : ApplicationModelLocator
{
     if ( modelLocator == null )
    {
      modelLocator = new ApplicationModelLocator();
      InterfaceModelLocator.getInstance().addModel(&quot;ApplicationLevelModelName&quot;,modelLocator);
    }

    return ApplicationModelLocator(
    InterfaceModelLocator.getInstance().getModel(&quot;ApplicationLevelModelName&quot;));
}
}
</pre>
<p>The module level ModelLocator should be coded on similar lines.</p>
<ul>
<li><em>Styles:</em></li>
</ul>
<p>css usage varies from project to project.  All CSS related changes of the application and the module could be kept in a single .css file.</p>
<ul>
<li><em>Command:</em></li>
</ul>
<p><em>'The Command class processes the event by running the Command class' execute() method, which is an ICommand interface method. The event object may include additional data if required by the developer. The execute() method can update the central Model, as well as invoke a Service class which typically involves communication with a remote server. The IResponder interface, which is also implemented by the Command class, includes onResult and onFault methods to handle responses returned from the invoked remote service.'</em></p>
<p>Commands imbibe business logic, thus should be unique.</p>
<ul>
<li><em>Module Loader :</em></li>
</ul>
<p>MXML residing in the main application and used to load the child module. This is the module wrapper that is called from the main application and handles all the module loading/unloading etc related events.</p>
<pre class="brush: java; title: ; notranslate">
xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	width=&quot;400&quot;
	height=&quot;300&quot;
	implements=&quot;..........ApplicationGateway&quot;
	xmlns:control=&quot;.......control.*&quot;
	xmlns:business=&quot;......business.*&quot;
	creationComplete=&quot;{initApp()}&quot;
	show=&quot;{loadModule()}&quot;
	&gt;

	 BaseApplicationController id=&quot;baseApplicationController&quot;/&gt;

	&lt;mx:Script&gt;
		&lt;!--[&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[--&gt;
			import mx.utils.StringUtil;
			import mx.core.Application;
			import mx.collections.ArrayCollection;
			import mx.modules.ModuleManager;
			import mx.managers.PopUpManager;
			import mx.events.CloseEvent;
			import mx.modules.Module;
			import mx.modules.IModuleInfo;
			import mx.containers.TitleWindow;
			import .............SampleGateway;   // SampleGateway is the communication interface
			import mx.events.ModuleEvent;

			protected var _moduleInfo:IModuleInfo;
			public var moduleTitleWindow:ModuleTitleWindow;
		      private var sampleGateway:SampleGateway = null;

		private function initApp():void {
		    _moduleInfo = ModuleManager.getModule(&quot;YourModule.swf&quot;);
		   _moduleInfo.addEventListener(ModuleEvent.READY, onModuleReady);
		   _moduleInfo.addEventListener(ModuleEvent.UNLOAD, onModuleUnload);
		}

        	private function loadModule():void {
	           _moduleInfo.load();
        	}

	        private function onModuleReady (e:ModuleEvent):void {
	            var moduleInfo:IModuleInfo = e.currentTarget as IModuleInfo;
	            var module:Module =  (moduleInfo.factory.create () as Module)
	            sampleGateway = module as SampleGateway;
	            sampleGateway.setApplicationGateway(this);

//THE NEXT LINE IS A TYPICAL IMPLEMENTATION FOR CREATING STATIC CUSTOM POPUPS
	            moduleTitleWindow = PopUpManager.createPopUp(DisplayObject(Application.application), ModuleTitleWindow, true) as ModuleTitleWindow;
	            moduleTitleWindow.addChild(module);
	            PopUpManager.centerPopUp(moduleTitleWindow);

	            var commandList:ArrayCollection = SampleGateway.getCommands();
//THE NEXT LINE ADDS ALL MODULE COMMANDS TO THE APPLICATION CONTROLLER
	            baseApplicationController.addCommands(commandList);

	       	}

	   		public function unloadModule(event:Event):void {
	    		 var cmdList:ArrayCollection;
	    		sampleGateway.cleanup();
	    		cmdList = sampleGateway.getCommands();
//THE NEXT LINE DELETES ALL MODULE COMMANDS FROM THE APPLICATION CONTROLLER
	    		baseApplicationController.removeCommands(cmdList);
	    		baseApplicationController.removeAllChildren();
	    		_moduleInfo.release();
	    		PopUpManager.removePopUp(moduleTitleWindow);
	    	}

	    	 public function onModuleUnload (e:ModuleEvent) : void {
	        }

	       public function returnToTarget(target:*):void{
	        	unloadModule(target);
	        }

		]]&gt;
	&lt;/mx:Script&gt;

&lt;/mx:Canvas&gt;
</pre>
<ul>
<li><em>Services.mxml:</em></li>
</ul>
<p>All remote objects of the application as well as the module should be declared here:</p>
<pre class="brush: java; title: ; notranslate">
RemoteObject id=&quot;applicationRemoteObject&quot;
	destination=&quot;applicationRemoteObjectJavaDelegate&quot;
	showBusyCursor=&quot;true&quot;
	result=&quot;event.token.resultHandler( event );&quot;
	fault=&quot;event.token.faultHandler( event );&quot;&gt;
 RemoteObject&gt;
 &lt;mx:RemoteObject id=&quot;moduleRemoteObject&quot;
	destination=&quot;moduleRemoteObjectJavaDelegate&quot;
	showBusyCursor=&quot;true&quot;
	result=&quot;event.token.resultHandler( event );&quot;
	fault=&quot;event.token.faultHandler( event );&quot;&gt;
 &lt;/mx:RemoteObject&gt;
</pre>
<ul>
<li><em>remoting-config.xml:</em></li>
</ul>
<p>All destinations pertaining to the application as well as the module level remote objects should be declared here:</p>
<pre class="brush: java; title: ; notranslate">
&lt;destination id=&quot;applicationRemoteObjectJavaDelegate&quot;&gt;
	&lt;properties&gt;
		&lt;source&gt;.....ApplicationRemoteObjectJavaDelegate&lt;/source&gt;
	&lt;/properties&gt;
&lt;/destination&gt;
&lt;destination id=&quot;moduleRemoteObjectJavaDelegate&quot;&gt;
	&lt;properties&gt;
		&lt;source&gt;.....ModuleRemoteObjectJavaDelegate&lt;/source&gt;
	&lt;/properties&gt;
&lt;/destination&gt;
</pre>
<p>Post the above mentioned considerations, merging Cairngorm specific modules and applications should be a hassle free process......</p>
<p>Happy Flexing !!</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/11/flex-modular-application-development-using-cairngorm-architecture/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flex : Talking to the outside world</title>
		<link>http://xebee.xebia.in/2010/10/09/flex-talking-to-the-outside-world/</link>
		<comments>http://xebee.xebia.in/2010/10/09/flex-talking-to-the-outside-world/#comments</comments>
		<pubDate>Sat, 09 Oct 2010 11:59:20 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[flex context menu]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5509</guid>
		<description><![CDATA[Some of the requirements from Customer - Customer : I dont want to add customer support built in the application but somehow would like to give a link to Customer : It's a little technical for the end user to understand. Should we really have this feature? I wanna try keeping it simple, Some familiar [...]]]></description>
			<content:encoded><![CDATA[<p>Some of the requirements from Customer -</p>
<p><strong>Customer :</strong> I dont want to add customer support built in the application but somehow would like to give a link to<br /> <strong> Customer :</strong> It's a little technical for the end user to understand. Should we really have this feature? I wanna try keeping it simple,</p>
<p>Some familiar voices  from developer world --<br /> <strong> Developer :</strong> Can you please attach the debug logs<br /> <strong> Developer :</strong> Please use this utility to check if it's a problem with your bandwidth.</p>
<p>While developing a Standalone Flex application following are some of the requirements that may come along</p>
<ul>
<li>Opening a Customer page</li>
<li>Utility to report bug</li>
<li>Advance Features for power users</li>
<li>If  its a media extensive application Utility to test the bandwidth</li>
</ul>
<p><span id="more-5509"></span></p>
<p>All the above requires talking to the outside world from your flex  application. These are good to have features. One of the approach would be to have a help page where links to all these utilities is present. But this still is not a elegant solution.  Flex Context menu is one of the best ways to introduce these features.</p>
<p>Following are the advantages of using the Flex Context Menu</p>
<ul>
<li>It does not become part of your core UI.</li>
<li>Its quick and easily available using right click.</li>
</ul>
<p>One of the classic examples is the way youtube does uses it. Notice the picture  you can now easily report a playback issue.</p>
<p><a rel="attachment wp-att-5510" href="http://xebee.xebia.in/2010/10/09/flex-talking-to-the-outside-world/paint/"><img class="alignnone size-full wp-image-5510" title="paint" src="http://xebee.xebia.in/wp-content/uploads/2010/10/paint.png" alt="" width="268" height="256" /></a></p>
<p>Earlier utililty like copy embed html code were only available on YouTube site.  Now if you want to embed the youtube video you can just right click and get the embed code. Its much faster and easier than previous approach.</p>
<p>YouTube also provide a link to take a speed test. Some of the Flex multimedia application do have a constraint on the minimum required bandwidth. Bandwidth being one of the volatile parameters , it a good idea to have a link to Bandwidth checker. This way whenever the user is in doubt can easily check the bandwidth if he faces any problem using the application</p>
<p>So lets see a small demo of how to use context menu.Assume that your application provides few themes that you can toggle , it would be a good idea to expose functionality using a menu items.Attach are the  <a rel="attachment wp-att-5519" href="http://xebee.xebia.in/2010/10/09/flex-talking-to-the-outside-world/flexcontextmenu/">source files</a> to the demo application.</p>
<p>Following link is a demo of<br /> <a href="http://xebee.xebia.in/wp-content/uploads/2010/10/2010-10-09_1852.swf">How to use context menu video</a></p>
<p>Please do let me know your comments, Thanks</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/09/flex-talking-to-the-outside-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data Visualization made better in Adobe Flex</title>
		<link>http://xebee.xebia.in/2010/10/08/flex-visualizer-kaplabs/</link>
		<comments>http://xebee.xebia.in/2010/10/08/flex-visualizer-kaplabs/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 04:14:19 +0000</pubDate>
		<dc:creator>Gaurav Srivastava</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5054</guid>
		<description><![CDATA[Recently i came across a requirement of showing the grid-based data in a more fancy way, probably in a way Flex is known for. There were some problems in displaying a grid-based data. Every cell of a Flex datagrid is basically a label. But what if we want to show an employee's complete information (picture, [...]]]></description>
			<content:encoded><![CDATA[<p>Recently i came across a requirement of showing the grid-based data in a more fancy way, probably in a way Flex is known for. There were some problems in displaying a grid-based data. Every cell of a Flex datagrid is basically a label. But what if we want to show an employee's complete information (picture, full name, reporting structure, current/past project details)? It's true that we can have item-renderers to show this. But for heavy datasets, will it really be a good option from usability perspective?</p>
<p>Another problem i can think of - Consider a project lead wants to see his/her team. We always have an option to double click on any cell of the datagrid to view the further data, and a back button to return to the original. But by simply giving an expand/collapse button on the data, aren't we making the user experience better?<br />
<span id="more-5054"></span></p>
<p>To achieve this and many such use cases, I found a component that suit best for my requirement. KAPLABS's Visualizer is the component i will be talking about. It's a powerful component that provides you with a vanilla implementation of all fancy stuff that you would want. Built in features, like zoom-in/zoom-out support, customizable nodes, expand/collapse buttons and many more adds cherry on the top.</p>
<p>To look at the official website, please follow this link – <a href="http://lab.kapit.fr/display/visualizer/Visualizer" target="_blank">http://lab.kapit.fr/display/visualizer/Visualizer</a>. In this blog, I will be sharing my experiences with this component.</p>
<p>To get started, download the swc from the official site.</p>
<p>Apart from simply displaying the data in this component, I will be sharing my ideas on the following areas-</p>
<ul>
<li>Customize the result object on XML grounds.</li>
<li>Show a close button on selective nodes.</li>
</ul>
<p>To start with, the first story which we took was to populate the component with the actual data.</p>
<p>(Did you just see the word 'story'? Yes, you guessed it right – We are Agile!). The actual data was a result of some remote-service, which was returned as a collection in Flex. Had it been the normal ArrayCollection for Flex, I could have simply passed it to the component. But as we all know, we generally get complex objects from the back-end, which may or may not be component-friendly. So to make it easy, try converting that object into simple XML or ArrayCollection. If you are looking for a helping-hand on this, then here is a tip.</p>
<p>Assuming the variable 'resultObject' holds your result, just run a for each loop on it.</p>
<pre class="brush: java; title: ; notranslate">

for each(var obj:Object in resultObject) {
// instantiate a VO which will be mapped through a RemoteClass metatag.
// start appending childs to your XML.
}
</pre>
<p>I faced another issue where I was asked to center any node whenever user clicks a link on the node. By centering the node I mean, to show immediate parents/children of the selected node. Well your life will be easy if you are playing around with XML-typed data-structure. Again a for-each loop with some if-else can get you the result. This is just a tip, which might not work if your requirement is different. Feel free to buzz me if you are stuck.</p>
<p>Going further, there was a 'close' button to be placed on some of the nodes. Showing a close button on all nodes was pretty easy. You can just provide a function to property named 'multimediaFunction' wherein you can define a renderer for the component.</p>
<p>Something like below-</p>
<p>Inside customNodeRendering, we can have the renderer-</p>
<pre class="brush: java; title: ; notranslate">

private function customNodeRendering(data:Object):IListItemRenderer {
var visualizerRenderer:VisualizerRenderer = new VisualizerRenderer();
visualizerRenderer.data = data;
return visualizerRenderer;
}
</pre>
<p>Now my requirement here was to display a close button on some of the nodes. My life is already easy as I am playing with XML-typed structure. I just need to place a if-else block inside my renderer that will check for the value in the self-made XML. Something like,</p>
<pre class="brush: java; title: ; notranslate">

private function customNodeRendering(data:Object):IListItemRenderer {
var visualizerRenderer:VisualizerRenderer = new VisualizerRenderer();
visualizerRenderer.data = data;
if(data['@showCloseButton']) {
//do something
}
else {
//do something
}
return visualizerRenderer;
}
</pre>
<p>Leaving you to play around with Visualizer. Feel free to get back, in case you are tired of googling.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/08/flex-visualizer-kaplabs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Web Socket Communication using jWebSocket</title>
		<link>http://xebee.xebia.in/2010/10/05/web-socket-communication-using-jwebsocket/</link>
		<comments>http://xebee.xebia.in/2010/10/05/web-socket-communication-using-jwebsocket/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 04:27:21 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[jWebSockets]]></category>
		<category><![CDATA[Web Sockets]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5130</guid>
		<description><![CDATA[Web Socket has been introduced in HTML5 to enable  full duplex communication with minimum network traffic and latency. I was working on a PoC on HTMl5 Web Socket. In this blog I am sharing my experience about working with jWebSocket to get the basic WebSocket communication running. jWebSocket is pure Java/JavaScript based implementation for implementing [...]]]></description>
			<content:encoded><![CDATA[<p>Web Socket has been introduced in HTML5 to enable  full duplex communication with minimum network traffic and latency. I was working on a PoC on HTMl5 Web Socket. In this blog I am sharing my experience about working with jWebSocket to get the basic WebSocket communication running. jWebSocket is pure Java/JavaScript based implementation for implementing Web Socket communication.  After reading this blog the readers should be able to send asynchronous request from client through Web Socket and get response from the server. This blog assumes that readers have basic knowledge of HTML5 Web Sockets</p>
<p>HTML 5 Web Socket specification defines an API that enables  full duplex communication over one (TCP) socket. Before web sockets the server could respond only on receiving a request from a web client. To overcome this limitation the common workarounds are polling, long polling and comet based solutions. HTML 5 Web Sockets comes as an inbuilt support for bi-directional communication which promises to be highly scalable due to reduced network traffic and latency.<br />
<span id="more-5130"></span></p>
<p>In this blog I have used  jWebSocket the Web Socket implementation for Java/JS. The first step is to download the required distribution files from <a title="http://jwebsocket.org/" href="http://jwebsocket.org/" target="_blank">jWebSocket.org </a> and follow the steps for configuration.</p>
<p>To get the Web Socket communication running both client and server side coding efforts are involved. I will deal with both of them.  Let us start with the client side code</p>
<p>The jWebSocket distribution comes with jWebSocket.js which needs to be included in your view file. Basically the jWebSocket.js exposes the JS implementation for WebSocket. The following steps are to be followed to make the client interact with the server through Web Sockets.</p>
<ol>
<li>Create an instance of jWebSocketJSONClient.</li>
<li>Create a WebSocket connection.</li>
<li>Send/Receive tokens.</li>
</ol>
<p>Step 1: Create an instance of jWebSocketJSONClient: jWebSocket exposes clients like jWebSocketJSONClient, jWebSocketCSVClient, jWebSocketXMLClient. For our example we will use jWebSocketJSONClient. As a first step I have written initWebSocket function which checks if  the browser supports HTML5's WebSocket and only then creates an instance of the jWebSocketJsonClient.</p>
<pre class="brush: xml; title: ; notranslate">
var jWebSocketClient = null;
function initWebSocket(){
if( jws.browserSupportsWebSockets() ) {
jWebSocketClient = new jws.jWebSocketJSONClient();
} else {
var lMsg = jws.MSG_WS_NOT_SUPPORTED;
}
}
</pre>
<p>Step 2: Create a WebSocket connection - Once it is ascertained that the browser supports Web Sockets and the jWebSocketClient is created then logon() function of the client can be invoked to create a physical WebSocket connection between the client and the server. The function takes the url, username, password and the callback functions as the argument.</p>
<ol>
<li>url -  represents the end-point to which you wish to connect. Please note that the url starts with ws:// and not http:// as the Web Socket connection is established using the Web Socket protocol. Web Socket protocol is an upgrade over HTTP protocol using the same underlying TCP/IP connection. ws:// and wss:// prefix are proposed to indicate a WebSocket and a secure WebSocket connection, respectively.</li>
<li>username / password - The user details can be configured in jWebSocket.xml which is packages in conf folder of the jWebSocket server deployment directory. All the authentication details by default will be validated against this file.</li>
<li>callback functions -  <a title="http://dev.w3.org/html5/websockets/#websocket" href="http://dev.w3.org/html5/websockets/#websocket" target="_blank">WebSocket interface</a> has attribute functions onOpen, onClose, onError and onMessage. Whenever we create a Web Socket connection we can provide callbacks for the Web Socket connection open and close events, an error event and a message receive event. When ever any of these events occur the corresponding call backs will get called allowing you to handle the situation.</li>
</ol>
<pre class="brush: xml; title: ; notranslate">
function logon(){
var lRes = jWebSocketClient.logon( &quot;ws://hostname|localhost:8787&quot;,
&quot;username&quot;, &quot;password&quot;, {
// OnOpen callback
OnOpen: function( aEvent ) {
log( &quot;jWebSocket connection established.&quot; );
},
// OnMessage callback
OnMessage: function( aEvent, aToken ) {
log( &quot;jWebSocket '&quot; + aToken.type + &quot;' token received, full message: '&quot;
+ aEvent.data);
},
// OnClose callback
OnClose: function( aEvent ) {
log( &quot;jWebSocket connection closed.&quot; );
}
});
}
</pre>
<p>Step 3: Send/Receive tokens - Once the connection request is authenticated and the socket connection is established both the client and server can send information to each other whenever they want.  To send token from the client  just create a token with namespace and type. Remember that the client being used  to send data is JSON client and therefore the token should follow the JSON format. Once the token is ready, invoke the send method of  the JSON client which takes token and the callback function (which will be invoked if the server sends some response) as arguments.</p>
<pre class="brush: xml; title: ; notranslate">
function sampleListener() {
if( jWebSocketClient.isConnected() ) {
log(&quot;sending message to jwebsocket&quot;);
var lToken = {
ns: &quot;my.namespace&quot;,
type: &quot;getInfo&quot;
};
jWebSocketClient.sendToken( lToken,	{
OnResponse: function( aToken ) {
log(&quot;Server responded: &quot;
+ &quot;vendor: &quot; + aToken.vendor
+ &quot;, version: &quot; + aToken.version
);
}
});
} else {
log( &quot;Not connected.&quot; );
}
}
</pre>
<p>Let us look into the server side code, all the requests related to Web Sockets are handled by Web Socket server. The following steps are required to be followed to make the server Web Socket enabled</p>
<ol>
<li>Start the jWebSocket server and register a JWebSocketTokenServerListener with the jWebSocketServer</li>
<li>Create a Listener implementation of JWebSocketTokenServerListener and provide the implementation (this is the listener which was registered with the server int the previous step)</li>
</ol>
<p>Step 1 : Start the jWebSocket server and register a JWebSocketTokenServerListener with the jWebSocketServer :  When the application starts up in the application server it has to be ensured that the jWebSocket server also starts up. To ensure this a listener of type ServletContextListener can be configured in web.xml. I have created a JWSContextListener and configured the listener in web.xml as below.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;listener&gt;
         &lt;description&gt;ServletContextListener&lt;/description&gt;
         &lt;listener-class&gt;com.checkList.web.contextUtils.JWSContextListener&lt;/listener-class&gt;
&lt;/listener&gt;
</pre>
<p>jWebSocketServer is started in the <em>contextInitialized</em> method of JWSContextListener. To be able to receive tokens and resopond to certain events in the jWebSocketServer a listener<em> JWebSocketListener</em> is registered to the token server. The listener registered to the server will listen to the events occurring in the sever and the corresponding methods will get called. In jWebSocket.xml in conf folder of the jWebSocket server deployment you can specify the server types to be instantiated for jWebSocket. Each server type has a unique id. By default <em> token server</em> and<em> custom server</em> are defined with ids as ts0 and cs0 respectively. That is why there is reference to ts0 in "<em>TokenServer tokenServer = (TokenServer)JWebSocketFactory.getServer("ts0")</em>;."</p>
<pre class="brush: java; title: ; notranslate">
&lt;pre&gt;public class JWSContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// start the jWebSocket server sub system
JWebSocketFactory.start(&quot;&quot;);
TokenServer tokenServer = (TokenServer)JWebSocketFactory.getServer(&quot;ts0&quot;);
if(tokenServer !=null){
tokenServer.addListener(new JWebSocketListener());
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
JWebSocketFactory.stop();
}
}
</pre>
<p>Step 2 : Create a Listener implementation of JWebSocketTokenServerListener and provide the implementation : The JWebSocketListener implements the WebSocketTokenListener and provides the implementation. Once a token is received by the client the processToken method will be invoked. The other life cycle methods will similarly respond to the corresponding events. If we further look into the processToken() method, the WebSocketServerTokenEvent is injected as an argument. WebSocketServerTokenEvent  has a <em>createResponse </em>method which takes token as argument and creates a response token. Once the responseToken is ready, it is sent using the sendToken method of WebSocketServerTokenEvent object. This is how server sends back the response.</p>
<pre><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">
<pre class="brush: java; title: ; notranslate">
public class JWebSocketListener implements WebSocketServerTokenListener{
@Override
public void processToken(WebSocketServerTokenEvent serverTokenEvent, Token token) {
// here you can interpret the token type sent from the client according to your needs.
String tokenNameSpace = token.getNS();
String tokenType = token.getType();
// check if token has a type and a matching namespace
if (tokenType != null &amp;&amp; &quot;my.namespace&quot;.equals(tokenNameSpace)) {
// create a response token
Token tokenResponse = serverTokenEvent.createResponse(token);
if (&quot;getInfo&quot;.equals(tokenType)) {
// if type is &quot;getInfo&quot; return some server information
tokenResponse.setString(&quot;vendor&quot;, &quot;JWebSocket&quot;);
tokenResponse.setString(&quot;version&quot;, &quot;.10&quot;);
tokenResponse.setString(&quot;copyright&quot;, &quot;JWebSocket.org&quot;);
tokenResponse.setString(&quot;license&quot;, &quot;No Liscense&quot;);
tokenResponse.setString(&quot;Demo Text&quot;, &quot;This is demo text&quot;);
} else {
// if unknown type in this namespace, return corresponding error message
tokenResponse.setString(&quot;code&quot;, &quot;-1&quot;);
tokenResponse.setString(&quot;msg&quot;, &quot;Token type '&quot; + tokenType + &quot;'
not supported in namespace '&quot; + tokenNameSpace + &quot;'.&quot;);
}
serverTokenEvent.sendToken(tokenResponse);
}
}

@Override
public void processClosed(WebSocketServerEvent arg0) {
}

@Override
public void processOpened(WebSocketServerEvent event) {
System.out.println(&quot;***********Client '&quot; + event.getSessionId() +
&quot;' connected.*********&quot;);
}

public void sendPacket(){
}

@Override
public void processPacket(WebSocketServerEvent arg0, WebSocketPacket arg1) {
}

}
</pre>
<p> Please refer to following links to read more about Web Socket</pre>
<ol>
<li><a title="http://www.websockets.org/about.html" href="http://www.websockets.org/" target="_blank">http://www.websockets.org</a></li>
<li><a title="http://dev.w3.org/html5/websockets/" href="http://dev.w3.org/html5/websockets/" target="_blank">http://dev.w3.org/html5/websockets/</a></li>
</ol>
<p>Please refer to following link to read more about jWebSocket</p>
<ol>
<li><a title="http://jwebsocket.org/" href="http://jwebsocket.org/" target="_blank">http://jwebsocket.org/</a></li>
</ol>
<p>In my next blog, I will discuss how to implement the data push from the server.</p>
<p></span></pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/10/05/web-socket-communication-using-jwebsocket/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>JavaFx clean code</title>
		<link>http://xebee.xebia.in/2010/09/28/add-more-to-javafx-clean-code-manage-components-in-gui/</link>
		<comments>http://xebee.xebia.in/2010/09/28/add-more-to-javafx-clean-code-manage-components-in-gui/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 05:02:03 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[clean code]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=5060</guid>
		<description><![CDATA[The declarative nature of JavaFx code often results in an ugly, untidy and lengthy files which are quite overwhelming at times. It’s very easy to let things written-on in JavaFX script unless it gets impossible to follow such deeply nested code as it is not easy to figure out what goes with what. Though we [...]]]></description>
			<content:encoded><![CDATA[<p>The declarative nature of JavaFx code often results in an ugly, untidy and lengthy files which are quite overwhelming at times.<br />
It’s very easy to let things written-on in JavaFX script unless it gets impossible to follow such deeply nested code as it is not easy to figure out what goes with what.</p>
<p>Though we can also adhere to the principles of clean code by keeping methods small and proper naming, at the same time we would like to keep a code which is not only more readable but also reflects the structure of the GUI.</p>
<p><span id="more-5060"></span></p>
<p>Let’s take an example of the most commonly used components like containers or layout components eg. VBox and HBox.<br />
Since we know that in JavaFx, these components do not support background styling directly, so mostly we add a rectangle at the base content and group other elements above it like:</p>
<pre class="brush: javafx; title: ; notranslate">
var stageRef1 = HBox {
    Group {
      content:
             [
              var rectRef:Rectangle
              rectRef = Rectangle {
                  x:0;
                  y:0;
                  styleClass: &quot;rect&quot;
                  width: stageRef.width * .85
                  height: stageRef.height * .85
              },
              textRef = Text {
                  content: &quot;{row},{column}&quot;
                  fill: Color.WHITE
                  textOrigin: TextOrigin.TOP
                  font: Font {
                      size: 24
                      style: FontStyle.BOLD
                  }, comp2, comp3...
               }
           ]
 }
</pre>
<p>another similar component in the same file lies like:</p>
<pre class="brush: javafx; title: ; notranslate">
var stageRef2 = HBox {
     Group {
       content:
             [
              var rectRef: Rectangle
              rectRef = Rectangle {x: 0;
              y : 4;
              styleClass:   &quot;rect1&quot;
              width: stageRef.width * .80
              height: stageRef.height * .80
           },
           Button {
              strong: true;
              text: &quot; Scroll &quot;;
              styleClass: &quot;button1&quot;
              layoutX: 928;
              layoutY: 80;
              action: function() {
                textScrollerRef.startScrolling();
              }
          }, comp4 ,comp5
         ...
        ]
 }
</pre>
<p>The real adhoc in the file appeared when we intended to use these type of containers at multiple places with different content (keeping the requirement of having a Rectangle + HBox/VBox combo every time).</p>
<p>Instead of repeating the declaration of these in your GUI file and growing its size, try making your custom classes even if your variable instance isn’t really doing extra but repeating itself in the file with different content.</p>
<p>For this example, first extract your rectangle component with common attributes in a different class.</p>
<pre class="brush: javafx; title: ; notranslate">
 package test.cleancode.MyRectangle;
 import javafx.scene.shape.Rectangle;

 public class MyRectangle extends Rectangle {
     var xCord: Integer = 0;
     var yCord: Integer = 0;
     var widthOfRect: Number = 100;
     var heightOfRect: Number = 50;
     var styleClassOfRect:String =”rect”;

     public function create(x:Integer, y:Integer, width:Number, height:Number):Rectangle {
         this.xCord = x;
         this.yCord = y;
         this.widthOfRect = width;
         this.heightOfRect = height;

         return Rectangle {
            styleClass: styleClassOfRect;
            x: xCord;
            y: yCord;
            width: widthOfRect;
            height: heightOfRect;
         }
      }

      public function create(): Rectangle {
            return Rectangle {
               x: xCord;
               y: yCord;
               width: widthOfRect;
               height: heightOfRect;
            }
      }

      public function setStyleClass(styleClass: String) {
          this.styleClassOfRect = styleClass;
      }
 }
</pre>
<p>then, organize your code as shown below :</p>
<pre class="brush: javafx; title: ; notranslate">

 var button = Button {
     strong: true;
     text: ” Scroll “;
     styleClass: “button1″
     layoutX: 928;
     layoutY: 80;
     action: function() {
        textScrollerRef.startScrolling();
      }
  }

var stageRef1 = HBox
    content: [comp2, comp3...]
}

var stageRef2 = HBox
    content: [comp4, comp5...]
}
</pre>
<p>And create the instances of MyRectangle with desired attributes as many times (with much shorter and cleaner way <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) :</p>
<pre class="brush: javafx; title: ; notranslate">
 var rectangle = new MyRectangle();
 hBoxBackground1 = rectangle.create(0,0,stageRef1.width * .85,stageRef1.height* .85);
 hBoxBackground1.styleClass = “rect1″;

 hBoxBackground2 = rectangle.create(0,0,stageRef2.width * .80,stageRef2.height* .80);
// no need to specify style as default will be applied
</pre>
<p>Now use the combination of above in your stage / scene or via a group likewise:</p>
<pre class="brush: javafx; title: ; notranslate">
 scene = javafx.scene.Scene {
     stylesheets: “{__DIR__}Styles.css”;
     width: UIProperties.APPLICATION_WIDTH;
     height: UIProperties.APPLICATION_HEIGHT;
     content: [hBoxBackground1 , stageRef1]
  };
</pre>
<p>Hence a judicious use of the language’s declarative nature and following a more disciplined style would definitely help developers learn and understand the language better and provide a more solid foundation for the language as a whole.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/09/28/add-more-to-javafx-clean-code-manage-components-in-gui/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating and Styling Resizable ‹input› Buttons</title>
		<link>http://xebee.xebia.in/2010/09/17/creating-and-styling-resizable-buttons/</link>
		<comments>http://xebee.xebia.in/2010/09/17/creating-and-styling-resizable-buttons/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 07:16:06 +0000</pubDate>
		<dc:creator>jthakur</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[tapestry]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4863</guid>
		<description><![CDATA[Last week I came across a new requirement in my project where tapestry is used. Project requirement: Internationalization, where language of the content, image text everything is changed as per the language selected. Client was very happy with curve edge button which also had gradient and embossed effect. These effects cannot be generated by using [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I came across a new requirement in my project where tapestry is used.</p>
<p>Project requirement:  Internationalization, where language of the content, image text everything is changed as per the language selected.</p>
<p>Client was very happy with curve edge button which also had gradient and embossed effect. These effects cannot be generated by using filter, alpha, or opacity property in CSS, which is again not browser compatible so finally the conclusion I thought was to use image.</p>
<p>Earlier the project requirement was to support two languages. So I made the button width slightly bigger which could accommodate text for both languages. But later, other two languages were added and the labels were now too long.</p>
<p>For example “Submit” in English, "Voorleggen" in Dutch, "Presentar" in Spanish ,"Soumettre" in French and so on.</p>
<p>To elaborate, here is the example of &lt;input&gt; element created button which renders according to language selected.<span id="more-4863"></span></p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="124" align="center" valign="top"><img class="alignnone size-full wp-image-4864" style="border: 0pt none;" title="101" src="http://xebee.xebia.in/wp-content/uploads/2010/09/101.png" border="0" alt="Upload fille" width="103" height="36" /></td>
<td width="160" align="center" valign="top"><img class="alignnone size-full wp-image-4866" style="border: 0pt none;" title="103-upload-dutch" src="http://xebee.xebia.in/wp-content/uploads/2010/09/103-upload-dutch1.png" border="0" alt="Upload file" width="143" height="36" /></td>
<td width="142" align="center" valign="top"><img class="alignnone size-full wp-image-4867" style="border: 0pt none;" title="104-upload-espanol" src="http://xebee.xebia.in/wp-content/uploads/2010/09/104-upload-espanol.png" border="0" alt="Upload file" width="125" height="36" /></td>
<td width="146" align="center" valign="top"><img class="alignnone size-full wp-image-4868" style="border: 0pt none;" title="105-upload-netherlands" src="http://xebee.xebia.in/wp-content/uploads/2010/09/105-upload-netherlands.png" border="0" alt="Upload file" width="130" height="38" /></td>
</tr>
<tr>
<td width="124" align="center" valign="top">English</td>
<td width="160" align="center" valign="top">Deutsch</td>
<td width="142" align="center" valign="top">Español</td>
<td width="146" align="center" valign="top">Nederlands</td>
</tr>
</tbody>
</table>
<p>Creating one time style is easy to use throughout the project. Then we do not need to create each button image, which increases the processing time and bandwidth in loading a site. Also it is not flexible enough to stretch according to label of the button and is very light in size as single image is used which is reused for different button.</p>
<p>I tried to Google but hardly could find any solution for &lt;input&gt; element button. The most of the solution were for &lt;button&gt; element and &lt;a  href&gt; element but could not find anything about &lt;input&gt; element submit button. &lt;input/&gt; tag does not have close tag where we can reside &lt;span&gt; or &lt;p&gt; in it and assigned class to it like we do for &lt;button&gt; or for &lt;a  href&gt;.</p>
<p>I found by using</p>
<pre class="brush: xml; title: ; notranslate">&lt;button&gt;&lt;span&gt;&lt;span&gt;Label&lt;/span&gt;&lt;/span&gt;&lt;/button&gt;</pre>
<p>or</p>
<pre class="brush: xml; title: ; notranslate"> &lt;a href=&quot;#&quot;&gt;&lt;span&gt;submit&lt;/span&gt;&lt;/a&gt;</pre>
<p>We can create and style resizable buttons. But in tapestry when we have to provide two action “Submit” and “Cancel” we cannot use &lt;button&gt; html element. We were using t:id=”…” t:value=”…” t:type=”…”  which is not supported to perform two action on a form.  In &lt;button&gt; tag we are using &lt;span&gt; tag to show the label which will appear on button, as the &lt;button&gt; tag has open and close tag, like</p>
<pre class="brush: xml; title: ; notranslate">&lt;button&gt;&lt;span&gt;&lt;span&gt;Label&lt;/span&gt;&lt;/span&gt;&lt;/button&gt;</pre>
<p>Using sliding doors we can have buttons flexible, where background image expand with the size of the button's text. I will be using sliding doors technique where two complementing images creating the illusion of a single, stretching image to create my &lt;input&gt; button.</p>
<p>Here is the way I created my &lt;input&gt; button. You can also download the demo file from <a rel="attachment wp-att-5036" href="http://xebee.xebia.in/2010/09/17/creating-and-styling-resizable-buttons/input-buttonfile/">here</a></p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- This div is container of  the buttons, if you want to place it on right or left side just assign new css class which float it to right/left --&gt;
&lt;div&gt;
  &lt;!--This div contain the small piece of left side of button image, fix width image --&gt;
  &lt;div&gt;
    &lt;!--Input button with the css class --&gt;
    &lt;input type=&quot;submit&quot; id=&quot;previous&quot; value=&quot;&amp;#171; previous&quot; /&gt;
    &lt;! -- Div with left side of image close here --&gt;
  &lt;/div&gt;
  &lt;! -- Spacer image for creating space between two images with float left css style --&gt;
  &lt;img src=&quot;images/spacer.gif&quot; width=&quot;20&quot; height=&quot;1&quot;&gt;&lt;/img&gt;
  &lt;!--This div contain the small piece of left side of button image, fix width image --&gt;
  &lt;div&gt;
    &lt;!--Input button with the css class --&gt;
    &lt;input type=&quot;submit&quot; id=&quot;next&quot; value=&quot;next &amp;#187;&quot; /&gt;
    &lt;! -- Div with left side of image close here --&gt;
  &lt;/div&gt;
  &lt;! -- Container div ends --&gt;
&lt;/div&gt;
</pre>
<p><strong>Style created for input button:</strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;style&gt;
.button_placeholder {
 border:none;
}
/* Buttonimage-new.png is 700px in width, which is used in background with right top */
.button_style_enabled {
 font-family: Arial, Helvetica, sans-serif;
 font-size: 12px;
 color: #ffffff;
 background: url(images/Buttonimage-new.png) no-repeat right top;
 text-align:center;
 cursor:pointer;
 height:29px;
 border:0px;
 margin:0px;
 font-weight:bold;
 vertical-align:middle;
 padding:0 15px;
}
.button_style_enabled:hover {
 background: url(images/Buttonimagehover-new.png) no-repeat right top;
 border:0px;
 margin:0px;
}
.button_style_enabled_edge {
 background: url(images/left-Buttonimage.png) no-repeat left top;
 height:29px;
 border:0px;
 margin:0px;
 padding-left:2px;
}
.left_float {
 float:left;
}
&lt;/style&gt;
</pre>
<p><strong>Images used in the button are:<br />
</strong>(I am using 700 width image for long button to fit in it.)</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td><img class="alignnone size-full wp-image-4890" title="left-Buttonimage" src="http://xebee.xebia.in/wp-content/uploads/2010/09/left-Buttonimage1.png" alt="left button image" width="2" height="29" /> left-Buttonimage.png</td>
</tr>
<tr>
<td><img class="alignnone size-medium wp-image-4891" title="Buttonimage" src="http://xebee.xebia.in/wp-content/uploads/2010/09/Buttonimage-300x12.png" alt="button image" width="630" height="27" /> Buttonimage.png</td>
</tr>
<tr>
<td><img class="alignnone size-medium wp-image-4892" title="Buttonimagehover" src="http://xebee.xebia.in/wp-content/uploads/2010/09/Buttonimagehover-300x12.png" alt="" width="630" height="27" /> Buttonimagehover.png</td>
</tr>
<tr>
<td><a rel="attachment wp-att-4893" href="http://xebee.xebia.in/2010/09/17/creating-and-styling-resizable-buttons/spacer/"><img class="alignnone size-full wp-image-4893" title="spacer" src="http://xebee.xebia.in/wp-content/uploads/2010/09/spacer.gif" alt="spacer" width="1" height="1" /></a> spacer.png</td>
</tr>
<tr>
<td><strong><br />
How it works:</strong><br />
<img class="size-full wp-image-4922 alignleft" style="border: 0pt none;" title="input" src="http://xebee.xebia.in/wp-content/uploads/2010/09/input2.png" border="0" alt="" width="616" height="200" /></td>
</tr>
<tr>
<td style="color: #f90; font-weight: bold;">This is how the buttons look like, if you have any question or any other solution please let me know, as this is just a trick to get the output<br />
<img class="size-full wp-image-4923 alignleft" style="border: 0pt none;" title="102" src="http://xebee.xebia.in/wp-content/uploads/2010/09/102.png" border="0" alt="" width="200" height="59" /></td>
</tr>
<tr>
<td>I hope you will like the solution.<br />
The designer has to be smart enough to create such button where the left side of button is either generated in 2-3 pixel width image or created with styling the border and background to create the button effect.</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/09/17/creating-and-styling-resizable-buttons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Groovy client for Apache Cassandra</title>
		<link>http://xebee.xebia.in/2010/09/14/groovy-client-for-apache-cassandra/</link>
		<comments>http://xebee.xebia.in/2010/09/14/groovy-client-for-apache-cassandra/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 06:45:23 +0000</pubDate>
		<dc:creator>Ravindra</dc:creator>
				<category><![CDATA[cassandra]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4727</guid>
		<description><![CDATA[I have been exploring Apache Cassandra recently for implementation of a project. Cassandra is a NoSQL (not only SQL) database open sourced by Facebook. This blog shares a Groovy implementation of a Cassandra client which makes accessing Cassandra as simple as accessing a HashMap. The Groovy implementation is currently a wrapper on the basic Thrift API. [...]]]></description>
			<content:encoded><![CDATA[<p>I have been exploring <a title="Apache Cassandra" href="http://cassandra.apache.org/" target="_self">Apache Cassandra</a> recently for implementation of a project. Cassandra is a NoSQL (not only SQL) database open sourced by Facebook.</p>
<p>This blog shares a Groovy implementation of a Cassandra client which makes accessing Cassandra as simple as accessing a HashMap. The Groovy implementation is currently a wrapper on the basic <a title="Apache Thrift" href="http://incubator.apache.org/thrift/" target="_self">Thrift </a>API. The map keys serve as the query language to perform slices and range queries.<span id="more-4727"></span></p>
<p>Cassandra provides a <a title="Apache Thrift" href="http://incubator.apache.org/thrift/" target="_self">Thrift </a>based interface which makes it accessible from different languages. It is similar to a WSDL file for Web Service which can be used to generate code clients in different languages.  There are two open source wrappers on Thrift API to access Cassandra:-</p>
<ol>
<li><a href="http://code.google.com/p/cassandra-java-client/">Cassandra Java Client</a></li>
<li><a href="http://github.com/rantav/hector">Hector</a></li>
</ol>
<p>Cassandra Java Client is too basic. Hector is a good option as it provides features like pooling and is JMX enabled.</p>
<p>I tried the Java thrift API and Hector but it looks too cumbersome and verbose if you wrote code in Groovy or another programming language. Following is the sample groovy test code compared to Thrift based <a title="Java example" href="http://wiki.apache.org/cassandra/ThriftExamples#Java" target="_blank">Java example.</a>.</p>
<pre class="brush: groovy; title: ; notranslate">

	void testSingleColumnGetAndSet() {
		k[&quot;User/a/user_id&quot;] = &quot;1&quot;;
		assert k[&quot;User/a/user_id&quot;] == &quot;1&quot;;
	}

	void testSlice() {
		k[&quot;User/b/1&quot;] = &quot;1&quot;;
		k[&quot;User/b/2&quot;] = &quot;2&quot;;
		k[&quot;User/b/3&quot;] = &quot;3&quot;;

		assert k[&quot;User/b/[1,2,3]&quot;] == [b:[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]];
		assert k[&quot;User/b/[1-2]&quot;] == [b:[&quot;1&quot;, &quot;2&quot;]];
		assert k[&quot;User/b/[3]&quot;] == [b:[&quot;3&quot;]];
	}

	void testRangeSlices() {
		k[&quot;User/d/1&quot;] = &quot;1&quot;;
		k[&quot;User/d/2&quot;] = &quot;2&quot;;

		k[&quot;User/e/1&quot;] = &quot;1&quot;;
		k[&quot;User/e/2&quot;] = &quot;2&quot;;

		assert k[&quot;User/[e-e]/[1,2,3]&quot;] == [e:[&quot;1&quot;,&quot;2&quot;]];
		assert k[&quot;User/[d-e]/[1,2,3]&quot;] == [d:[&quot;1&quot;,&quot;2&quot;],e:[&quot;1&quot;,&quot;2&quot;]];
	}
</pre>
<p>object 'k' is the keyspace wrapper, 'User' the column family and keys and columns follow them in a '/' separated path.</p>
<p>Cassandra data model is simple with only complication of a SuperColumn as explained in the <a href="http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model">blog</a> (the title of the post should give you an idea).</p>
<ol>
<li>Keyspace: like a database schema</li>
<li>ColumnFamily: Individual data spaces (User,Tweets)</li>
<li>Key: A key in the ColumnFamily</li>
<li>Column: A name,value and timestamp combination</li>
<li>SuperColumn: A Column that can contain multiple columns (in a ColumnFamily you cannot mix super and 'normal' columns)</li>
</ol>
<p>Following diagram tries to explain the data model.</p>
<pre><a rel="attachment wp-att-4781" href="http://xebee.xebia.in/2010/09/14/groovy-client-for-apache-cassandra/datamodel-3/"><img class="alignnone size-full wp-image-4781" title="DataModel" src="http://xebee.xebia.in/wp-content/uploads/2010/09/DataModel2.png" alt="Cassandra DataModel" width="572" height="324" /></a></pre>
<p>Now lets have a look at the Groovy code that accesses Cassandra.</p>
<p><strong>How it works:</strong></p>
<p>This is simply achieved by providing getAt and putAt in the Keyspace object which is the Groovy way of operator overriding.</p>
<pre class="brush: groovy; title: ; notranslate">
def getAt(String key) {
		def ctx = Selector.readContext(key)
		ctx[&quot;ks&quot;] = ks;
		def ret = client.get( ctx);
		return ret
	}

	void putAt(String key, Object value) {
		def ctx = Selector.writeContext(key)
		ctx[&quot;ks&quot;] = ks;
		client.put( ctx, value.toString());
	}
</pre>
<p>The 'selectors' (keys used in the subscript operator) are inspired from <a title="JXPath" href="http://commons.apache.org/jxpath/" target="_self">JXPath</a> world and are used for simple range queries as well. Below is a sample of the type of selectors that could be used.</p>
<pre class="brush: groovy; title: ; notranslate">
    void testIdentifySetRequest() {
		assert Selector.parse(&quot;cf/key/col&quot;, SelectorType.SET) == &quot;set_slice_col&quot;;
	}

	void testIdentifyGetRequest() {
		assert Selector.parse(&quot;cf/key/col&quot;, SelectorType.GET) == &quot;get_col&quot;;

		assert Selector.parse(&quot;cf/key/[col1,col2]&quot;, SelectorType.GET) == &quot;get_slice_col&quot;; // key slice
		assert Selector.parse(&quot;cf/key/[col1-col2]&quot;, SelectorType.GET) == &quot;get_slice_col&quot;;	// col range
		assert Selector.parse(&quot;cf/key/[col1-]&quot;, SelectorType.GET) == &quot;get_slice_col&quot;; // start to end
		assert Selector.parse(&quot;cf/key/[*]&quot;, SelectorType.GET) ==  &quot;get_slice_col&quot;; // all cols

		assert Selector.parse(&quot;cf/[key1-key2]/[col1-col2]&quot;,SelectorType.GET) == &quot;get_range_slice&quot;; // range
	}
</pre>
<p>Selectors are implemented using regular expressions. Selectors parse the 'path' expression and provide it as an input to client. Following is a code snippet of the expressions used.</p>
<pre class="brush: groovy; title: ; notranslate">
	def static final SET_REGEX = [
			set_slice_col: ~/(\w+)\/(\w+)\/(\w+)/
		];

	def static final GET_REGEX = [
		get_col: ~/(\w+)\/(\w+)\/(\w+)/, //  column get
		get_slice_col: ~/(\w+)\/(\w+)\/((\[(\w+[,-]?)+\])|(\[\*\]))/, // give me all columns
		get_range_slice: ~ /(\w+)\/((\[(\w+[,-]?)+\])|(\[\*\]))\/((\[(\w+[,-]?)+\])|(\[\*\]))/,   // get range slice
		get_range_key: ~/(\w+)\/\[(\w+[,-]?)+\]/  // give me a key range
	] as LinkedHashMap;
</pre>
<p>Below is the client code (GHector?) and Category code that takes out the reusable Cassandra specific code.</p>
<pre class="brush: groovy; title: ; notranslate">
	def put(ctx,value) {
		execute { Cassandra.Client client -&gt;
			use (CassandraCategory) {
				client.insert ctx.ks, ctx.key, cpath(ctx), value.serialize(), timestamp, defConLevel
			}
		}
	}

	def execute(cmd) {
		TTransport tt = new TSocket(server, port);
		TProtocol tp =  new TBinaryProtocol(tt);
		Cassandra.Client c = new Cassandra.Client(tp);
		try {
			tt.open();
			cmd(c);
		} finally {
			tt.close();
		}
	}
	...
	}
	// Category code
	class CassandraCategory {

	static cpath(ks, args) {
		ColumnPath cp = new ColumnPath(args[&quot;cf&quot;]);
		cp.setColumn(args[&quot;col&quot;].bytes);
		return cp;
	}

	static serialize(String s) {
		return s.getBytes(&quot;UTF-8&quot;);
	}
	...
	}
</pre>
<p>This approach could be useful for applications where we have fixed queries so the selectors could be cached. An application selecting large number of columns/keys dynamically would need an alternate approach (some sort of query API with filters).</p>
<p>This is still a work in progress (like results could have column names as keys as well... wait a second , it looks like JSON). In future I will be trying to implement the client using Hector instead of the raw Thrift API. Your comments are appreciated on how to make this better.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/09/14/groovy-client-for-apache-cassandra/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Exploring Android Charting and Graphs solutions</title>
		<link>http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/</link>
		<comments>http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 07:56:24 +0000</pubDate>
		<dc:creator>Yogesh Kapoor</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[achartengine]]></category>
		<category><![CDATA[chartdroid]]></category>
		<category><![CDATA[charting]]></category>
		<category><![CDATA[google chart api]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4669</guid>
		<description><![CDATA[In one of the Android applications that I was creating the requirement was to have graphs and charts to present the data in a meaningful way to the user. With no direct charting API support in Android to address graphs and charts creation, I explored few other possible solutions. This blog does not focus on [...]]]></description>
			<content:encoded><![CDATA[<p>In one of the Android applications that I was creating the requirement was to have graphs and charts to present the data in a meaningful way to the user. With no direct charting API support in Android to address graphs and charts creation, I explored few other possible solutions.</p>
<p>This blog does not focus on comparing the available solutions but demonstrates the simple implementations using the approaches explored.</p>
<p>I considered three different ways to create charts in Android device</p>
<p>1. <a href="http://code.google.com/apis/chart/">Google chart API</a><br />
2. <a href="http://www.achartengine.org/">Achartengine</a><br />
3. <a href="http://code.google.com/p/chartdroid/">ChartDroid</a><br />
<span id="more-4669"></span><br />
I tried creating a Pie Chart while using the solutions. Google charting API being the easiest one to integrate is taken first</p>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		H4 { margin-bottom: 0.08in } 		H4.western { font-family: "Arial", sans-serif; font-size: 11pt; font-style: italic } 		H4.cjk { font-family: "SimSun"; font-size: 11pt; font-style: italic } 		H4.ctl { font-size: 11pt; font-style: italic } --></p>
<h4>Google Charting API support</h4>
<p>Using Google charting API, we can create charts and graphs directly by providing data to the Google charting service</p>
<p>The call to the Google's charting API looks like below:</p>
<pre class="brush: xml; title: ; notranslate">http://chart.apis.google.com/chart?cht=&amp;amp;chd=&amp;amp;chs=&amp;amp;...additional_parameters...</pre>
<p>More on Google charting API can be found <a href="http://code.google.com/apis/chart/docs/making_charts.html">here</a></p>
<p>For creating a pie chart using Google charting solution, I created the following URI</p>
<pre class="brush: xml; title: ; notranslate">http://chart.apis.google.com/chart?cht=p3&amp;amp;chd=t:30,60,10&amp;amp;chs=250x100&amp;amp;chl=cars|bikes|trucks</pre>
<p>Within my activity's onCreate() I included the code below</p>
<pre class="brush: java; title: ; notranslate">@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView googleChartView = new WebView(this);
setContentView(googleChartView);
String mUrl = &quot;http://chart.apis.google.com/chart?cht=p3&amp;amp;chd=t:30,60,10&amp;amp;chs=250x100&amp;amp;chl=cars|bikes|trucks&quot;;
googleChartView.loadUrl(mUrl);
}</pre>
<p>In the onCreate() method, I am creating a WebView and just loading it with the URL response.<br />
It needs an internet access so I included the code below within AndroidManifest.xml</p>
<pre class="brush: xml; title: ; notranslate">
&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
</pre>
<p>That's it!!! we are done with the first approach. The screen shot for the application I build using Google chart API looks like below:</p>
<div id="attachment_4674" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-4674" href="http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/googleapichart/"><img class="size-medium wp-image-4674" title="GoogleAPIChart" src="http://xebee.xebia.in/wp-content/uploads/2010/08/GoogleAPIChart-300x193.png" alt="Google Charting API PIE Chart" width="300" height="193" /></a><p class="wp-caption-text">Google Charting API PIE Chart</p></div>
<p>The only issue I had with this approach is that the device should have internet access available which in my case may not be always there. This small limitation made me look into other approaches and I came across another solution <a href="http://www.achartengine.org/">Achartengine</a>.</p>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		H4 { margin-bottom: 0.08in } 		H4.western { font-family: "Arial", sans-serif; font-size: 11pt; font-style: italic } 		H4.cjk { font-family: "SimSun"; font-size: 11pt; font-style: italic } 		H4.ctl { font-size: 11pt; font-style: italic } --></p>
<h4>Achartengine</h4>
<p>This Achart's charting support comes in the form of a download-able <a href="http://code.google.com/p/achartengine/downloads/list">Jar</a>.</p>
<p>I added this into the lib folder of my application.</p>
<div id="attachment_4677" class="wp-caption alignnone" style="width: 257px"><a rel="attachment wp-att-4677" href="http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/libfolder/"><img class="size-full wp-image-4677" title="libFolder" src="http://xebee.xebia.in/wp-content/uploads/2010/08/libFolder.png" alt="Library Folder" width="247" height="290" /></a><p class="wp-caption-text">Android App Structure</p></div>
<p>I created a class with a method that gives out a Pie chart intent as below</p>
<pre class="brush: java; title: ; notranslate">
public class AChartExample {

public Intent execute(Context context) {
int[] colors = new int[] { Color.RED, Color.YELLOW, Color.BLUE };
DefaultRenderer renderer = buildCategoryRenderer(colors);

CategorySeries categorySeries = new CategorySeries(&quot;Vehicles Chart&quot;);
categorySeries.add(&quot;cars &quot;, 30);
categorySeries.add(&quot;trucks&quot;, 20);
categorySeries.add(&quot;bikes &quot;, 60);

return ChartFactory.getPieChartIntent(context, categorySeries, renderer);
}

protected DefaultRenderer buildCategoryRenderer(int[] colors) {
DefaultRenderer renderer = new DefaultRenderer();
for (int color : colors) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(color);
renderer.addSeriesRenderer(r);
}
return renderer;
}
}
</pre>
<p>Within the execute method a SimpleSeriesRender is created with the required color that is required in the pie chart.<br />
These renderers are then added to the DefaultRender.</p>
<p>Next step is to create a CategorySeries with the appropriate data. Once this is done we can get achartingengine specific intent back with the following call<br />
<code><br />
ChartFactory.getPieChartIntent(context, categorySeries, renderer);<br />
</code></p>
<p>With this intent we launch our activity and the code goes as below</p>
<pre class="brush: java; title: ; notranslate">
Intent achartIntent = new AChartExample().execute(this);
startActivity(achartIntent);
</pre>
<p>The screen shot below shows the generated PIE chart using Achart library</p>
<div id="attachment_4697" class="wp-caption alignleft" style="width: 233px"><a href="http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/achart-3/" rel="attachment wp-att-4697"><img src="http://xebee.xebia.in/wp-content/uploads/2010/08/Achart2-223x300.png" alt="" title="Achart" width="223" height="300" class="size-medium wp-image-4697" /></a><p class="wp-caption-text">Achart</p></div><br />
The other charting solution I explored is <a href="http://code.google.com/p/chartdroid/">chartDroid </a></p>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		H4 { margin-bottom: 0.08in } 		H4.western { font-family: "Arial", sans-serif; font-size: 11pt; font-style: italic } 		H4.cjk { font-family: "SimSun"; font-size: 11pt; font-style: italic } 		H4.ctl { font-size: 11pt; font-style: italic } --></p>
<h4>Chartdroid</h4>
<p>This solution needs the ChartDroid Application to be installed along with the application which intends to use the charting solution.</p>
<p>Although, we can install the application programmaticly from the Android apps market place, I directly installed the application into my device to explore it further.To install it download the apk from <a href="http://code.google.com/p/chartdroid/downloads/list">here</a> and install it to the device.</p>
<p>The Chartdroid's charting solution requires a content provider to be created. Below is the content provider's code that I created</p>
<pre class="brush: java; title: ; notranslate">
public class ChartDroidDataProvider extends ContentProvider {

static final String AUTHORITY =  &quot;com.xyz.contentprovider.chardroid&quot;;

@Override
public String getType(Uri uri) {
return &quot;vnd.android.cursor.dir/vnd.com.googlecode.chartdroid.graphable&quot;;
}

public static final Uri PROVIDER_URI = new Uri.Builder().scheme(
ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build();

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {

// Fetch the actual data

MatrixCursor c = new MatrixCursor(new String[] 					{ BaseColumns._ID,
&quot;COLUMN_AXIS_INDEX&quot;, &quot;COLUMN_SERIES_INDEX&quot;,
&quot;COLUMN_DATUM_VALUE&quot;, &quot;COLUMN_DATUM_LABEL&quot; });

c.newRow().add(1).add(0).add(1).add(30).add(null);
c.newRow().add(2).add(0).add(1).add(10).add(null);
c.newRow().add(3).add(0).add(1).add(60).add(null);

return c;
}

}
</pre>
<p>In the code above, I have excluded some methods which are the default IDE's implementations. The query method provides the data along with other details which are required to build a chart. The data can come from database as well. In the simplistic case of generating a PIE chart I created a MatixCursor to serve as my PIE chart data. In the cursor, I am adding three rows which takes data values as 30,10 and 60 respectively and the labels as null.</p>
<p>For detailed information on the other parameters please look <a href=" http://code.google.com/p/chartdroid/wiki/InterfaceSpecification">here</a></p>
<p>Now, to display the Chartdroid activity with the PIE Chart backed by data from the content provider created above an Intent is to be created.</p>
<p>The implementation goes like below:</p>
<pre class="brush: java; title: ; notranslate">
Intent chartDroidIntent = new Intent(Intent.ACTION_VIEW,
ChartDroidDataProvider.PROVIDER_URI);
chartDroidIntent.putExtra(Intent.EXTRA_TITLE, &quot;Chart droid&quot;);
chartDroidIntent
.addCategory(&quot;com.googlecode.chartdroid.intent.category.PIE_CHART&quot;);
startActivity(chartDroidIntent);
</pre>
<p>In the code above adding category is important as it decides what form of charting is required. In my case it's PIE_CHART.</p>
<p>Also, we can pass in most of the data in form of Intent's extras, except the actual data. In example above the title information is going as the extra.</p>
<p>Launching the ChartDroid's activity gives the results as below:</p>
<p><div id="attachment_4683" class="wp-caption alignnone" style="width: 221px"><a rel="attachment wp-att-4683" href="http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/chartdroid/"><img class="size-medium wp-image-4683" title="chartdroid" src="http://xebee.xebia.in/wp-content/uploads/2010/08/chartdroid-211x300.png" alt="Chartdroid" width="211" height="300" /></a><p class="wp-caption-text">Chartdroid</p></div>
<p>Complete source code for the application can be downloaded <a href="http://www.esnips.com/doc/ccb345ad-25ed-40df-aeb9-b3e0ae17daa8/charting">here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>How to improve modularity and extensibility of web-apps using OSGi</title>
		<link>http://xebee.xebia.in/2010/08/30/4543/</link>
		<comments>http://xebee.xebia.in/2010/08/30/4543/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 14:21:26 +0000</pubDate>
		<dc:creator>Shankar Jha</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Embedded felix]]></category>
		<category><![CDATA[embedded OSGi container]]></category>
		<category><![CDATA[OSGi]]></category>
		<category><![CDATA[OSGi in web app]]></category>
		<category><![CDATA[Web Modularization]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4543</guid>
		<description><![CDATA[Please note that this blog assumes that the reader has basic knowledge of OSGi and how to create bundles. If you are a beginner you may like to read the Getting Started with OSGi. Sometimes in an existing application you may want to use the capabilities of the OSGi framework. For example, in my recent project [...]]]></description>
			<content:encoded><![CDATA[<p>Please note that this blog assumes that the reader has basic knowledge of OSGi and how to create bundles. If you are a beginner you may like to read the <a href="http://www.osgi.org/About/HowOSGi">Getting Started with OSGi</a>.</p>
<p>Sometimes in an existing application you may want to use the capabilities of the OSGi framework. For example, in my recent project we had a already built, live web application. A module of the application was offering some services and user could choose from the available list. Each service in this module was in turn a separate product with its own pricing and license. As part of enhancement we had following requirements</p>
<ol>
<li>When a client procures this application (product) he should have the flexibility to procure some or all associated services.</li>
<li>If the client has ready made implementation of some related services which he wants to incorporate in the application then that integration should be possible with minimum effort.<span id="more-4543"></span></li>
</ol>
<p>On deliberation and analysis we decided to use OSGi framework to solve the technical problem in hand.</p>
<h4>Reasons to choose OSGi</h4>
<ol>
<li>On use of OSGi the application would not contain any logic related to any services. Application would only know how to discover the different categories of bundles and make them availble to the user.</li>
<li>The logic of each service will get encapsulated in bundles. This would make the design very modular, flexible, extensible and clean.</li>
<li>It would be very easy to remove unwanted services or add desired services without any change in the application.</li>
<li>For integrating of the client's application we would need to wrap the client's implementation in a bundle and deploy it, that's all. Application code would remain untouched.</li>
</ol>
<h4>Advantages of using OSGi</h4>
<p>By using the capabilities of OSGi the application could be moved to next level of flexibility. The application would only know how to interact with the user and the bundles. All the core logic of services would now move to the bundle. Which meant the new  requirements had led to a design which would make our application light, easily testable (less to test), easily extensible and maintainable (an issue in a service would mean check the respective bundle and not the whole application).</p>
<h4>Get your hands dirty</h4>
<p>Since the background is set in support of using OSGi as part of web application, its time to make our hands dirty and learn how we can go about doing it. Let us take a simple problem statement and try to solve it. Suppose xyz comany has 'n' number of stores. xyz company is IT equipped and they have a website where people can come and see the available stores. They can also see the list of items available at store along with their prices etc. Due to popularity of the website the other store owners started contacting xyz company to enlist their store in the same website. To solve the issue techies decided to use OSGi. It was decided that every store will be an OSGi bundle.</p>
<h4>1. Identify the common interface/service declaration</h4>
<p>The first task is to create a set of common interface and classes which would facilitate communication between web application and OSGi bundles.</p>
<p>a. Interface Store.java</p>
<pre class="brush: java; title: ; notranslate">
package com.osgi.learn.ext;

import java.util.List;
import com.osgi.learn.ext.entities.Item;

public interface Store {
public String getStoreName();
public List&lt;Item&gt; getItems();
}
</pre>
<p>b. Class Item.java</p>
<pre class="brush: java; title: ; notranslate">
package com.osgi.learn.ext.entities;

public class Item {
private String name;
private float price;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
</pre>
<p>This glue code can be packaged as a Jar and injected as dependency to both application and implementing bundles. The bundles would provide the implementation for Store.java and export the implementation as service.</p>
<p>To download the Jar file for the common interface click <a href="http://www.esnips.com/nsdoc/0471819e-9182-4f72-a835-4932936f2ea3/?action=forceDL">here</a>.</p>
<p>Common communication interface is in place. The bundles can also be created with little effort (to download the bundle jar click <a href="http://www.esnips.com/nsdoc/c124b58c-c12d-4ace-a8cf-37a57197d1fe/?action=forceDL">here</a>). The next task is to enable communication between web application and bundles. To do that we need to do the following:</p>
<h4>2. Embed OSGi container</h4>
<p>Embed OSGi container in the web-application - Apache Felix in our case. To programmatically start a Felix container we need to do the following (to see the complete code download the <a href="http://www.esnips.com/nsdoc/e5b8d17b-0009-49f4-a9d1-cb10a545ba35/?action=forceDL">HostApplication.java </a>and<a href="http://www.esnips.com/nsdoc/239da89e-7a11-4960-a274-8b20929a1b8b/?action=forceDL"> StoreServiceTracker.java</a>).</p>
<pre class="brush: java; title: ; notranslate">
try {
felix = new Felix(getConfigMap());
felix.start();
logger.info(&quot;OSGI container started&quot;);

} catch (BundleException ex) {
logger.error(&quot;Could not create framework: &quot;, ex);
throw new RuntimeException(ex);
}
</pre>
<p>In the above code one thing that needs special attention is 'getConfigMap()'. getConfigMap() will return an Object of java.util.Map which contains special configuration info which we want to pass to the container during start up. The configMap argument in the Felix container can be passed as null. The framework is supposed to have intelligent defaults which it will use to get started. But in case you want to override the defaults then you can do something like this:</p>
<pre class="brush: java; title: ; notranslate">
public Map getConfigMap(){
// Create a configuration property map.
Map configMap = new HashMap();
// Export the host provided service interface package.
configMap.put(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,                      - 1
&quot;com.learn.osgi.ext; version=1.0.0&quot;);
//specify the file system path to a directory which will be used by framework. One of the many uses is to store the cached bundle here.
configMap.put(FelixConstants.FRAMEWORK_STORAGE, cacheDirectory);                      - 2
return configMap;
}
</pre>
<p>-1 FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA - This attribute tells OSGi framework to add the specified package as part of system package so that it gets available to all bundles by default. It also enable communication between application and the bundles. The other option could be to also deploy the jar with the package com.learn.osgi.ext as bundle.</p>
<p>-2 FelixConstants.FRAMEWORK_STORAGE - This attribute tells the application that the location in file system specified (cacheDirectory) can be used by Framework for all purposes like storing cached bundles etc.</p>
<h4>3. Create service trackers</h4>
<p>There may be number of bundles deployed in the container, some of them may be system bundles and others may be supporting bundles. To identify the Store bundles we will have to create a service tracker</p>
<pre class="brush: java; title: ; notranslate">
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.osgi.learn.ext.Store;

public class StoreServiceTracker extends ServiceTracker {
/**
* Constructor
* @param bundleContext
*/
public StoreServiceTracker(BundleContext bundleContext) {
super(bundleContext, Store.class.getName(), null);
}

/**
* Opens this tracker
*/
@Override
public void open() {
super.open();
}
}
</pre>
<p>Just after the start up of felix we can execute the following code to instantiate the tracker</p>
<pre class="brush: java; title: ; notranslate">
storeServiceTracker = new storeServiceTracker(felix.getBundleContext());
storeServiceTracker.open();
</pre>
<p>Now to get all bundles that are registered as Store bundles just call the following method</p>
<pre class="brush: java; title: ; notranslate">
public Set&lt;Bundle&gt; getStoreBundles() {

ServiceReference[] refs = getTrackedStoreServiceReferences();
if (refs == null) {
return Collections.emptySet();
}

Set&lt;Bundle&gt; bundles = new HashSet&lt;Bundle&gt;();

for (ServiceReference ref : refs) {
bundles.add(ref.getBundle());
}

return bundles;
}

public ServiceReference[] getTrackedStoreServiceReferences() {
return storeServiceTracker.getServiceReferences();
}
</pre>
<h4>4. Interact with the bundle service</h4>
<p>The last step is to interact with the bundle</p>
<pre class="brush: java; title: ; notranslate">
Store service = bundle.getService(Store.class);
service.getStoreName();
service.getItems();
</pre>
<p>This solves the complete cycle.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/30/4543/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex: The wmode nightmare!! &#8211; Some workarounds</title>
		<link>http://xebee.xebia.in/2010/08/29/the-wmode-nightmare-in-flex-some-workarounds-to-resolve-issues-pertaining-to-wmode-settings-in-flex/</link>
		<comments>http://xebee.xebia.in/2010/08/29/the-wmode-nightmare-in-flex-some-workarounds-to-resolve-issues-pertaining-to-wmode-settings-in-flex/#comments</comments>
		<pubDate>Sun, 29 Aug 2010 18:14:30 +0000</pubDate>
		<dc:creator>Karan Nangru</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[measure]]></category>
		<category><![CDATA[wmode]]></category>
		<category><![CDATA[wmode bug]]></category>
		<category><![CDATA[wmode issue]]></category>
		<category><![CDATA[wmode problem]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4620</guid>
		<description><![CDATA[It is highly likely that if you have at any point of your development cycle fiddled around with the feature called - wmode, then you have landed into some trouble or the other. Brief introduction to wmode: 'wmode' stands for Windowless Mode. The wmode parameter is available in the object/embed tags used to place the [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } -->It is highly likely that if you have at any point of your development cycle fiddled around with the <em>feature </em><em>called </em>- <em>wmode</em>, then you have landed into some trouble or the other.</p>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --> <!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --> <!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="font-size: medium;"><em><strong>Brief introduction to wmode:</strong></em></span></p>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><em>'wmode'</em> stands for Windowless Mode. The wmode parameter is available in the object/embed tags used to place the Flash swf (compiled application) on stage:<span id="more-4620"></span></p>
<pre class="brush: java; title: ; notranslate">
&lt;div id=&quot;mainContainer&quot; align=&quot;center&quot;&gt;
&lt;object classid=&quot;......&quot; id=&quot;Main&quot; width=&quot;969&quot; height=&quot;100%&quot; codebase=&quot;......&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;#request....URL#&quot; /&gt;
&lt;param name=&quot;quality&quot; value=&quot;high&quot; /&gt;
&lt;param name=&quot;bgcolor&quot; value=&quot;##FFFFFF&quot; /&gt;
&lt;param name=&quot;allowScriptAccess&quot; value=&quot;sameDomain&quot; /&gt;
&lt;param name=&quot;wmode&quot; value=&quot;opaque&quot; /&gt;
&lt;embed src=&quot;#request....URL#&quot; quality=&quot;high&quot; bgcolor=&quot;##FFFFFF&quot; width=&quot;969&quot; height=&quot;100%&quot; name=&quot;Main&quot; align=&quot;middle&quot; play=&quot;true&quot; loop=&quot;false&quot; quality=&quot;low&quot;
allowScriptAccess=&quot;sameDomain&quot; type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.adobe.com/go/getflashplayer&quot; wmode=&quot;opaque&quot;&gt;
&lt;/embed&gt;
&lt;/object&gt;
&lt;/div&gt;
</pre>
<p>There are three wmode's available with the Flash player across most browsers and platforms.</p>
<ul>
<li><strong>Window</strong>: Use the 	Window value to play a Flash Player movie in its own rectangular 	window on a web page. This is the default value for wmode and it 	works the way the classic Flash Player works. This normally provides 	the fastest animation performance.(If you do not notice a wmode 	specified in your SWF wrapper, then the wmode value is Window)</li>
<li><strong>Opaque</strong>: By using 	the Opaque value you can use JavaScript to move or resize movies 	that don't need a transparent background. Opaque mode makes the 	movie hide everything behind it on the page. Additionally, opaque 	mode moves elements behind Flash movies (for example, with dynamic 	HTML) to prevent them from showing through.</li>
<li><strong>Transparent</strong>: Transparent mode allows the 	background of the HTML page, or the DHTML layer underneath the Flash 	movie or layer, to show through all the transparent portions of the 	movie. This allows you to overlap the movie with other elements of 	the HTML page. Animation performance might be slower when you use 	this value.</li>
</ul>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="font-size: medium;"><em><strong>wmode Issues:</strong></em></span></p>
<p><span style="font-size: small;"><em>wmode</em> bestows inconsistencies while using different browsers.</span></p>
<p><span style="font-size: small;">Here are a few issues:</span></p>
<ul>
<li><span style="font-size: small;">When using a transition between states the resize effect flashes the final resize state before resizing (more apparent with wmode set to opaque or transparent)</span></li>
</ul>
<p><span style="font-size: small;">https://bugs.adobe.com/jira/browse/SDK-12421</span></p>
<ul>
<li><span style="font-size: small;">When using wmode=opaque or transparent text input fields do not allow special characters </span></li>
</ul>
<p><span style="font-size: small;">https://bugs.adobe.com/jira/browse/SDK-12420</span></p>
<ul>
<li><span style="font-size: small;"> Wheel mouse does not work in Firefox when wmode is set to opaque or transparent (Firefox)</span></li>
</ul>
<p><span style="font-size: small;">https://bugs.adobe.com/jira/browse/SDK-12415</span></p>
<ul>
<li><span style="font-size: small;">Flex TextInput does not gain focus when cursor is in text field of iframe</span></li>
</ul>
<p><span style="font-size: small;">https://bugs.adobe.com/jira/browse/SDK-12377</span></p>
<ul>
<li><span style="font-size: small;">Multiple SWF embeds, wmode enabled, fullscreen requested (FP 9.0.115 &gt;), on exit of fullscreen mode, out of focus flash movies will not be redrawn.(IE)</span></li>
</ul>
<ul>
<li><span style="font-size: small;">SetInterval will be constrained to enterframe count with wmode enabled. Will cause redraw and performance issues.(IE)</span></li>
</ul>
<ul>
<li><span style="font-size: small;">Fullscreen not available with FP 9.0.23 – FP 9.0.100 when wmode enabled.</span></li>
</ul>
<ul>
<li><span style="font-size: small;">Animation sequences / Video will stutter and show empty frames (effect more prevalent in FF). Animated sequences of bitmaps show blank frames (memory issues), video will stutter or skip frames unnecessarily. Generally the issue is related to memory management – with wmode enabled all aspects of the scripting engine is throttled and swapping of memory is handled poorly.</span></li>
</ul>
<ul>
<li><span style="font-size: small;">Text fields may be offset from their natural location during text entry if page is scrolled.</span></li>
</ul>
<ul>
<li><span style="font-size: small;"> Text field tabbing will not function if wmode is enabled.</span></li>
</ul>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="font-size: small;"><span style="font-size: medium;"><em><strong>A major wmode bug and a workaround to avoid it:</strong></em></span> </span></p>
<p><span style="font-size: small;">It turns out to be a nightmare if while merging  your flex application into a coldfusion(or scripting) base application you need to switch the wmode to opaque or transparent to enable scripting pop up be visible above the flex layer. </span></p>
<p><span style="font-size: small;">I encountered a bug that switching wmode to opaque or transparent made my complete flex application go </span>weird<span style="font-size: small;">. Everytime I scrolled down the application, the complete screen used to distort. Every componenent rendered on the stage used to break and nothing was legible. So, in a way the complete effort of building the application was ruined by just </span>switching <span style="font-size: small;">from wmode = window to wmode = transparent. The UI seemed like a scrambled puzzle.</span></p>
<p><span style="font-size: small;">With </span>lilliputian<span style="font-size: small;"> help from Adobe, I had resort to the following :</span></p>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="text-decoration: underline;"><span style="font-size: small;"><em>Workaround for avoiding screen distortion on flex application scrolling when wmode set to opaque or transparent:</em></span></span></p>
<p><span style="font-size: small;">On carefully analysing the issue, I figured out that the application distorts everytime flex appplication level scrollbar is used. So I thought of a workaround wherein there would be no flex application level scrollbar. Thus, if there is no scrolling on flex application – the screen would not break.</span></p>
<p><span style="font-size: small;">Since the flex swf is wrapped in an html(or cfm) wrapper, I thought of adjusting the height of the browser everytime the height of the my flex swf changes. So this way, everytime there is a change in the height of the swf (stage), I would be sending the height to the underlying wrapper which would then set the height of the browser equivalent to the height of the swf.  Sounds confusing? Heres the gist of the logic:</span></p>
<ul><span style="font-size: small;">&gt;&gt; 	Disable vertical scrolling of the flex application by overriding the 	measure method at the application level and thereon adjusting the 	browser height:</span><span style="font-size: small;">Write this code in the flex application class:</span><span style="font-size: small;"><br />
</span></ul>
<pre class="brush: java; title: ; notranslate">

/**
* resize wrapper container
*/
private var _lastMeasuredHeight : int;
override protected function measure() : void
{
super.measure();
if( measuredHeight != _lastMeasuredHeight )
{
_lastMeasuredHeight = measuredHeight;
if( ExternalInterface.available )
{
ExternalInterface.call(&quot;setFlashHeight&quot;, measuredHeight);
}
}
}
</pre>
<ul><span style="font-size: small;"><em>Note</em>: Height and width of the flex swf is set in the object/embed tag of the swf wrapper:</span><span style="font-size: small;">Whenever the height of the flex application exceeds the height of its container, there is vertical scrollbar in the flex application.  So we will set a relative height for the swf container in wrapper class and update it whenever the height of the swf changes:</span></p>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><em><span style="font-size: small;">Wrapper code:</span></em></p>
<pre class="brush: java; title: ; notranslate">
&lt;div id=&quot;mainContainer&quot; align=&quot;center&quot;&gt;
&lt;object classid=&quot;......&quot; id=&quot;Main&quot; width=&quot;969&quot; height=&quot;100%&quot; codebase=&quot;......&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;#request....URL#&quot; /&gt;
&lt;param name=&quot;quality&quot; value=&quot;high&quot; /&gt;
&lt;param name=&quot;bgcolor&quot; value=&quot;##FFFFFF&quot; /&gt;
&lt;param name=&quot;allowScriptAccess&quot; value=&quot;sameDomain&quot; /&gt;
&lt;param name=&quot;wmode&quot; value=&quot;opaque&quot; /&gt;
&lt;embed src=&quot;#request....URL#&quot; quality=&quot;high&quot; bgcolor=&quot;##FFFFFF&quot; width=&quot;969&quot; height=&quot;100%&quot; name=&quot;Main&quot; align=&quot;middle&quot; play=&quot;true&quot; loop=&quot;false&quot; quality=&quot;low&quot;
allowScriptAccess=&quot;sameDomain&quot; type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.adobe.com/go/getflashplayer&quot; wmode=&quot;opaque&quot;&gt;
&lt;/embed&gt;
&lt;/object&gt;
&lt;/div&gt;
</pre>
<p><span style="font-size: small;">Now, we will define the method </span><span style="font-size: small;"><em>setFlashHeight </em></span><span style="font-size: small;">in the wrapper. This method is called everytime the height of the flex swf(flex application) changes.</span></p>
<pre class="brush: java; title: ; notranslate">
/*
resize Flex div
*/
function setFlashHeight(newHeight)
{
if( navigator.appVersion.indexOf('MSIE 6.') != -1 )
{
newHeight = newHeight + 2000;
}
var flashContentHolderDiv = document.getElementById('mainContainer');
flashContentHolderDiv.style.height = newHeight + &quot;px&quot;;
}
</pre>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="font-size: small;">So this way, everytime the height of the swf changes creating a scenario for a vertical scrollbar, we send the height to the browser and thus increase the browser's height, thereby a vertical scroll bar is introduced in the browser,rather than in the swf.</span></p>
<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } --><span style="font-size: small;"><strong>Caution</strong></span><span style="font-size: small;"> : If the swf height increases beyond 4000px, the page will not be rendered completely.This is an irony in the solution described above.</span></p>
<p><em><span style="font-size: small;">Try this out:</span></em><span style="font-size: small;"><em><br />
</em></span></p>
<p><span style="font-size: small;"><em> </em>If you debug the default maxHeaight property set for any component in Flex, then it is 10000px.  But still the browser cannot render beyond 4000px.  The reason being that although flex supports a height of 10000px but, the flash player does not render beyond 4000px!!!</span></p>
<p><span style="font-size: small;">So be cautious that your applications height should not exceed 4000px.</span></ul>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/29/the-wmode-nightmare-in-flex-some-workarounds-to-resolve-issues-pertaining-to-wmode-settings-in-flex/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Implementing Generic functionality  in Grails</title>
		<link>http://xebee.xebia.in/2010/08/28/implementing-generic-functionality-in-grails/</link>
		<comments>http://xebee.xebia.in/2010/08/28/implementing-generic-functionality-in-grails/#comments</comments>
		<pubDate>Sat, 28 Aug 2010 11:24:00 +0000</pubDate>
		<dc:creator>Sunil Prakash Inteti</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[auto complete]]></category>
		<category><![CDATA[DRY principle]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4593</guid>
		<description><![CDATA[In web applications we have functionalities like auto suggestions , rating objects, adding to favourites etc which repeat themselves in an application and across applications. So it demands to think about implementing a generic way of rating and adding to user favourites etc and follow DRY principle. Recently in one of my Grails projects we [...]]]></description>
			<content:encoded><![CDATA[<p>In web applications we have functionalities like auto suggestions , rating objects, adding to favourites etc which repeat themselves in an application and across applications. So it demands to think about implementing a generic way of rating and adding to user favourites etc and follow <strong>DRY</strong> principle. Recently in one of my Grails projects we implemented these functionalities in a generic way so that they are reusable and easy to use. Here in this blog, specifically lets look at how we can implement generic auto suggest functionality in Grails. This idea can be extended for other functionalities as well.</p>
<p>Jquery already provides <a href="http://docs.jquery.com/Plugins/Autocomplete">auto suggest</a> functionality. The question here is making functionality generic so that next time we have to use that its a breeze to use. Lets create a tag which can add the necessary jquery code for a text field to have auto suggest capability.<span id="more-4593"></span></p>
<p><strong>HTML code :</strong></p>
<pre class="brush: xml; title: ; notranslate"> &lt;g:textField name=&quot;city&quot; id=&quot;city&quot; value=&quot;&quot; /&gt;
&lt;g:autoSuggest autoCompleteForId=&quot;city&quot; searchObject=&quot;com.xebia.Address&quot; searchProperty=&quot;city&quot;/&gt;
</pre>
<p>For searchObject property we must give the fully qualified class name of the domain object. Here we have Address as the domain objects which has a property city in it. The above tag is handled by the following closure in the Taglibrary.</p>
<p><strong>Autocomplete Tag Library:</strong></p>
<pre class="brush: java; title: ; notranslate">
    def autoSuggest = { attrs , body -&gt;
		def searchObject = attrs.searchObject
		def searchProperty = attrs.searchProperty
		def htmlId = attrs.autoCompleteForId
		def width = attrs.width
		def contextName = grailsApplication.config.grails.serverURL
		def actionName = attrs.action ? attrs.action : 'autoSuggest'
		def controllerName = attrs.controller ? attrs.controller : 'autocomplete' 

		String serviceUrl =  createLink(controller:controllerName, action:actionName , absolute:true)

		importScriptsAndCSS(out, contextName, pageScope);

		out &lt;&lt; &quot;&lt;script&gt;  jQuery(function() {&quot;
		out &lt;&lt; 	&quot;\$(\&quot;#&quot;+ htmlId+ &quot;\&quot;).autocomplete({ &quot;
		out &lt;&lt;			  &quot; serviceUrl: \'&quot;+ serviceUrl +&quot;\',&quot;
		out &lt;&lt; 		'''
					    minChars:1,
					    maxHeight:400,
					    zIndex: 9999,
					    deferRequestBy: 0,
					 '''
		if(width) {
			out &lt;&lt; 	&quot;width:&quot;+width+&quot;,&quot;
		}

		out &lt;&lt;	&quot;params: {searchObject:\'&quot;+searchObject+&quot;\',searchProperty:\'&quot;+searchProperty  + &quot;\'}, &quot; 

		out &lt;&lt; '''
						noCache: false
					});
			});
			 &lt;/script&gt;
		'''

	} 
</pre>
<p>The method importScriptsAndCSS(out, contextName, pageScope) as the name suggests, adds the necessary css and javascript needed only once per page.<br />
The auto suggest tag that we use in tandem with a text field captures the property that we need suggestions for on an domain object and adds necessary jquery code to hit a generic AutoSuggestController which will return the matching options in JSON format to jquery. Now lets look at the generic AutoSuggestController code.</p>
<p><strong>AutoSuggestController</strong></p>
<pre class="brush: java; title: ; notranslate">
  def autoSuggest = {
		log.debug(&quot;Inside the auto complete controller&quot;)
		def searchObject = params.searchObject
		def searchProperty = params.searchProperty
		def queryValue = params.query

		def searchCriteria = grailsApplication.getClassForName(searchObject).createCriteria()
		log.debug &quot;query value is ${queryValue}&quot;
		def results = searchCriteria.list{
			projections {
				groupProperty(searchProperty)
			}
			ilike(searchProperty, &quot;%${queryValue}%&quot;)
			maxResults(5)
		}
		log.debug(&quot;Auto suggest Results  : &quot;+results)
		render createJSONForResults(results, queryValue , searchProperty)
	}
</pre>
<p>The above code snippet is the action that will be accessed by the jquery which also passes the search Property and Search Object to  the controller. Dynamically we determine the domain object by this line of code   <strong>grailsApplication.getClassForName(searchObject).createCriteria()</strong></p>
<p>We get the domain object from the fully qualified class name and then create a criteria on the grails domain object. In this criteria we attempt to get the list of objects for which the searchProperty(city) matches. Once we get the list of objects we have to convert the list into JSON object format, so that that is passed back to the jquery to render the auto suggestions.</p>
<p><strong>JSON format can be achieved like this</strong></p>
<pre class="brush: java; title: ; notranslate">
   private String createJSONForResults(def results, String queryValue, String searchProperty) {
		def resultsArray = results.toArray()
		StringBuilder resultsJSONObject = new StringBuilder(&quot;{ query : \'${queryValue}\' , suggestions: [&quot;)
		if(resultsArray.length &gt; 0) {
			for(int i=0;i&lt;resultsArray.length-1;i++) {
				String currentProperty = resultsArray[i]
				currentProperty = &quot;'&quot; + currentProperty + &quot;',&quot;
				resultsJSONObject.append(currentProperty)
			}

			def lastResult = resultsArray[resultsArray.length-1]
			String lastElement = &quot;'&quot; + lastResult + &quot;']}&quot;
			resultsJSONObject.append(lastElement)
			return resultsJSONObject.toString()
		} else {
			resultsJSONObject.append(&quot;]}&quot;)
		}
	}
</pre>
<p>This piece of functionality can be used across the Grails applications and can be resued heavily in a single application as well following the DRY principle.</p>
<p><strong>Conclusion</strong><br />
Following the same way of using a taglibrary and generic controller we can implement the other functionalities like rating objects, using adding favourites and many more using Grails dynamism.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/28/implementing-generic-functionality-in-grails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Integrating Spring 3 with JPA 2</title>
		<link>http://xebee.xebia.in/2010/08/27/integrating-spring-3-with-jpa-2/</link>
		<comments>http://xebee.xebia.in/2010/08/27/integrating-spring-3-with-jpa-2/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 12:20:20 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[JPA 2]]></category>
		<category><![CDATA[Spring 3]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4584</guid>
		<description><![CDATA[I have been working on Grails recently and am amazed with the productivity gains it gives. Grails is great for giving you a kick-start, it uses convention over configuration and gives you things such as ORM, transaction management, dependency injection among others, without you writing a single line of configuration. I decided to mimic the [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working on Grails recently and am amazed with the productivity gains it gives. Grails is great for giving you a kick-start, it uses convention over configuration and gives you things such as ORM, transaction management, dependency injection among others, without you writing a single line of configuration.</p>
<p>I decided to mimic the Grails behavior in a Spring + Hibernate application. To stay on the cutting edge I decided to use Hibernate 3.5 and Spring 3, to top it up I decided to use Hibernate as an implementation of JPA 2. Recently released, Hibernate 3.5 combines the Hibernate Annotations and the Hibernate Entity-Manager projects into Hibernate-Core, so basically its just one jar which provides the full implementation of JPA 2. For advantages of using JPA 2 see the excellent presentation here - <a href="http://jazoon.com/portals/0/Content/ArchivWebsite/jazoon.com/jazoon09/download/presentations/8461.pdf">http://jazoon.com/portals/0/Content/ArchivWebsite/jazoon.com/jazoon09/download/presentations/8461.pdf</a><br />
<span id="more-4584"></span></p>
<p><strong>Integrating Hibernate with JPA 2</strong></p>
<p>As usual, I started with a vanilla maven web project and started adding dependencies, the first being Hibernate - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;dependency&gt;
            &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
            &lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
            &lt;version&gt;3.5.4-Final&lt;/version&gt;
	&lt;/dependency&gt;
</pre>
<p>This dependency is found in the repository - <a href="https://repository.jboss.org/nexus/content/groups/public/">https://repository.jboss.org/nexus/content/groups/public/</a> as mentioned on the Hibernate site. After a lot of pain I found that this jar did not match the jar you from <a href="http://sourceforge.net/projects/hibernate/files/hibernate3">http://sourceforge.net/projects/hibernate/files/hibernate3</a>. So, I had to manually install the jar in my local repository (remember, I found this out after setting up JPA, Spring etc. which I will cover next). Similarly, in the JBoss repository I could not find the JPA 2 specfication jar (again available if you download the Hibernate distribution from sourceforge).I had to install that manually as well. After all this jiggery-pokery and some more, I somehow got Hibernate and JPA working.</p>
<p>JPA needs a persistence.xml file in META-INF folder in the classpath. I added META-INF folder in source/main/resources with persistence.xml reading as - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
	    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	    xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;
	    version=&quot;2.0&quot;&gt;
		&lt;persistence-unit name=&quot;postage&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
			&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
		&lt;/persistence-unit&gt;
	&lt;/persistence&gt;
</pre>
<p>So, here I basically tell JPA that Hibernate is providing its implementation. Plus I give my persistence-unit a name "postage" (the name of my application).</p>
<p><strong>Integrating Spring with JPA</strong></p>
<p>Now, I need to get Spring working with JPA and it is not exactly a cakewalk. With a lot of people pointing in different directions and the Spring documentation itself not very helpful in this particular aspect.</p>
<p>The Spring JPA support itself offers three ways of setting up the JPA EntityManagerFactory, so that it can be used by the application to obtain an entity manager. I chose the "LocalContainerEntityManagerFactoryBean" because it gives full control over EntityManagerFactory configuration and is appropriate for fine-grained customization, if required. Below is my config - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean id=&quot;entityManagerFactory&quot; class=&quot;org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean&quot;
		p:dataSource-ref=&quot;dataSource&quot;&gt;
		&lt;property name=&quot;jpaProperties&quot;&gt;
			&lt;props&gt;
				&lt;prop key=&quot;hibernate.dialect&quot;&gt;${hibernate.dialect}&lt;/prop&gt;
				&lt;prop key=&quot;hibernate.hbm2ddl.auto&quot;&gt;${hibernate.hbm2ddl.auto}&lt;/prop&gt;
				&lt;prop key=&quot;hibernate.show_sql&quot;&gt;${hibernate.show_sql}&lt;/prop&gt;
			&lt;/props&gt;
		&lt;/property&gt;
	&lt;/bean&gt;
</pre>
<p>As evident, you need a "dataSource" bean defined, which looks like - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean id=&quot;dataSource&quot; class=&quot;org.springframework.jdbc.datasource.DriverManagerDataSource&quot;
		p:driverClassName=&quot;${dataSource.driverClassName}&quot;
		p:url=&quot;${dataSource.url}&quot;
		p:username=&quot;${dataSource.username}&quot;
		p:password=&quot;${dataSource.password}&quot;
	/&gt;
</pre>
<p>To get the "${}" thingy working, i.e. a properties file lookup, add - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;context:property-placeholder location=&quot;classpath:datasource.properties&quot;/&gt;
</pre>
<p>datasource.properties can look like - </p>
<pre class="brush: java; title: ; notranslate">
	dataSource.driverClassName=org.hsqldb.jdbcDriver
	dataSource.url=jdbc:hsqldb:mem:postage
	dataSource.username=sa
	dataSource.password=
	#Hibernate Properties
	hibernate.hbm2ddl.auto=create-drop
	hibernate.dialect=org.hibernate.dialect.HSQLDialect
	hibernate.show_sql=true
</pre>
<p>To get transactions working, add - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;tx:annotation-driven/&gt;
</pre>
<p>And define a transaction manager - </p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean id=&quot;transactionManager&quot; class=&quot;org.springframework.orm.jpa.JpaTransactionManager&quot;
			p:entityManagerFactory-ref=&quot;entityManagerFactory&quot;
	/&gt;
</pre>
<p>Now, assuming that you have an Entity "Post", lets create the DAO - </p>
<pre class="brush: java; title: ; notranslate">
	@Repository
	@Transactional
	public class PostageDAOImpl implements PostageDAO {

		@PersistenceContext
		private EntityManager em;

		public void savePost(Post post){
			em.persist(post);
			em.flush();
		}

	}
</pre>
<p>The @Transactional annotation makes the DAO transactional (remember we added <tx:annotation-driven/>). Let's look at the other Annotations - @Repository annotation is a "stereotype" annotation added in Spring 2.5 which enables Spring to identify Beans for AOP pointcuts. In our case @Repository annotation also enables Spring to automatically convert JPA exceptions to Spring exception hierarchy. Finally, the EntityManager is automatically injected by Spring as it is annotated by @PersistenceContext. Also add - </p>
<pre class="brush: xml; title: ; notranslate">
      &lt;context:component-scan base-package=&quot;net.rocky.postage&quot;/&gt;
</pre>
<p>This tag enables dependency injection with annotations and also auto-detects stereotype classes in the specified package and registers the corresponding beans. </p>
<p>That's it! We have integrated Spring with JPA 2 and Hibernate. Let's write a test case to verify our setup - </p>
<pre class="brush: java; title: ; notranslate">
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(&quot;/applicationContext.xml&quot;)
public class PostageDAOImplTest {

	@Resource
	private PostageDAO postageDAOImpl;

	@Test
	public void testPostStorage() throws Exception {
		Post post = new Post();
		post.setComments(&quot;A simple comment&quot;);
		post.setDescription(&quot;A simple description&quot;);
		postageDAOImpl.savePost(post);
	}

...
</pre>
<p><strong>Parting thoughts</strong></p>
<p>This whole exercise took me a long time due to lack of comprehensive documentation, version mismatches and multiple approaches suggested by documents/bloggers. The advantage of the approach I have suggested above is that it allows you to switch to different databases for test/production as the datasource and dialect is specified in a .properties file.</p>
<p>The big idea behind this exercise was to setup a DAO and domain layer akin to Grails which can be easily scaled up. We can further add a service layer to access the data and then use it over a UI. For my next blog I will build on this and create a web application that uses GWT as the front-end.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/27/integrating-spring-3-with-jpa-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Android Content Providers</title>
		<link>http://xebee.xebia.in/2010/08/18/android-content-providers/</link>
		<comments>http://xebee.xebia.in/2010/08/18/android-content-providers/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 20:43:08 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Content Providers]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4536</guid>
		<description><![CDATA[The database in an Android application is available only to the application which created it. In normal scenarios, applications need to share data quiet frequently. There is a concept of content provider  in Android which can be used to share data between different applications. The content provider is a type of data store which has [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">The database in an Android application is available only to the application which created it. In normal scenarios, applications need to share data quiet frequently. There is a concept of content provider  in Android which can be used to share data between different applications. The content provider is a type of data store which has an URI. This URI is the signature of the content providers. The URI is used to get the handle to the content provider and perform operations on it.</p>
<p style="text-align: justify;">
<p style="text-align: justify;">Android comes with several in built content providers like call log info, contacts, medial files etc which provide information about the calls, the contacts and the media files stored. Each is having a URI through which the data inside them can be accessed.</p>
<p style="text-align: justify;">
<p style="text-align: justify;">You can also create your own content providers and assign an URI to it.  In this blog, we will create our own content provider and use it to insert/access data in/from it.</p>
<p style="text-align: justify;"><span id="more-4536"></span></p>
<p style="text-align: justify;">First of all we need to create a class which extends the ContentProvider class provided by Android.</p>
<pre class="brush: java; title: ; notranslate">
public class AddressProvider extends ContentProvider {

 public static final Uri CONTENT_URI = Uri.parse(&quot;content://com.example.AddressProvider&quot;);

 private SQLiteDatabase db;
 private String DATABASE_TABLE = &quot;address&quot;;

 @Override
 public boolean onCreate() {
      DatabaseHelper dbHelper = new DatabaseHelper(getContext());
      db = dbHelper.getWritableDatabase();
      return (db == null) ? false : true;
 }
 ...
}
</pre>
<p>Here we have extended the ContentProvider class and added instance variables for using database, and an URI which is the URI of the content provider. Then we have overridden the onCreate() to initialize the SQLiteDatabase db using DatabaseHelper which was created in my <a href="http://xebee.xebia.in/2010/08/16/database-implementation-in-android/">previous post about Android databases</a>.</p>
<p>The ContentProvider is an abstract class and subclassing it needs implementation for these five methods</p>
<p>getType()<br />
onCreate()<br />
query()<br />
insert()<br />
delete()<br />
update()</p>
<p>Implement all methods by the default implementation given by Eclipse(or other IDE). Then we will change the implementation for insert() and query(). insert() is used to insert record and query() is used to fetch data.</p>
<pre class="brush: java; title: ; notranslate">
@Override
 public Uri insert(Uri uri, ContentValues values) {

      long rowID = db.insert(DATABASE_TABLE, &quot;&quot;, values);

      if (rowID &gt; 0) {
           Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
           getContext().getContentResolver().notifyChange(_uri, null);
           return _uri;
      }
      throw new SQLException(&quot;Failed to insert row into &quot; + uri);
 }

 @Override
 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
      String[] columns = new String[] { “id”, “city”, “street”, “country”};
      return db.query(DATABASE_TABLE, columns, null, null, null, null, null);
 }
</pre>
<p>The implementation of insert() and delete simply uses the db instantiated in onCreate() to insert/fetch the record. The insert() then notifies other users using the content provider about the insertion of a row in the table.</p>
<p>This content provider resembles a service in Service Oriented Architecture(SOA). For this we need to change the AndroidManifest.xml. This is just like publishing an wsdl for web services. Add the content provider as a provider  in AndroidManifest.xml.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
      &lt;activity android:name=&quot;.AddressProviderActivity&quot; android:label=&quot;@string/app_name1&quot;&gt;
           ...
      &lt;/activity&gt;
      &lt;provider android:name=&quot;AddressProvider&quot; android:authorities=&quot;com.example.AddressProvider&quot; /&gt;
&lt;/application&gt;
</pre>
<p>Suppose any Activity wants to access the address db through this service provider. The Activity can use getContentResolver() method to get the handle to the provider. To insert a row from an activtiy we just need to call the insert() using getContentResolver().</p>
<pre class="brush: java; title: ; notranslate">
private void insert(AddressDAO addressDAO) {
      ContentValues values = new ContentValues();
      values.put(&quot;city&quot;, &quot;Gurgaon&quot;);
      values.put(&quot;street&quot;, &quot;sector 14&quot;);
      values.put(&quot;country&quot;, &quot;India&quot;);
      getContentResolver().insert(AddressProvider.CONTENT_URI, values);
 }
</pre>
<p>Same is the case for fetching the data.</p>
<pre class="brush: java; title: ; notranslate">
private void get(AddressDAO addressDAO) {
     Cursor c = getContentResolver().query(AddressProvider.CONTENT_URI, null, null, null, null);
     if (c.moveToFirst())
          DisplayAddress(c);
     else
          Toast.makeText(this, &quot;No address found&quot;, Toast.LENGTH_LONG).show();
     }

public void DisplayAddress(Cursor c) {
     final EditText editText = (EditText) findViewById(R.id.EditText01);
     editText.setText(new String(c.getString(2)));
     Toast.makeText(this,
     &quot;id: &quot; + c.getString(0) + &quot;\n&quot; +
     &quot;ISBN: &quot; + c.getString(1) + &quot;\n&quot; +
     &quot;TITLE: &quot; + c.getString(2) + &quot;\n&quot; +
     &quot;PUBLISHER:  &quot;+ c.getString(3),
     Toast.LENGTH_LONG).show();
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/18/android-content-providers/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Performace Testing made easy using Badboy and JMeter</title>
		<link>http://xebee.xebia.in/2010/08/17/performace-testing-made-easy-using-badboy-and-jmeter/</link>
		<comments>http://xebee.xebia.in/2010/08/17/performace-testing-made-easy-using-badboy-and-jmeter/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 10:35:13 +0000</pubDate>
		<dc:creator>Harsh</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Badboy]]></category>
		<category><![CDATA[JMeter]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4365</guid>
		<description><![CDATA[When it comes to performance testing and especially using open source tools such as JMeter, it is often observed that testers(especially from black box background) have a hard time. For simple scenarios such as analyzing performance of different pages in a website wherein the pages can be directly accessed through URL directly, writing JMeter scripts [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to performance testing and especially using open source tools such as <a href="http://jakarta.apache.org/jmeter/" target="_blank">JMeter</a>, it is often observed that testers(especially from black box background) have a hard time. For simple scenarios such as analyzing performance of different pages in a website wherein the pages can be directly accessed through URL directly, writing JMeter scripts is fairly simple. But even for these simple test cases testers sometimes avoid writing the JMeter scripts themselves and often pair up with developers. Coming from a background of record &amp; playback tools, testers find it inconvenient to write JMeter scripts. Fortunately, <a href="http://www.badboysoftware.biz" target="_blank">Badboy</a> solves most of the problems which are stated above. Testers can simply record the flow in Badboy and export the script as JMeter script which can be easily run in JMeter.Here in this blog, using a simple example I'll explain how we can record the flow in Badboy, export and run in JMeter.<span id="more-4365"></span></p>
<p>Let's take a scenario of analyzing performance for logging in gmail, and logging out. If we try to write this in JMeter, it could be bit complicated as we have to add some parameters, change the request type (to POST) and other things such as we cannot access the pages directly by typing the URL. But in Badboy it is fairly easy, simply press record button, navigate to different pages as a normal user and finally export the test as JMeter. So lets look at this step by step:-</p>
<p><strong>1.</strong> Download the latest version of Badboy from <a href="http://www.badboy.com.au/download" target="_blank">here</a> and install.</p>
<p><strong>2.</strong> Record the flow in Badboy, by clicking on the record button, typing the url and navigating through different pages.<br />
<a href="http://xebee.xebia.in/wp-content/uploads/2010/08/1.jpg"><img class="alignleft size-large wp-image-4481" title="Record Flow in BadBoy" src="http://xebee.xebia.in/wp-content/uploads/2010/08/1-1024x424.jpg" alt="" width="679" height="297" /></a></p>
<p><strong>3.</strong> Export to JMeter and save the .jmx script<a href="http://xebee.xebia.in/wp-content/uploads/2010/08/2.jpg"><img class="alignleft size-large wp-image-4501" title="Export to JMeter" src="http://xebee.xebia.in/wp-content/uploads/2010/08/2-1024x640.jpg" alt="" width="677" height="248" /></a></p>
<p><strong>4. </strong>Open the Exported Script in JMeter. Sometimes the latest version (jmeter 2.4 ) fails to import the exported file, so import the file in an older version of JMeter (jmeter 2.3)</p>
<p><strong>5.</strong> Set the Thread Properties in Thread Group. Click on Thread Group in Left Panel and set the number of threads, ramp up period &amp; loop count.<a href="http://xebee.xebia.in/wp-content/uploads/2010/08/3.jpg"><img class="alignleft size-large wp-image-4503" title="Thread Group" src="http://xebee.xebia.in/wp-content/uploads/2010/08/3-1024x533.jpg" alt="" width="684" height="373" /></a></p>
<p><strong>6.</strong> Add Graphs by right clicking on Thread Group &amp; adding a listener.<a href="http://xebee.xebia.in/wp-content/uploads/2010/08/4.jpg"><img class="alignleft size-large wp-image-4506" title="Graph Result" src="http://xebee.xebia.in/wp-content/uploads/2010/08/4-1024x537.jpg" alt="" width="681" height="376" /></a></p>
<p><strong>7. </strong>Run the JMeter Test.</p>
<p><strong>8.</strong> Click the Graph Results to view the graphs and analyze the performance of the application under test.<br />
<a href="http://xebee.xebia.in/wp-content/uploads/2010/08/5.jpg"><img class="alignleft size-large wp-image-4512" title="Graph Results" src="http://xebee.xebia.in/wp-content/uploads/2010/08/5-1024x639.jpg" alt="" width="679" height="447" /></a></p>
<p>Unfortunately Jscripts &amp; data sources created in Badboy are not supported when exported to JMeter. But again these features are for advanced users who can create the complicated scripts in JMeter itself. Also ,we can do a performance testing in Badboy but Badboy does not have very good performance analysis capability which is there in JMeter. Different types of listeners then can be added in JMeter (such as Graphs, Aggregate Report, etc) to get a good performance report after exporting a script from Badboy.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/17/performace-testing-made-easy-using-badboy-and-jmeter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Scrolling text in JavaFx</title>
		<link>http://xebee.xebia.in/2010/08/16/javafx-text-animations-marquee-effect-auto-scrolling-text-down-to-up-and-left-to-right/</link>
		<comments>http://xebee.xebia.in/2010/08/16/javafx-text-animations-marquee-effect-auto-scrolling-text-down-to-up-and-left-to-right/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 12:50:52 +0000</pubDate>
		<dc:creator>Richa Singhal</dc:creator>
				<category><![CDATA[Creativity]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[Scrolling]]></category>
		<category><![CDATA[swing]]></category>
		<category><![CDATA[text]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4453</guid>
		<description><![CDATA[If you want to have Marquee effect i.e automatic scrolling of text from left to right or down to up in JavaFx, you need to write a custom component of your own. Using a Marquee tag of HTML doesn't work, if you try to use directly in a label text or a swing component in [...]]]></description>
			<content:encoded><![CDATA[<p>If you want to have Marquee effect i.e automatic scrolling of text from left to right or down to up in JavaFx, you need to write a custom component of your own.</p>
<p>Using a <span style="color: #ff0000;">Marquee tag of HTML doesn't work</span>, if you try to use directly in a label text or a swing component <span style="color: #ff0000;">in JavaFx</span>, unlike other html tags which works fine.</p>
<p>The easiest way is to extend your <strong>ScrollingText</strong> class with <span style="color: #000080;"><em>javafx.scene.CustomNode</em></span> class and animate it by changing the component's co-ordinates using <span style="color: #000080;"><em>javafx.animation.Timeline</em></span> and <em><span style="color: #000080;">javafx.animation.KeyFrame </span></em>classes;</p>
<p>The following<span style="color: #000080;"> <strong>TextScroll.fx</strong> </span>file acts a scrolling text custom class :</p>
<p><span id="more-4453"></span></p>
<pre class="brush: java; title: ; notranslate">

import javafx.animation.KeyFrame;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.scene.shape.Rectangle;
import javafx.animation.Timeline;

public class TextScroll extends CustomNode
{
    public var x: Number;
    public var y: Number;
    public var width: Number;
    public var height: Number;
    public var stroke: Paint;
    public var strokeWidth: Number;
    public var delay = 10ms;
    var scrollingText: Text;

    public var text: String on replace
    {
        if (isScrollingText ())
            scrollingText.translateY = 0.0;
    }
    override public function create(): Node
    {
        Group
        {
            content:
            [
                scrollingText = Text
                {
                    content: bind text
                    textOrigin: TextOrigin.TOP
                    x: bind x
                    y: bind y+(height-10)/2
                }
            ]
            clip: Rectangle
            {
                x: x
                y: y
                width: bind width
                height: bind height
            }
        }
    }

    public function isScrollingText ()
    {
        autoTimer.running
    }

    public function scrollUp ()
    {
       autoTimer.play();
    }

    public function stopScrolling ()
    {
        autoTimer.stop ()
    }

     var autoTimer = Timeline
    {
        repeatCount: Timeline.INDEFINITE

        keyFrames:
        [
            KeyFrame
            {
                time: delay
                action: function ()
                {
                    if (scrollingText.translateY+height &lt; 0)
                    {
                        scrollingText.translateY = 0.0;
                        return
                    }
                    scrollingText.translateY -= 0.5
                }
            }
        ]
    }

}
</pre>
<p>Variable delay (line number 19 in TextScroll.fx) controls the speed of the scrolling.<br />
Now, to use this animation, you can use the following code snippet which declares a text line that you want to scroll up automatically.</p>
<p>file <strong>DemoScrollingText.fx</strong></p>
<pre class="brush: java; title: ; notranslate">
import com.utility.TextScroll;
...
var textScrollerObj = TextScroll
{
     text: &quot;Hi!! This text scrolls down to up automatically...&quot;;
     width: 500;
     height: 200;
     stroke: Color.BLACK
     strokeWidth: 1.0
     fill: Color.BLACK
}
....
...
</pre>
<p>after that, just initiate the scrolling of your text by calling the <span style="color: #000080;"><em>scrollUp()</em></span> and stop by <span style="color: #000080;"><em>stopScrolling()</em></span> function of your TextScroll class.</p>
<pre class="brush: java; title: ; notranslate">
button = Button {
     strong:true;
     text :&quot;Scroll Text&quot;'
     action: function(){
     textScrollerObj.scrollUp();
  }
}
</pre>
<p>You can change the direction of text scroll from right to left by changing the TextScroll file as:</p>
<pre class="brush: java; title: ; notranslate">
...
textRef = Text
{
...
x: bind x+width
y: bind y+(height-10)/2
}
...
action: function ()
{
if (scrollingText.translateX+width &amp;amp;lt; 0)
{
     scrollingText.translateX = 0.0;
     return
}
     scrollingText.translateX -= 0.5
}
</pre>
<p>Optionally, you can add text effects like shadow to this text and encapsulate this in a Frame or Rectangle and bind its coordinates with your TextScroll's coordinates.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/16/javafx-text-animations-marquee-effect-auto-scrolling-text-down-to-up-and-left-to-right/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database implementation in Android</title>
		<link>http://xebee.xebia.in/2010/08/16/database-implementation-in-android/</link>
		<comments>http://xebee.xebia.in/2010/08/16/database-implementation-in-android/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 19:29:39 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4435</guid>
		<description><![CDATA[Android uses SQLLite, which is an open source SQL database system for storing persistent data. The database that you create for an application is only accessible to itself, others applications won’t be able to access it. Android provides API’s to interact with the database which are quite easy to use. The performance of the database [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Android uses SQLLite, which is an open source SQL database system for storing persistent data. The database that you create for an application is only accessible to itself, others applications won’t be able to access it. Android provides API’s to interact with the database which are quite easy to use. The performance of the database also seems to be good.</p>
<p style="text-align: justify;">In this post we will be creating the DatabaseUtility classes which will encapsulate the database centric functionality. Then we will use the utility to create more specific DAO classes which will encapsulate more fine grained functions of talking to the database.</p>
<p style="text-align: justify;">Let's start with the creation of the database utility. First of all we need to extend the SQLiteOpenHelper class.</p>
<blockquote><pre class="brush: java; title: ; notranslate">
public class DatabaseHelper extends SQLiteOpenHelper {

 static final String DATABASE_NAME = &quot;records&quot;;
 static final int DATABASE_VERSION = 1;

 static final String TABLE_CREATE = &quot;create table address (id integer primary key autoincrement, &quot; + &quot;city text not null, street text not null,     &quot; + &quot;country text not null);&quot;;

 DatabaseHelper(Context context) {
      super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {
      db.execSQL(TABLE_CREATE);
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      db.execSQL(&quot;DROP TABLE IF EXISTS address&quot;);
      onCreate(db);
 }
}
</pre>
<p><span id="more-4435"></span></p></blockquote>
<p style="text-align: justify;">It requires a constructor taking a context. The context in our case will be the Activity from which the DatabaseHelper will be created.  The super constructor is called with the database name and database version. If the database asked does not exists, then a new database is created. The onCreate() and onUpgrade() methods are also needed. The onCreate() method is a callback method used to create the database and the other callback method onUpgrade() is used to delete the old table and create new if a new version of database is specified.</p>
<p style="text-align: justify;">The onCreate() here simply executes a sql query to create the table. The onUpgrade() drops the already existing table and creates a new one.</p>
<p style="text-align: justify;">Now we have a database and table created. We will proceed to insert data into the table. For this we will create an AddressDAO class which will operate on the address table created using the DatabaseHelper class.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public class AddressDAO {

static final String TABLE_NAME = &quot;address&quot;;

static final String ID = &quot;id&quot;;
static final String CITY = &quot;city&quot;;
static final String STREET = &quot;street&quot;;
static final String COUNTRY = &quot;country&quot;;

private final Context androidContext;

private DatabaseHelper databaseHelper;
private SQLiteDatabase db;

public AddressDAO(Context ctx) {
     this.androidContext = ctx;
     databaseHelper = new DatabaseHelper(androidContext);
}

...
}
</pre>
</blockquote>
<p style="text-align: justify;">Here we have created variables like table name, column names , the context and a constructor used to instantiate the DatabaseHelper. The DatabaseHelper’s instantiation ensures the presense of an address table.</p>
<p style="text-align: justify;">Now we can insert utility methods in the AddressDAO. Let’s start with opening the databse. The open() simple gets a writeble database using the DatabaseHelper’s superclass’s methods. The close simply closes the writeble database.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public void open() throws SQLException {
     db = databaseHelper.getWritableDatabase();
}
</pre>
<pre class="brush: java; title: ; notranslate">

public void close() {
     databaseHelper.close();
}
</pre>
</blockquote>
<p style="text-align: justify;">The insert method will insert city,street, and country in their respective columns. It uses ContentValues classes which stores data as key value pairs. The key being the column name and the value being the data to be stored in that column. It uses databaseHelper’s insert method, which asks for the table name and the values to be inserted.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public long insert(String city, String street, String country) {
     ContentValues values = new ContentValues();
     values.put(CITY, city);
     values.put(STREET, street);
     values.put(COUNTRY, country);
     return db.insert(TABLE_NAME, null, values);
}
</pre>
</blockquote>
<p>Next we will implement the delete method. The delete method needs the table name, and the where clause. In our case we delete by id.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public boolean delete(long id) {
     String whereClause = ID + &quot;=&quot; + id;
     return db.delete(TABLE_NAME, whereClause, null) &gt; 0;
}
</pre>
</blockquote>
<p style="text-align: justify;">Now we will implement the get method. It takes the id as parameter and gets by id. The columns to be extracted can be specified in a String array. It also has a where clause. The query method returns a Cursor object. The cursor.moveToFirst() method ensures that it points to the object found, if it has.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public Cursor get(long id) throws SQLException {
     String[] columns = new String[] { ID, CITY, STREET, COUNTRY };
     String whereClause = ID + &quot;=&quot; + id;
     Cursor mCursor = db.query(true, TABLE_NAME, columns, whereClause, null, null, null, null, null);
     if (mCursor != null) {
          mCursor.moveToFirst();
     }
     return mCursor;
}
</pre>
</blockquote>
<p style="text-align: justify;">The getAll method is same as get() other than it doesn’t has any where clause. The Cursor object returned has methods like moveToFirst(), moveToNext(), moveToLast() which can be used to iterate over the list obtained.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public Cursor getAll() {
     String[] columns = new String[] { ID, CITY, STREET, COUNTRY };
     return db.query(TABLE_NAME, columns, null, null, null, null, null);
}
</pre>
</blockquote>
<p>The update method is same as the insert method, other than that it has a where clause.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public boolean update(long id, String city, String street, String country) {
     ContentValues values = new ContentValues();
     values.put(CITY, city);
     values.put(STREET, street);
     values.put(COUNTRY, country);
     String whereClause = ID + &quot;=&quot; + id;
     return db.update(TABLE_NAME, values, whereClause, null) &gt; 0;
}
</pre>
</blockquote>
<p>To test this code you can create an Activity which uses its onCreate() to initialize the AddressDao. Then insert, get and delete an object using the AddressDAO.</p>
<blockquote><pre class="brush: java; title: ; notranslate">

public class AddressActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     AddressDAO addressDAO = new AddressDAO(this);
     insert(addressDAO);
     get(addressDAO);
     delete(addressDAO);
}

private void insert(AddressDAO addressDAO) {
     addressDAO.open();
     long id = addressDAO.insert(&quot;Gurgaon&quot;, &quot;Sector 14&quot;, &quot;India&quot;);
     addressDAO.close();
}

private void get(AddressDAO addressDAO) {
     addressDAO.open();
     Cursor c = addressDAO.get(1);
     if (c.moveToFirst())
          DisplayAddress(c);
     else
          Toast.makeText(this, &quot;No address found&quot;, Toast.LENGTH_LONG).show();
     addressDAO.close();
}

private void delete(AddressDAO addressDAO) {
     addressDAO.open();
     if (addressDAO.delete(1))
          Toast.makeText(this, &quot;Delete successful.&quot;, Toast.LENGTH_LONG).show();
     else
          Toast.makeText(this, &quot;Delete failed.&quot;, Toast.LENGTH_LONG).show();

     addressDAO.close();
}

public void DisplayAddress(Cursor c) {
     final EditText editText = (EditText) findViewById(R.id.EditText01);
     editText.setText(new String(c.getString(2)));
     Toast.makeText(this, &quot;id: &quot; + c.getString(0) + &quot; &quot; + &quot;CITY: &quot; + c.getString(1) + &quot; &quot; + &quot;STREET: &quot; + c.getString(2) + &quot;\n&quot; + &quot;COUNTRY:  &quot;
     + c.getString(3), Toast.LENGTH_LONG).show();
}
}
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/16/database-implementation-in-android/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Content and Metadata Extraction with Apache Tika</title>
		<link>http://xebee.xebia.in/2010/08/13/content-and-metadata-extraction-with-apache-tika/</link>
		<comments>http://xebee.xebia.in/2010/08/13/content-and-metadata-extraction-with-apache-tika/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 10:57:45 +0000</pubDate>
		<dc:creator>Rahul Sharma</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4324</guid>
		<description><![CDATA[Often we  have the requirement of reading different types of files e.g. CSV, PDF, XLS files and there can be  many more types need to be read in an application. One way, we try to implement such a requirement is by using separate readers for all of them and  may use different frameworks for analyzing [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Often we  have the requirement of reading different types of files e.g. CSV, PDF, XLS files and there can be  many more types need to be read in an  application.</p>
<p style="text-align: justify;">One way, we try to implement such a requirement is by  using separate readers for all of them and  may use different frameworks for  analyzing each of them e.g. if our application requires PDF, XML and XLS file parsing, we can create a FileReader interface. Then we can  have different implementations of this interface for each of the types and use PDFBox for reading PDF files, Apache POI for XLS files and SAX for XML  files.<span id="more-4324"></span></p>
<pre class="brush: java; title: ; notranslate">
// Read PDF using PDFBox
PDDocument pdDoc = new PDDocument(cosDoc);
PDFTextStripper stripper = new PDFTextStripper();
String docText = stripper.getText(pdDoc);
.......
//Read XLS using POI
POIFSFileSystem fileSystem = new POIFSFileSystem(is);
HSSFWorkbook workBook = new HSSFWorkbook(fileSystem);
....`
// Read XML using  SAX
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
</pre>
<p>This poses additional set of issues like :</p>
<ul>
<li>We must configure each and every type separately.</li>
<li>We may be using different APIs for reading different types, this poses additional challenge of  learning and configuring separate APIs for each of types.</li>
</ul>
<p>As the list of types  that your application needs to handle grows, these two issues become more and more visible.</p>
<h3>Solution : <a href="http://tika.apache.org/">Apache Tika</a></h3>
<p style="text-align: justify;"><a href="http://tika.apache.org/">Apache Tika</a> is one project that can assist in reducing, if not eliminating, these pains. The projects site suggests :</p>
<p style="padding-left: 60px; text-align: justify;">"<em>Apache  Tika as toolkit for detecting and extracting meta-data and  structured  text content from various documents using existing parser  libraries</em>"</p>
<p style="text-align: justify;">Basically  the Tika API is a single shot API to read data from multiple types,  internally it configures and uses the various existing libraries for  reading the data eg. POI for Excel stuff.</p>
<h4><strong>The Parser API</strong></h4>
<p style="text-align: justify;">The <a href="http://tika.apache.org/0.7/api/org/apache/tika/parser/Parser.html">Parser</a> interface is the key component of  Tika library, that can be used to parse data . You need to create an instance of  <a href="http://tika.apache.org/0.7/api/org/apache/tika/parser/Parser.html">Parser</a> and call the parse API to get the required data.  The project currently  supports around 14 different formats e.g. text,  pdf,  audio, video,  image, archives, ms-office, xmls, emails etc. For  each of the  supported  format the package has a <a href="http://tika.apache.org/0.7/api/org/apache/tika/parser/Parser.html">Parser </a>which  it employs to read the format. You can either use each of these  different parsers for reading different types of data or the API also  provides a <a href="http://tika.apache.org/0.7/api/org/apache/tika/parser/AutoDetectParser.html">AutoDetectParser</a> that can detect the type of stream and  use the corresponding parser.</p>
<p style="text-align: justify;">The  Parser.parse method takes the stream, related meta-data                      as input and a few more arguments, and outputs the results and extra                      meta-data. The API is not concerned about the specs  of the stream i.e. how it is  opened etc. The code using the Parser  should take care of the stream  maintenance i.e opening and closing.</p>
<pre class="brush: java; title: ; notranslate">
@Test
public void testPDFParser() throws Exception {
 String resourceLocation = &amp;quot;Tika.pdf&amp;quot;;
 InputStream input = this.getClass().getClassLoader().getResourceAsStream(resourceLocation);
 ContentHandler textHandler = new BodyContentHandler();
 Metadata metadata = new Metadata();
 PDFParser parser = new PDFParser();
 parser.parse(input, textHandler, metadata, new ParseContext());
 input.close();
 System.out.println(&amp;quot;Title: &amp;quot; + metadata.get(&amp;quot;title&amp;quot;));
 System.out.println(&amp;quot;Author: &amp;quot; + metadata.get(&amp;quot;Author&amp;quot;));
 System.out.println(&amp;quot;format: &amp;quot; + metadata.get(&amp;quot;source&amp;quot;));
 System.out.println(&amp;quot;content: &amp;quot; + textHandler.toString());
}
@Test
public void testAutoDetectParser() throws Exception {
 InputStream input = this.getClass().getResourceAsStream(&amp;quot;TestTikaAPI.class&amp;quot;);
 ContentHandler textHandler = new BodyContentHandler();
 Metadata metadata = new Metadata();
 Parser parser = new AutoDetectParser();
 parser.parse(input, textHandler, metadata, new ParseContext());
 input.close();
 System.out.println(&amp;quot;Title: &amp;quot; + metadata.get(&amp;quot;title&amp;quot;));
 System.out.println(&amp;quot;Author: &amp;quot; + metadata.get(&amp;quot;Author&amp;quot;));
 }
</pre>
<h4>The Value-Adds</h4>
<p style="text-align: justify;">The Parser API gives back meta data that confirms to various metadata formats like <a href="http://dublincore.org/">Dublin core</a> and <a href="http://creativecommons.org/">Creative commons</a>. If you are not concerned with the meta-data then you can use the simpler <a href="http://tika.apache.org/0.7/api/org/apache/tika/utils/ParseUtils.html">ParseUtils </a>API for extracting only text.</p>
<pre class="brush: java; title: ; notranslate">
@Test
public void testTikaParserUtils() throws Exception {
 String resourceLocation = &amp;quot;target/test-classes/Tika_EN.txt&amp;quot;;
 String content = ParseUtils.getStringContent(new File(resourceLocation), new TikaConfig());
 System.out.println(content);
}
</pre>
<p style="text-align: justify;">The API also provides a bunch of value add APIs like  language detection, stream detection etc.</p>
<pre class="brush: java; title: ; notranslate">
@Test
public void testTypeDetector() throws Exception {
 String resourceLocation = &amp;quot;Tika.pdf&amp;quot;;
 InputStream input = this.getClass().getClassLoader().getResourceAsStream(resourceLocation);
 Detector detector = new TypeDetector();
 MediaType media = detector.detect(input, new Metadata());
 System.out.println(&amp;quot;Extact Type: &amp;quot; + media.getType());
 System.out.println(&amp;quot;Sub Type: &amp;quot; + media.getBaseType());
 }

@Test
public void testLanguageIdentifier() throws Exception {
 String resourceLocation = &amp;quot;Tika_EN.txt&amp;quot;;
 InputStream input = this.getClass().getClassLoader().getResourceAsStream(resourceLocation);
 ContentHandler textHandler = new BodyContentHandler();
 Metadata metadata = new Metadata();
 Parser parser = new AutoDetectParser();
 parser.parse(input, textHandler, metadata, new ParseContext());
 input.close();
 LanguageIdentifier languageIdentifier = new LanguageIdentifier(textHandler.toString());
 System.out.println(&amp;quot;found language :&amp;quot;+ languageIdentifier.getLanguage() + &amp;quot; certainity : &amp;quot; + languageIdentifier.isReasonablyCertain());
 }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/13/content-and-metadata-extraction-with-apache-tika/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XML communication between Tapestry and Flex</title>
		<link>http://xebee.xebia.in/2010/08/11/xml-communication-between-tapestry-and-flex/</link>
		<comments>http://xebee.xebia.in/2010/08/11/xml-communication-between-tapestry-and-flex/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 08:12:06 +0000</pubDate>
		<dc:creator>Iti Agarwal</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[tapestry]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[flex integration]]></category>
		<category><![CDATA[Tapestry 5]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4195</guid>
		<description><![CDATA[How to get your swf talking to your tapestry application using xml: In this writeup, we will look at how we can send xml data using tapestry pages and use this in a swf object. We will consider the following are already in place: 1. A tapestry application that needs to send the xml 2. [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<h1>How to get your swf talking to your tapestry application using xml:</h1>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">In this writeup, we will look at how we can send xml data using tapestry pages and use this in a swf object.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">We will consider the following are already in place:</div>
<div id="_mcePaste" style="background: none repeat scroll 0% 0% #e7d3ec; border: 1px solid; padding: 5px; margin: 5px 0px; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">1. A tapestry application that needs to send the xml</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">2. A swf object which needs to use the xml.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">There are 2 things that you will need now:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">1. The tapestry page which will send xml data</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">To send xml from tapestry page we need the following:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">1. A usual Tapestry style Java class with a special modification:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<pre class="brush: java; title: ; notranslate">&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;@ContentType(&quot;application/xml&quot;)// this will define that this class in xml type&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;public class ICanSendXML {&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;@Property&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;private String property1;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;@Property&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;private String property2;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;p&gt;</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">2. The tapestry style ICanSendXML.tml file which looks something like this:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<pre class="brush: xml; title: ; notranslate">&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;?xml version=&quot;1.0&quot;?&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;
&lt;properties&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;
&lt;property1&gt;${property1}&lt;/property1&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;
&lt;property2&gt;${property2}&lt;/property2&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;....&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;/properties&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;p&gt;</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">2. The flex that calls this page to read the xml.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">This can be achieved in the following manner:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">1. Declare an Http Service which calls our tapestry page:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">&lt;/pre&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;mx:HTTPService&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;id=&quot;xmlFromTapestry&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;url=&quot;http://localhost:8080/myTapestryAppThatSendsXML/ICanSendXML&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;resultFormat=&quot;e4x&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;result=&quot;loadPropertiesResultHandler(event);&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;fault=&quot;loadPropertiesFaultHandler(event);&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/&gt;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;p&gt;</p>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">2. call this httpService on some event such as creationComplete</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">&lt;/pre&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; xmlns:components=&quot;components.*&quot; layout=&quot;absolute&quot;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;creationComplete=&quot;loadProperties()&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;mx:Script&gt;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;private function loadProperties():void{&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;xmlFromTapestry.send();&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;}&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;/mx:Script&gt;&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;p&gt;</p>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">3. Handle the success and failure events:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">&lt;/pre&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;private function loadPropertiesResultHandler(event:ResultEvent):void{&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;// now do something with the xml&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;var properties:XML = XML(event.result);&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;.....&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;.....&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;.....&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;}&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;private function loadGroupFaultHandler(event:FaultEvent):void&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;{&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;Alert.show(event.fault.message, &quot;Could not load properties.&quot;);&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;}&lt;/div&gt;<br />
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;p&gt;</p>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">Thats it. <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </div>
<h2><span style="font-weight: normal; font-size: 13px;">Many a times we may need to use a flex component in our Tapestry based application. In such a scenario, we will need a neat way to send data from the Tapestry page to the embedded Flex object. For example, we may need too use Tapestry's localization capabilities in the Flex application.  A very simple way of achieving it can be using XML.</span></h2>
<p>A tapestry page can be used to send xml data which can then be read in the flex application. This can greatly simplify things in comparison to web-services and also make it much cleaner than using external interfaces. In this blog, we will look at how we can harness this.<span id="more-4195"></span></p>
<p><span style="color: #800080;">We will consider the following are already in place:</span></p>
<p><span style="color: #000000;">1. A Tapestry application that needs to send the xml</span></p>
<p><span style="color: #000000;">2. A Flex application that needs to use the xml.</span></p>
<p><span style="color: #000000;"> </span></p>
<p>There are 2 things that you will need now:</p>
<h4>1. A Tapestry page which will send xml data</h4>
<p>To send xml from tapestry page we need the following:</p>
<h5><span style="color: #800080;">1. A usual Tapestry style Java class with a special modification:</span></h5>
<pre class="brush: java; title: ; notranslate">
@ContentType(&quot;application/xml&quot;)// this will define that this class in xml type
public class ICanSendXML {
  @Property
  private String property1;
  @Property
  private String property2;
  ....
  ....
  ....
  ....
}
</pre>
<h5><span style="color: #800080;">2. The tapestry style ICanSendXML.tml file which looks something like this:</span></h5>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot;?&gt;
 &lt;properties&gt;
  &lt;property1&gt;${property1}&lt;/property1&gt;
  &lt;property2&gt;${property2}&lt;/property2&gt;
  &lt;localizedString1&gt;${message:aLocalizedStringMessage}&lt;/localizedString1&gt;
  ....
  ....
  ....
 &lt;/properties&gt;
</pre>
<h4>2. A Flex application that calls this page to read the xml.</h4>
<p>This can be achieved in the following manner:</p>
<h5><span style="color: #800080;">1. Declare an Http Service which calls our tapestry page:</span></h5>
<pre class="brush: xml; title: ; notranslate">
&lt;mx:HTTPService id=&quot;xmlFromTapestry&quot; url=&quot;http://localhost:8080/myTapestryAppThatSendsXML/ICanSendXML&quot; resultFormat=&quot;e4x&quot; result=&quot;loadPropertiesResultHandler(event);&quot; fault=&quot;loadPropertiesFaultHandler(event);&quot; /&gt;
</pre>
<h5><span style="color: #800080;">2. call this httpService on some event such as creationComplete</span></h5>
<pre class="brush: xml; title: ; notranslate">
&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; xmlns:components=&quot;components.*&quot; layout=&quot;absolute&quot; creationComplete=&quot;loadProperties()&quot;&gt;
&lt;mx:Script&gt;
  private function loadProperties():void{
    xmlFromTapestry.send();
  }
&lt;/mx:Script&gt;
</pre>
<h5><span style="color: #800080;">3. Handle the success and failure events:</span></h5>
<pre class="brush: jscript; title: ; notranslate">
private function loadPropertiesResultHandler(event:ResultEvent):void{
  // now do something with the xml
  var properties:XML = XML(event.result);
  .....
  .....
  .....
}
private function loadPropertiesFaultHandler(event:FaultEvent):void
{
  Alert.show(event.fault.message, &quot;Could not load properties.&quot;);
}
</pre>
<p>Thats it. <img src='http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/11/xml-communication-between-tapestry-and-flex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Processing Custom Annotations</title>
		<link>http://xebee.xebia.in/2010/08/09/processing-custom-annotations/</link>
		<comments>http://xebee.xebia.in/2010/08/09/processing-custom-annotations/#comments</comments>
		<pubDate>Mon, 09 Aug 2010 07:39:55 +0000</pubDate>
		<dc:creator>Jayant Dhingra</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4263</guid>
		<description><![CDATA[How to write custom annotations using APT? Annotations provide data about a program that is not part of the program itself. The more advanced uses of annotations include writing an annotation processor that can read a Java program and take actions based on its annotations. To facilitate this task, release 5.0 of the JDK includes [...]]]></description>
			<content:encoded><![CDATA[<p><strong>How to write custom annotations using APT?</strong><br />
<br>
<div>
Annotations provide data about a program that is not part of the program itself. The more advanced uses of annotations include writing an annotation processor that can read a Java program and take actions based on its annotations. To facilitate this task, release 5.0 of the JDK includes an annotation processing tool, called apt. In release 6 of the JDK, the functionality of apt is a standard part of the Java compiler.<br />
<span id="more-4263"></span></p>
<div style="width: 700px; text-align: left; margin-left: 0px;">
<br><strong>Using APT-Annotation Processing Tool</strong></p>
<ol>
<li> JDK tool for processing source annotations</li>
<li> cleaner model of source and types than doclet</li>
<li> support recursive processing of generated files</li>
<li> Multiple processors (vs single doclet)</li>
</ol>
</div>
<p>Each processor implements the <em>AnnotationProcessor</em> interface in the package com.sun.mirror.apt. This interface has one method i.e. process used by the apt tool to invoke the processor. A processor will "process" one or more annotation types. A processor instance is returned by its corresponding factory - an <em>AnnotationProcessorFactory</em>. The apt tool calls the factory's <em>getProcessorFor</em> method to get hold of the processor. During this call, the tool provides an <em>AnnotationProcessorEnvironment</em>. In the environment the processor will find everything it needs to get started, including references to the program structure on which it is operating, and the means to communicate and cooperate with the apt tool by creating new files and passing on warning and error messages.</p>
<p><strong>Steps for creating a custom processor</strong></p>
<ol>
<li> Write an annotation processor, extends <em>AbstractProcessor</em>
<ul>
<li> Provide implementation for <em>process </em>method-public void process();</li>
<li> Implement the annotation processing logic</li>
<li> Use environment from <em>AnnotationProcessorFactory</em>; iterate through types being processed</li>
</ul>
</li>
<li>add tools.jar to classpath</li>
<li>Invoke apt</li>
<li>Use Mirror packages for representing types and processing declaration and types.</li>
</ol>
<p><strong>APT Configuration</strong></p>
<ol>
<li> Configuration is done by creating text file containing fully qualified name of the AP under file<br />
              META-INF/services/javax.annotation.processing.Processor. Sample file content is shown below:</p>
<pre class="brush: java; title: ; notranslate">com.abc.ConstructorWithoutArgsProcessor</pre>
</li>
<li> Jar the AP classes and META-INF</li>
<pre class="brush: java; title: ; notranslate">
jar cvMif myProcessor.jar -C com/* META-INF/services/*
</pre>
</ol>
<p><strong>Sample Annotation Processor Source Code</strong></p>
<pre class="brush: java; title: ; notranslate">
public class MyCustomProcessor extends AbstractProcessor {
public boolean process(Set annotations,
RoundEnvironment env) {
for (TypeElement type : annotations) {
doProcess(env, type);
}
return true;
}
</pre>
<p>Let's write a sample annotation</p>
<pre class="brush: java; title: ; notranslate">
@Inherited
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface ConstructorWithoutArgs {
}
</pre>
<p>Here is the code of custom processor:</p>
<pre class="brush: java; title: ; notranslate">
@SupportedAnnotationTypes(&quot;com.abc.ConstructorWithoutArgs&quot;)
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ConstructorWithoutArgsProcessor extends AbstractProcessor {
  public boolean process(Set&lt;? extends TypeElement&gt; annotations, RoundEnvironment env) {
    for (TypeElement type : annotations) {
      processClassesWithoutConstructorArgs(env, type);
    }
    return true;
  }

  private void processClassesWithoutConstructorArgs(RoundEnvironment env, TypeElement type) {
    for (Element element : env.getElementsAnnotatedWith(type)) {
      processClass(element);
    }
  }

  private void processClass(Element element) {
    if (!doesClassContainConstructorWithoutArgs(element)) {
      processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
          &quot;Class &quot; + element + &quot; needs a No-Args Constructor&quot;);
    }
  }

  private boolean doesClassContainConstructorWithoutArgs(Element el) {
    for (Element subelement : el.getEnclosedElements()) {
      if (subelement.getKind() == ElementKind.CONSTRUCTOR &amp;&amp;
          subelement.getModifiers().contains(Modifier.PUBLIC)) {
        TypeMirror mirror = subelement.asType();
        if (mirror.accept(noArgsVisitor, null)) return true;
      }
    }
    return false;
  }

  private static final TypeVisitor&lt;Boolean, Void&gt; noArgsVisitor =
      new SimpleTypeVisitor6&lt;Boolean, Void&gt;() {
        public Boolean visitExecutable(ExecutableType t, Void v) {
          return t.getParameterTypes().isEmpty();
        }
      };
}
</pre>
<p>In the doesClassContainConstructorWithoutArgs() method, we iterate through all of the class elements and pick out the public constructors. A class that does not have any will automatically fail the test. Note that when we do not specify any constructor, Java automatically adds a default no-args constructor. </p>
<p>Once we have found our constructor element, we visit it with to determine whether the argument list is empty. Using the Visitor pattern in this case helps us to avoid a downcast.<br />
Once we have all these files packaged in a jar file, let's call it myProcessor.jar, we can add a processing parameter to our call to javac: </p>
<pre class="brush: java; title: ; notranslate">
javac -classpath .;myProcessor.jar -processorpath myProcessor.jar com/*.java
</pre>
<p>Let's test this with few test cases: </p>
<pre class="brush: java; title: ; notranslate">
@ConstructorWithoutArgs
public abstract class SuperClassWithoutArgs {
  public SuperClassWithoutArgs() {
  }
}

// Passes
public class PublicConstructorWithoutArgs extends SuperClassWithoutArgs {
  public PublicConstructorWithoutArgs() {
  }
}

// Fails
public class NonPublicConstructor extends SuperClassWithoutArgs {
  NonPublicConstructor() {
  }
}

// Fails
public class WrongConstructor extends SuperClassWithoutArgs {
  public WrongConstructor(String aString) {
  }
}
</pre>
<p>  When we compile these classes with the ConstructorWithoutArgsProcessor, we see the following compiler errors: </p>
<p>    error: Class NonPublicConstructor needs a No-Args Constructor<br />
    error: Class WrongConstructor needs a No-Args Constructor<br />
    2 errors</p>
<p><strong>Limitations of APT</strong></p>
<ol>
<li> no processing of local variable annotations</li>
<li> no inheritance of annotations</li>
</ol>
<p>In this way, we can write custom annotations which may require specific logic for any certain business needs like persistence, auditing etc. In Java SE 6, annotations can be written only on method parameters and the declarations of packages, classes, methods, fields, and local variables. <a href="http://types.cs.washington.edu/jsr308/">JSR 308</a> extends Java to allow annotations on nearly any use of a type, and on type parameter declarations. JSR 308 uses a simple prefix syntax for type annotations, with a special case for receiver types and for constructor results.<br />
The <a href="http://types.cs.washington.edu/checker-framework/">Checker Framework</a> is one way to create plug-ins that do pluggable type-checking for the type qualifiers. A pluggable type-checker enables you to detect certain bugs in your code, or to prove that they are not present and this verification happens at compile time. The Checker Framework enhances Java’s type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs.
</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/09/processing-custom-annotations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex : Exploiting Data Bindings for CRUD Based Applications</title>
		<link>http://xebee.xebia.in/2010/08/04/flex-exploiting-data-bindings-for-crud-based-applications/</link>
		<comments>http://xebee.xebia.in/2010/08/04/flex-exploiting-data-bindings-for-crud-based-applications/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 04:25:53 +0000</pubDate>
		<dc:creator>Sohil</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4284</guid>
		<description><![CDATA[Its been sometime I have been writing CRUD based application and I always wished how can I get rid of so much of actionscript code. The pain points while writing CRUD based application is collection of data and submitting the data , another two features make coding unclean is the clear and reset functionality of [...]]]></description>
			<content:encoded><![CDATA[<p>Its been sometime I have been writing CRUD based application and I always wished how can I get rid of so much of actionscript code. The pain points while writing CRUD based application is collection of data and submitting the data , another two features make coding unclean is the clear and reset functionality of the form, also another pain point is using only one form for create , read and update. This article gives insight of how to write least of the actionscript code to exploit the power of data binding.</p>
<p> </p>
<h3><span id="more-4284"></span></h3>
<h3>Smart Collection of the Form Data</h3>
<p>Often i come across the following code in a CRUD applications</p>
<pre>private function getUserDetails():UserVO{

    var user:UserVO = new UserVO();
    user.name = userName.text;
    user.email = email.text

}
</pre>
<p>In this case once the user clicks on submit button you write a function to get the user details from the form.</p>
<p> This approach is a little error prone also it has an overhead of collection data from the right text field.</p>
<p>I have seen very few applications declaring the VO in mxml. Declaring VO in mxml can help you avoid the dirty data collection function as we saw above.With effective use of binding collect the data from the form.</p>
<p>Following is the way you define the object in mxml to bind the fields data to VO object.This I personally feel is more cleaner and readable than the above mentioned approach</p>
<pre> &lt;local:UserVO id="updatedVO" username="{username.text}" firstName="{firstName.text}" lastName="{lastName.text}" email="{email.text}" /&gt;
</pre>
<p>As any other binding rules you can also have expressions in the mxml declaration of VO in case the assignments are complex.</p>
<h3>Cleaner Clear and reset functionality in Form</h3>
<p>The simplest way of clearning and reset the form can be done in the following way</p>
<pre>private function clear():void{

username.text = "";
Firstname.text = "";
Lastname.text = "";
email.text = "";

}

private function reset(user:UserVO):void{

username.text = user.name;
Firstname.text =  user.firstName;
Lastname.text =  user.lastName;
email.text =  user.email;

}
</pre>
<p>However your QA might just log a bug that you missed one property to be reset <img class="wp-smiley" src="http://xebee.xebia.in/wp-includes/images/smilies/icon_smile.gif" alt=":)" /> .</p>
<p>As i have already binded the user object to my custom fields i use this.executebindings(true); to force the</p>
<p> controls to reflect the values they were binded to.</p>
<pre>private var clear():void{
	localUser = new UserVO();
	this.executebindings(true) \\ to be on a safer side
}

private var reset(user:UserVO):void{
	this.localUser = user; \\ to be on a safer side
}
</pre>
<p>Here I assign the values to a private variable localUser and executeBindings on the Form to make the bindings effective.</p>
<p>Well these are just the basic idea to explain my point. I have attached the application files to the blog. This is more generalized application and uses mode &amp; data binding in the ManageUser component  for create , update , read. It's a simple application that demonstrates how to exploit flex data bindings</p>
<p>Following is a video explanation of the topic</p>
<p><a href="http://live.kpoint.in/kapsule/gcc-426c1119-1733-47d8-9592-9665152029f9">video explanation of application</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/08/04/flex-exploiting-data-bindings-for-crud-based-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 Useful Maven2 Plugins</title>
		<link>http://xebee.xebia.in/2010/07/26/5-useful-maven2-plugins/</link>
		<comments>http://xebee.xebia.in/2010/07/26/5-useful-maven2-plugins/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 15:38:09 +0000</pubDate>
		<dc:creator>Ankit Kumar</dc:creator>
				<category><![CDATA[Build and Release]]></category>
		<category><![CDATA[Java2WSDL]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Maven Plugins]]></category>
		<category><![CDATA[WSDL2Code]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4238</guid>
		<description><![CDATA[In this blog we will talk about some common problems faced while building, deploying and releasing java based projects in a maven build environment and also explain solutions for them using different maven plugin(s). This post will cover usage of the following maven plugin(s): - Maven WAR Plugin Maven Cobertura Plugin Maven Java2WSDL Plugin (Axis2) [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog we will talk about some common problems faced while  building, deploying and releasing java based projects in a maven build  environment and also explain solutions for them using different maven  plugin(s). This post will cover usage of the following maven plugin(s): -</p>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<ul>
<li><a href="http://maven.apache.org/plugins/maven-war-plugin/">Maven WAR Plugin</a></li>
<li><a href="http://mojo.codehaus.org/cobertura-maven-plugin/">Maven Cobertura Plugin</a></li>
<li><a href="http://ws.apache.org/axis2/tools/1_2/maven-plugins/maven-java2wsdl-plugin.html">Maven Java2WSDL Plugin</a> (<a href="http://ws.apache.org/axis2/">Axis2</a>)</li>
<li><a href="http://ws.apache.org/axis2/tools/1_2/maven-plugins/maven-wsdl2code-plugin.html">Maven WSDL2Code Plugin</a> (<a href="http://ws.apache.org/axis2/">Axis2</a>)</li>
<li><a href="http://maven.apache.org/plugins/maven-release-plugin/">Maven Release Plugin</a></li>
</ul>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p><img title="More..." src="http://ankitk.wordpress.com/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /></p>
<h3><span id="more-4238"></span></h3>
<h3><strong>Problem: Overlay ZIP or WAR file on another WAR source.</strong></h3>
<p><strong>Description:</strong> We have a maven project with some artifact  dependencies, classes and resources which need to be bundled together  into a WAR file. The artifact dependencies to be bundled together are: -  axis2 AAR file (Axis Archive), a zipped folder and another WAR file.</p>
<p><strong>Solution:</strong> Use maven WAR plugin with overlays. Add below plugin configuration to the project <a href="http://maven.apache.org/pom.html">POM</a> file.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
  &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
  &lt;version&gt;2.1-beta-1&lt;/version&gt;
  &lt;configuration&gt;
    &lt;warName&gt;FinalProject&lt;/warName&gt;
    &lt;overlays&gt;
      &lt;!--Overlay an AAR file inside the generated WAR file --&gt;
      &lt;overlay&gt;
        &lt;groupId&gt;com.test.services&lt;/groupId&gt;
        &lt;artifactId&gt;test-services&lt;/artifactId&gt;
        &lt;type&gt;aar&lt;/type&gt;
        &lt;targetPath&gt;WEB-INF/services&lt;/targetPath&gt;
      &lt;/overlay&gt;
      &lt;!--Overlay a ZIP file and place extracted content under WEB-INF/knowledge --&gt;
      &lt;overlay&gt;
        &lt;groupId&gt;com.test.knowledge&lt;/groupId&gt;
        &lt;artifactId&gt;test-knowledge&lt;/artifactId&gt;
        &lt;type&gt;zip&lt;/type&gt;
        &lt;targetPath&gt;WEB-INF/knowledge&lt;/targetPath&gt;
      &lt;/overlay&gt;
      &lt;!--Overlay a WAR file and exclude the .jpg in final war --&gt;
      &lt;overlay&gt;
        &lt;groupId&gt;com.example.project&lt;/groupId&gt;
        &lt;artifactId&gt;projectdependency&lt;/artifactId&gt;
        &lt;excludes&gt;
          &lt;exclude&gt;images/sampleimage-dependency.jpg&lt;/exclude&gt;
        &lt;/excludes&gt;
      &lt;/overlay&gt;
    &lt;/overlays&gt;
  &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>Overlays are applied in the order in which they are defined in the  overlays configuration. By default, the source of the project (a.k.a the  current build) is added first (e.g. before any overlay is applied). The  current build is defined as a special overlay with no groupId,  artifactId. If overlays need to be applied first, simply configure the  current build after those overlays.</p>
<h3><strong>Problem: Ensure build breaks if code coverage &lt; threshold.</strong></h3>
<p><strong>Description:</strong> Ensure that during each build code coverage is above the required threshold value, if not then the maven build fails.</p>
<p><strong>Solution:</strong> Use <a href="http://mojo.codehaus.org/cobertura-maven-plugin/">Maven cobertura</a> plugin.</p>
<pre class="brush: xml; title: ; notranslate">
      &lt;plugin&gt;
        &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
        &lt;artifactId&gt;cobertura-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.4&lt;/version&gt;
        &lt;configuration&gt;
          &lt;instrumentation&gt;
            &lt;excludes&gt;
              &lt;exclude&gt;com/project/test/TestMain.class&lt;/exclude&gt;
            &lt;/excludes&gt;
          &lt;/instrumentation&gt;
          &lt;check&gt;
            &lt;totalLineRate&gt;85&lt;/totalLineRate&gt;
          &lt;/check&gt;
          &lt;formats&gt;
            &lt;format&gt;html&lt;/format&gt;
            &lt;format&gt;xml&lt;/format&gt;
          &lt;/formats&gt;
        &lt;/configuration&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;clean&lt;/id&gt;
            &lt;phase&gt;pre-site&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;clean&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
          &lt;execution&gt;
            &lt;id&gt;instrument&lt;/id&gt;
            &lt;phase&gt;install&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;check&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
      &lt;/plugin&gt;
</pre>
<h3><strong>Problem: Generate <a href="http://www.w3.org/TR/wsdl">WSDL</a> from a Java class at build time.</strong></h3>
<p><strong>Solution:</strong> Use <a href="http://ws.apache.org/axis2/tools/1_2/maven-plugins/maven-java2wsdl-plugin.html">Maven Java2WSDL</a> plugin. Below configuration creates a TestProject.wsdl from the class <em>com.test.service.TestWebService</em>.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
  &lt;groupId&gt;org.apache.axis2&lt;/groupId&gt;
  &lt;artifactId&gt;axis2-java2wsdl-maven-plugin&lt;/artifactId&gt;
  &lt;version&gt;1.5&lt;/version&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;id&gt;generate web service wsdl&lt;/id&gt;
      &lt;goals&gt;
        &lt;goal&gt;java2wsdl&lt;/goal&gt;
      &lt;/goals&gt;
      &lt;configuration&gt;
        &lt;serviceName&gt;TestService&lt;/serviceName&gt;
        &lt;className&gt;com.test.service.TestWebService&lt;/className&gt;
        &lt;targetNamespace&gt;http://www.test.com/TestProject&lt;/targetNamespace&gt;
        &lt;schemaTargetNamespace&gt;http://www.test.com/TestProject&lt;/schemaTargetNamespace&gt;
        &lt;elementFormDefault&gt;qualified&lt;/elementFormDefault&gt;
        &lt;package2Namespace&gt;
          &lt;property&gt;
            &lt;name&gt;com.test.domain&lt;/name&gt;
            &lt;value&gt;http://www.test.com/TestProject&lt;/value&gt;
          &lt;/property&gt;
        &lt;/package2Namespace&gt;
        &lt;outputFileName&gt;target/generated-resources/TestProject.wsdl&lt;/outputFileName&gt;
      &lt;/configuration&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>NOTE: The plugin will be invoked automatically in the  generate-sources phase. You can also invoke it directly from the command  line by running the command.</p>
<pre class="brush: xml; title: ; notranslate">
mvn java2wsdl:java2wsdl
</pre>
<h3><strong>Problem: Generate web service stub from the wsdl file.</strong></h3>
<p><strong>Solution:</strong> Use <a href="http://ws.apache.org/axis2/tools/1_2/maven-plugins/maven-wsdl2code-plugin.html">Maven WSDL2Code</a> plugin. This plugin takes as input a WSDL and generates client and  server stubs for calling or implementing a Web service matching the  WSDL.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!--
  Generate Java code for the Admin web service (target/wsdl/test.wsdl).
  Places result in target/generated-sources/axis2/wsdl2code/src
--&gt;
&lt;plugin&gt;
  &lt;groupId&gt;org.apache.axis2&lt;/groupId&gt;
  &lt;artifactId&gt;axis2-wsdl2code-maven-plugin&lt;/artifactId&gt;
  &lt;version&gt;1.5&lt;/version&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;goals&gt;
        &lt;goal&gt;wsdl2code&lt;/goal&gt;
      &lt;/goals&gt;
      &lt;configuration&gt;
        &lt;packageName&gt;com.test.wsclient&lt;/packageName&gt;
        &lt;wsdlFile&gt;${project.build.directory}/wsdl/test.wsdl&lt;/wsdlFile&gt;
        &lt;syncMode&gt;sync&lt;/syncMode&gt;
      &lt;/configuration&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>NOTE: The plugin will be invoked automatically in the  generate-sources phase. You can also invoke it directly from the command  line by running the command.</p>
<pre class="brush: xml; title: ; notranslate">
mvn wsdl2code:wsdl2code
</pre>
<h3><strong>Problem:</strong> <strong>Releasing project artifacts and branching.<br />
</strong></h3>
<p><strong>Description:</strong> Release the project artifacts for release 1.0  into local repository and create a new branch out of trunk for bug fixes  on release 1.0.  All new development for release 2.0 will be done on  trunk.</p>
<p><strong>Solution:</strong> Use maven release plugin.</p>
<p>Add the following configuration in the parent projects <a href="http://maven.apache.org/pom.html">POM</a> file.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;scm&gt;
   &lt;!--SCM connection URL to checkout from --&gt;
   &lt;connection&gt;scm:svn:svn://svn/trunk/java/testproject/root&lt;/connection&gt;
   &lt;developerConnection&gt;scm:svn:svn://svn/trunk/java/testproject/root&lt;/developerConnection&gt;
&lt;/scm&gt;
&lt;repositories&gt;
   &lt;repository&gt;
     &lt;id&gt;nexus&lt;/id&gt;
     &lt;name&gt;Nexus maven repo at HI&lt;/name&gt;
     &lt;url&gt;http://build-cordys:8080/nexus/content/groups/public&lt;/url&gt;
   &lt;/repository&gt;
&lt;/repositories&gt;
</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
   &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
   &lt;artifactId&gt;maven-release-plugin&lt;/artifactId&gt;
   &lt;version&gt;2.0-beta-9&lt;/version&gt;
   &lt;configuration&gt;
        &lt;!--Goals to execute while release preparation --&gt;
	&lt;preparationGoals&gt;clean install&lt;/preparationGoals&gt;
   &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>In order to perform the release and then create a branch we run the following commands in sequence.</p>
<pre class="brush: xml; title: ; notranslate">
mvn release:prepare
</pre>
<p><strong>mvn release:prepare</strong> executes the following task: -</p>
<ol>
<li>Check that there are no uncommitted changes in the sources</li>
<li>Check that there are no SNAPSHOT dependencies</li>
<li>Change the version in the POMs from x-SNAPSHOT to a new version (you will be prompted for the versions to use)</li>
<li>Transform the SCM information in the POM to include the final destination of the tag</li>
<li>Run the project tests against the modified POMs to confirm everything is in working order</li>
<li>Commit the modified POMs</li>
<li>Tag the code in the SCM with a version name (this will be prompted for)</li>
<li>Bump the version in the POMs to a new value y-SNAPSHOT (these values will also be prompted for)</li>
<li>Commit the modified POMs</li>
</ol>
<pre class="brush: xml; title: ; notranslate">
mvn release:perform
</pre>
<p><strong>mvn release:perform</strong> executes the following tasks: -</p>
<ol>
<li>Checkout from an SCM URL with optional tag</li>
<li>Run the predefined Maven goals to release the project (by default, <tt>deploy site-deploy</tt></li>
</ol>
<p>In order to create a new branch from the trunk we run the following commands in sequence.</p>
<pre class="brush: xml; title: ; notranslate">
mvn release:branch -DbranchName=&lt;branchName&gt;
</pre>
<p><strong>mvn release:branch</strong> executes the following tasks: -</p>
<ol>
<li>Check that there are no uncommitted changes in the sources</li>
<li>Change the version in the POMs if you want to change it in the branch (you will be prompted for the versions to use)</li>
<li>Transform the SCM information in the POM to include the final destination of the tag</li>
<li>Commit the modified POMs</li>
<li>Tag the code in the SCM as a new branch with a version name (this will be prompted for)</li>
<li>Bump the version in the POMs if you want to change it to a new value y-SNAPSHOT (these values will also be prompted for)</li>
<li>Commit the modified POMs</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/26/5-useful-maven2-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinking Sideways</title>
		<link>http://xebee.xebia.in/2010/07/25/thinking-sideways/</link>
		<comments>http://xebee.xebia.in/2010/07/25/thinking-sideways/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:54:06 +0000</pubDate>
		<dc:creator>akabhay</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Creativity]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Human Behaviour]]></category>
		<category><![CDATA[Workshop]]></category>
		<category><![CDATA[Ideas]]></category>
		<category><![CDATA[Lateral Thinking]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4212</guid>
		<description><![CDATA["I just had an idea…and its crap…" How many times have you just had a bulb light up over your head? Or, how many sleepless nights have you spent turning over &#38; over, hoping to see a tiny glimpse of the spark that signals the arrival of a new idea? Your idea may have the [...]]]></description>
			<content:encoded><![CDATA[<p>"I just had an idea…and its crap…"</p>
<p>How many times have you just had a bulb light up over your head? Or, how many sleepless nights have you spent turning over &amp; over, hoping to see a tiny glimpse of the spark that signals the arrival of a new idea?</p>
<p>Your idea may have the potential to be bigger than Facebook, or maybe it just allows you to shave 2 minutes off your unit schedule. 2 minutes might not mean a lot to you, but it would definitely appeal to Foxconn employees. The size of the idea is not the only factor that drives creativity, but how much value that idea derives also matters.</p>
<p>I recently attended Edward de Bono’s creativity thinking workshop. The gathering was quite eclectic, ranging from engineers from one of the biggest heavy goods engineering companies, to sales managers from a cigarettes company, to education providers, and even a corporate lawyer.</p>
<p>If I could sum up the workshop in one sentence, it would be this: The mind can be trained to think creatively, to ‘ideate’. Of course, some will always be more talented than the rest at being creative, but it is not the prerogative of a select few. More often than not, it involves changing perceptions, and challenging established notions.</p>
<p><span id="more-4212"></span></p>
<p>People are generally educated to think vertically, to go from one logical step to another, thus arriving at a solution to a stated problem. Vertical thinking often follows a linear approach, excluding alternate or remote possibilities, by keeping the problem in its target sights. Lateral Thinking approaches the problem from a different angle, by identifying &amp; exploring other possibilities, and also looks beyond the solution to the stated problem, to generate new concepts and explore new ways of doing things.</p>
<p>Lateral Thinking understands that our brains are pattern recognition systems. We can recognize objects &amp; situations very quickly. There are techniques that help us break this conditioned, patterned way of thinking. They provide a deliberate, systematic process to be creative, so that it works for you when you need it.</p>
<p><strong>Lateral Thinking Tools</strong></p>
<p>Tools can help you ideate. A tool is just a means to achieving an end, helps us in amplifying our skills and enables us to do things faster, or simpler. An example, a key aids us to escape a locked room, but it does not determine where we go from there.</p>
<p>Some of the Lateral Thinking tools we studied at the workshop were:</p>
<ol>
<li><strong><em>Alternatives / Concept Extraction:</em></strong> Use concepts to breed new ideas</li>
<li><strong><em>Focus:</em></strong> Sharpen or change your focus to improve your creative efforts</li>
<li><strong><em>Challenge:</em></strong> Break free from the limits of accepted ways of operating</li>
<li><strong><em>Random Entry:</em></strong> Use unconnected input to open new lines of thinking</li>
<li><strong><em>Provocation:</em></strong> Move from a provocative statement to useful ideas</li>
</ol>
<p><strong><em>Alternatives/Concept Extraction</em></strong><br />
Concepts are a general way of doing things. A concept has to be put into implementation through a specific idea. Sometimes, when you are stuck at a particular problem, you might just consider taking a step back to get a broader perspective. Re-word the problem in general terms. From this, look for alternative solutions, which might not be related to the problem at hand. Use the newly generated ideas to further mine for concepts. Each new concept then provides a whole new pathway for generating new ideas. Expand &amp; redefine the problem until a useable solution can be generated and implemented.</p>
<p>This is a useful technique for widening the search for solutions when obvious approaches have been exhausted.</p>
<p><strong><em>Focus</em></strong><br />
Focus sharpens or changes your perspective to improve the creative efforts. You learn to focus on areas no one else has thought about. By concentrating your focus to an area, you can up with a breakthrough idea simply by being the first person to be “at the scene of the crime”. Willing yourself to include focus on areas other than problem areas expands your chances of coming up with ideas.</p>
<p><strong><em>Challenge</em></strong><br />
Challenge helps you to break from the current limits of accepted ways of thinking. It works on the simple premise of challenging the status quo, and is based on the assumption that there might be a better way of doing something, even though there is no problem the way the current system works.</p>
<p>It works by asking “Why?” in a non threatening way, more like an inquisitive query: Why something exists, why is it done the way it is? The result is a clearer understanding of the system, which then leads to fresh new ideas.</p>
<p>A simple example we tried our hand at the workshop: “Why are the tea cups &amp; saucers round?“</p>
<p>Some of the answers were:</p>
<ul>
<li>The round shape is symmetrical</li>
<li>Both left &amp; right handed people can hold the handle in either hand, and drink easily</li>
<li>People use the saucer to keep cookies and more…</li>
</ul>
<p>Newer ideas that then sprang from this exercise were:</p>
<ul>
<li>Would a hexagonal shape look more chic?</li>
<li>Would insulation on the outer shell of the cup allow the cup makers to discard the handle?</li>
<li>Can we extend the cup itself to have a hollow space below it to keep a couple of cookies,      eliminating the need for the saucer?</li>
</ul>
<p><strong><em>Random Word</em></strong><br />
The Random Word tool uses a random word or picture to open new lines of thinking. It relies on the human mind to find connections between seemingly unrelated things. It is a technique to link patterns associated with that word or picture with the patterns we are currently using with the problem at hand. This is a very effective tool, often providing startling leaps in creativity, even with untrained groups. The best words to use are concrete nouns. Care should be noted that they do not come from the same field as the problem under consideration.</p>
<p>Eg. You are considering the problem of reducing car pollution. The chosen random word is “plants”. Brainstorming on this could bring the following ideas:</p>
<ul>
<li>Plant trees on the roadside to convert CO<sub>2</sub> to      oxygen.</li>
<li>Pass exhaust gases through a soup of algae to convert CO<sub>2</sub> to oxygen. An idea for a radical version of a catalytic converter,      perhaps?</li>
<li>Plant also means a factory. Maybe gases could be collected      and compressed, and offloaded while fuel is being filled. The collected      gases would then be processed in a special plant to be cleaned?</li>
</ul>
<p><strong><em>Provocation</em></strong><br />
Provocation technique works on the premise of postulating deliberate unreasonable ideas, which would ordinarily be vetoed off at face value. However, these ideas are laid out to change perception. These statements then serve as a springboard through which other practical ideas can be extracted. Unfortunately, it was nearing the end of the day. We didn’t get a chance to try this tool out at the workshop, and had to be content with a celebrated example of the application of this tool. Dr. Bono was once given a topic as an exercise that there were too few police officers to patrol the streets. He postulated that “The police have six eyes.” This outrageous statement, on further brainstorming, brought about the idea that citizens could serve as extra eyes to notice and report any unusual activities in their neighborhoods. This idea eventually grew into the Neighborhood Watch Program, now used widely in many cities across the world.</p>
<p>People can either have the drive to use the tools to be creative. Or they might try out the tools, and on finding them quite useful, be motivated to be more creative. For example, the idea of dashboards and corporate wikis challenged and turned the traditional model of top down project management model on its head, while fostering collaboration &amp; team spirit.</p>
<p>You don’t own the idea anymore than it owns you. There are billions of people on this planet, and the law of averages states that many of them could have the same idea. In fact, some of them might be having it at the same time as you. Maybe, even earlier. The clock is ticking…</p>
<p><em>Have fun creating!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/25/thinking-sideways/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google App Engine + Maven + JSF2</title>
		<link>http://xebee.xebia.in/2010/07/21/google-app-engine-maven-jsf2/</link>
		<comments>http://xebee.xebia.in/2010/07/21/google-app-engine-maven-jsf2/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 06:18:56 +0000</pubDate>
		<dc:creator>Rocky Jaiswal</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[Maven]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4183</guid>
		<description><![CDATA[I have tried to put all the keywords in the title of this blog, hoping that it will turn some heads. Google App Engine (GAE) provides a great hosting platform for open source apps written in Java/Python. So if you have no qualms about hosting you Java applications on a public server then you have [...]]]></description>
			<content:encoded><![CDATA[<p>I have tried to put all the keywords in the title of this blog, hoping that it will turn some heads. Google App Engine (GAE) provides a great hosting platform for open source apps written in Java/Python. So if you have no qualms about hosting you Java applications on a public server then you have no better choice than GAE.</p>
<p>The only catch however is, that GAE does not support certain APIs (see the white-list here - <a href="http://code.google.com/intl/de/appengine/docs/java/jrewhitelist.html" target="_blank">http://code.google.com/intl/de/appengine/docs/java/jrewhitelist.html</a>). This restriction makes it difficult to host certain apps / frameworks.</p>
<p>GAE provides the infrastructure, a modified Jetty server included in the GAE SDK (<a href="http://code.google.com/appengine/downloads.html" target="_blank">http://code.google.com/appengine/downloads.html</a>) though which you can test your app. If it runs on the local GAE Jetty server then it will also run on GAE itself. The project structure that Google asks you to create for uploading an app is also quite typical (unless you use Ant) which brings me to my next point.</p>
<p><span id="more-4183"></span></p>
<p>Maven is my favorite build tool, it would really take something for me to move on to Ant now. So I tried to create my application using Maven and then test it locally on GAE's Jetty and finally upload it to GAE. After a little search I found the Maven GAE plugin (<a href="http://code.google.com/p/maven-gae-plugin/">http://code.google.com/p/maven-gae-plugin/</a>).</p>
<p>Below is my pom.xml to make this plugin work - </p>
<pre class="brush: xml; title: ; notranslate">
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;

    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;net.rocky&lt;/groupId&gt;
    &lt;artifactId&gt;rocky-gae-app&lt;/artifactId&gt;
    &lt;packaging&gt;war&lt;/packaging&gt;
    &lt;version&gt;1&lt;/version&gt;
    &lt;name&gt;rocky-gae-app&lt;/name&gt;
    &lt;url&gt;http://maven.apache.org&lt;/url&gt;

    &lt;repositories&gt;
        &lt;repository&gt;
            &lt;id&gt;java.net&lt;/id&gt;
            &lt;url&gt;http://download.java.net/maven/2&lt;/url&gt;
        &lt;/repository&gt;
    &lt;/repositories&gt;

    &lt;pluginRepositories&gt;
        &lt;pluginRepository&gt;
            &lt;id&gt;maven-gae-plugin-repo&lt;/id&gt;
            &lt;name&gt;maven-gae-plugin repository&lt;/name&gt;
            &lt;url&gt;http://maven-gae-plugin.googlecode.com/svn/repository&lt;/url&gt;
        &lt;/pluginRepository&gt;
    &lt;/pluginRepositories&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
            &lt;artifactId&gt;servlet-api&lt;/artifactId&gt;
            &lt;version&gt;2.5&lt;/version&gt;
            &lt;scope&gt;provided&lt;/scope&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;javax.servlet.jsp&lt;/groupId&gt;
            &lt;artifactId&gt;jsp-api&lt;/artifactId&gt;
            &lt;version&gt;2.1&lt;/version&gt;
            &lt;scope&gt;provided&lt;/scope&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.sun.faces&lt;/groupId&gt;
            &lt;artifactId&gt;jsf-api&lt;/artifactId&gt;
            &lt;version&gt;2.0.2&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.sun.faces&lt;/groupId&gt;
            &lt;artifactId&gt;jsf-impl&lt;/artifactId&gt;
            &lt;version&gt;2.0.2&lt;/version&gt;
            &lt;classifier&gt;gae&lt;/classifier&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.glassfish.web&lt;/groupId&gt;
            &lt;artifactId&gt;el-impl&lt;/artifactId&gt;
            &lt;version&gt;2.2&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;junit&lt;/groupId&gt;
            &lt;artifactId&gt;junit&lt;/artifactId&gt;
            &lt;version&gt;4.8.1&lt;/version&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;version&gt;2.0.2&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;source&gt;1.6&lt;/source&gt;
                    &lt;target&gt;1.6&lt;/target&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;net.kindleit&lt;/groupId&gt;
                &lt;artifactId&gt;maven-gae-plugin&lt;/artifactId&gt;
                &lt;version&gt;0.6.0&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;sdkDir&gt;/home/rockyj/01rocky/02apps/appengine-java-sdk-1.3.5&lt;/sdkDir&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
        &lt;finalName&gt;rocky-gae-app&lt;/finalName&gt;
    &lt;/build&gt;

&lt;/project&gt;
</pre>
<p>I have included the whole pom as there is hardly anything I can miss here. The GAE plugin is not in maven central so we need to include the plugin repository, the dependencies are pretty standard except one (which I will explain in a moment) and the plugin itself needs the configuration to know where you have the GAE SDK.</p>
<p>As I mentioned earlier, some classes are blacklisted on the GAE so your default jsf-impl.jar (Mojarra) wil not work on GAE. You will need a modified jar which you can download from here (<a href="http://code.google.com/p/joshjcarrier/source/browse/trunk/Sun%20JSF%20GAE/jsf-impl-gae.jar">http://code.google.com/p/joshjcarrier/source/browse/trunk/Sun%20JSF%20GAE/jsf-impl-gae.jar</a>), if you have a Nexus repo you can install the modified jar there or install the jar in you local repository manually. Also as seen in the pom, for resolving EL (Expression Language) you need el-impl.jar, GAE does not support EL unlike Tomcat. </p>
<p>To make JSF work you need the following entries in your web.xml -</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;!-- Seems like GAE 1.2.6 cannot handle server side session management. At least for JSF 2.0.1 --&gt;
    &lt;context-param&gt;
      &lt;param-name&gt;javax.faces.STATE_SAVING_METHOD&lt;/param-name&gt;
      &lt;param-value&gt;client&lt;/param-value&gt;
    &lt;/context-param&gt;
    &lt;!-- Recommendation from GAE pages  --&gt;
    &lt;context-param&gt;
      &lt;param-name&gt;javax.faces.PROJECT_STAGE&lt;/param-name&gt;
      &lt;param-value&gt;Production&lt;/param-value&gt;
    &lt;/context-param&gt;
    &lt;!-- Accommodate Single-Threaded Requirement of Google AppEngine  --&gt;
    &lt;context-param&gt;
      &lt;param-name&gt;com.sun.faces.enableThreading&lt;/param-name&gt;
      &lt;param-value&gt;false&lt;/param-value&gt;
    &lt;/context-param&gt;
</pre>
<p>Finally, in your appengine-web.xml (the GAE configuration file), you need the following entry - </p>
<pre class="brush: xml; title: ; notranslate">
&lt;sessions-enabled&gt;true&lt;/sessions-enabled&gt;
</pre>
<p>That's it. Now you can work on your JSF2 application. To test, all you need to do is : <strong>mvn clean gae:run</strong></p>
<p>For uploading the application, I would still recommend using the SDK provided script (otherwise you need a whole lot of other changes). What I do is - </p>
<p>$HOME/01rocky/02apps/appengine-java-sdk-1.3.5/bin/appcfg.sh update /home/rockyj/01rocky/03workspace/scbcd/rocky-gae-app/target/rocky-gae-app/</p>
<p>This means run the GAE script with the param <strong>"update"</strong> and the path to your maven created target folder. If you have signed up for GAE, it will ask your username and password and your app will be uploaded to GAE.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/21/google-app-engine-maven-jsf2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>To All Agile NCR 2010 Participants</title>
		<link>http://xebee.xebia.in/2010/07/20/to-all-agile-ncr-2010-participants/</link>
		<comments>http://xebee.xebia.in/2010/07/20/to-all-agile-ncr-2010-participants/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 19:35:17 +0000</pubDate>
		<dc:creator>Anurag Shrivastava</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile Maintenance]]></category>
		<category><![CDATA[AgileNCR]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4174</guid>
		<description><![CDATA[Dear All, A turnout of close to 300 people on a hot and humid weekend in Gurgaon for the annual event on Agile software development, Agile NCR 2010, was a clear signal about the growing interest in Agile, SCRUM and XP in India. Agile practitioners from all over the India interacted with people from software [...]]]></description>
			<content:encoded><![CDATA[<p>Dear All,</p>
<p>A turnout of close to 300 people on a hot and humid weekend in Gurgaon for the annual event on Agile software development, Agile NCR 2010, was a clear signal about the growing interest in Agile, SCRUM and XP in India. Agile practitioners from all over the India interacted with people from software industry that included roles such as project managers, teachers, students, developers and testers, at Ansal Institute of Technology located in Gurgaon.</p>
<p><strong>Parallel Tracks</strong></p>
<p>We have divided the whole event in four tracks to cover the needs of individuals who find themselves in different stages of Agile adoption which was appreciated by most people. Another remarkable point was a diverse selection of speakers from the companies of all sizes though the agenda was mainly dominated by the folks from Xebia and Thoughtworks who are among the early adopters of Agile.</p>
<p><img class="aligncenter" title="Serge Beaumont on Shu Ha Ri" src="http://farm5.static.flickr.com/4102/4807772215_1c1c090c1d_m.jpg" alt="" width="240" height="161" /></p>
<p>When I set up Agile NCR platform in 2006, I never expected that this event would grow so much in size but similarly when Xebia first adopted Agile in 2003, we never expected Agile to become a software movement on the lines similar to the open source movement, in the world in just 7 years.<br />
<span id="more-4174"></span></p>
<p>Rapid growth of offshore IT industry and the associated economics have forced Agile community to look at the collaboration of geographically distributed teams which is very important in the context of India. We see a convergence of the best practices when executing a distributed project which was beautifully described by Rini van Solingen over the phone line from Holland. Ironically technical problems in setting up good quality Skype video connection also exposed the limitations imposed by the poor internet connectivity on distributed collaboration.</p>
<p><img class="aligncenter" title="Audience in the Main Hall" src="http://farm5.static.flickr.com/4115/4808377280_b330a563f1_m.jpg" alt="" width="240" height="161" /></p>
<p><strong>Distributed Agile</strong></p>
<p>At Xebia, distributed Agile is close to our hearts.  We started our first serious distributed Agile project with India and The Netherlands team for our customer Dutch Railway in 2007. Around the same time, Gurgaon Metro construction had begun  few yards away from our Millennium Plaza office.  As the metro construction progressed so did this project. The last distributed team in India finished working on this project in 2009 i.e. just a year before the Metro begun running between Delhi and Gurgaon.</p>
<p>This project was very significant because  it was a failing project before we took it over and re-did it with Distributed Agile teams located in India and The Netherlands. During the course of this project, several times I interacted with Jeff Sutherland (Co-Creator of Scrum) who observed the growing productivity and the quality of our work with indifference, as for him this was an expected outcome of Scrum implemented the right way. The <a href="http://www.infoq.com/presentations/Distributed-Scrum-Sutherland-Schoonheim">success of this project</a> has been presented in the IEEE publications and Agile conferences in North America and Europe. The book “<em>Succeeding with Agile</em>” by Mike Cohn that you have got free during Agile NCR 2010<em> (Courtsey: Pete Deemer, GoodAgile)</em>, mentions about this project on page 368.</p>
<p><strong>Do and Learn</strong></p>
<p>We do, we learn, we give leanings back to the community for further refinement. This is the central idea behind Agile NCR platform. Since past 4 years, we had opportunity to host the Thought Leaders such as Poppendiecks, Venkat and Michael Feathers and top Agile consultants such as Sanjiv Augustine and Nilay Oza for our community events. If you missed those events then this is the good time to get involved.</p>
<p><strong>Win a Free CSM Training</strong></p>
<p>Sanjiv will be visiting New Delhi region to conduct a CSM training in August.<strong> Xebia will give away a <span style="text-decoration: underline;">free CSM seat</span> to a person who publishes the best blog about Agile NCR on any site,  in this <a href="http://xebia.wordpress.com/2010/06/23/certified-scrummaster-training-19-20-august-gurgaon-india/">upcoming CSM training</a> (Last date of submission is 10<sup>th</sup> August and we expect at least 8 published blogs to select from to choose the winner or else no winner). </strong>Xebia is also trying to make CSM trainings <strong><span style="text-decoration: underline;">more affordable in India by</span></strong> offering special discounts to Agile NCR participants. You will see a new pricing soon.</p>
<p>The real success of Agile NCR will be determined by the agile adoptions in India. Please keep documenting and sharing you learning and experience so that we all know if Agile has helped you do your project better.</p>
<p>Best regards,</p>
<p>Anurag Shrivastava</p>
<p>Agile NCR</p>
<p><a href="http://www.xebia.in/">www.xebia.in</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/20/to-all-agile-ncr-2010-participants/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Basic  iPhone User Interface and Usability Tips &#8211; Part I</title>
		<link>http://xebee.xebia.in/2010/07/16/basic-iphone-user-interface-and-usability-tips-part-i/</link>
		<comments>http://xebee.xebia.in/2010/07/16/basic-iphone-user-interface-and-usability-tips-part-i/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 05:35:03 +0000</pubDate>
		<dc:creator>jthakur</dc:creator>
				<category><![CDATA[Multimedia]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[iphone designing]]></category>
		<category><![CDATA[Mobile designing]]></category>
		<category><![CDATA[mobile usability]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4128</guid>
		<description><![CDATA[While attending “Human Factors International” certification classes sometime back, I came across a very interesting activity. We were asked to exchange our mobile devices within a group of people and perform small tasks after switching off it. Tasks were: Restart the mobile Set different ring tone and Set calendar meeting with alarm. The duration given [...]]]></description>
			<content:encoded><![CDATA[<p>While attending “<a href="http://www.humanfactors.com/training/schedule.asp?courseid=6#schedule" target="_blank">Human Factors International</a>” certification classes sometime back, I came across a very interesting activity. We were asked to exchange our mobile devices within a group of people and perform small tasks after switching off it. Tasks were:</p>
<ol style="padding-left:180px;">
<li>Restart the mobile</li>
<li>Set different ring tone and</li>
<li>Set calendar meeting with alarm.</li>
</ol>
<p>The duration given was 120 seconds. I got a Samsung mobile, while I carry a Nokia. I was not able to easily switch it on, and when I did, I could not perform half of my tasks in time.</p>
<p><strong>The conclusion</strong> – The Device was not user friendly and many of us could not achieve the goals in the given time. With this blog I intend to share my experience about designing Mobile User Interface - iPhone in particular.</p>
<p>Designing a mobile application is different than website designing. Mobile designing is complex and challenging. Further in mobile designing, touch screen applications are not much different. In touch screen finger is used to perform action, while others keys are used.</p>
<p><span id="more-4128"></span>Selecting an application technology and designing a mobile application needs:</p>
<ol style="padding-left:40px; padding-top:5px; padding-bottom:0px;">
<li>Good understanding of its benefits</li>
<li>Target device
<ol style="padding-left:60px;">
<li>normal mobile</li>
<li>touch screen</li>
</ol>
</li>
<li>End users</li>
<li>Cost involved and the profit earned</li>
<li>Context, market trend, and restrictions of the Development Company for building it.</li>
</ol>
<p>Attractive user interfaces are crucial too.  For end user the technology used is not as important as a good user interface.</p>
<p style="background-color:#f1ebf2; border:solid 1px #dcd4dd; line-height:25px; padding-left:20px; padding-top:0px; color:#653a71; font-weight:bold;">Here are some of the Usability points I took into consideration while working on an iPhone interface:</p>
<ol>
<li>Screen size should be 320 x 480 or 960 x 640 pixels. It is a good practice to draw wireframes on piece of paper .With this you get a fare idea of how the placement will be and so you can adjust the content in it accordingly.</li>
<li>Launcher icons should be present on the home screen. The standard size of launcher icon for low density, medium density screen and high density screen is 36 x 36 pixels, 48 x 48 pixels, 72 x 72 pixels. For more tips creating and managing icon sets for multiple densities, see <a href="http://developer.android.com/guide/practices/ui_guidelines/icon_design.html#design_tips" target="_blank">http://developer.android.com/guide/practices/ui_guidelines/icon_design.html#design_tips</a></li>
<li>Images should be light and small in size and loading resources idly. Preferred format is PNG as it gives rich colors and iphone is able to optimize PNG rendering for optimization.</li>
<li>Homepage is the place where branding starts. Make it simple, attractive and bold.
<ol style="padding-left:60px; padding-top:10px; padding-bottom:10px;">
<li>Once user is on the home page, Search comes handy to help a lost user.</li>
<li>Search should be prominent on the page with Search button.</li>
<li>Prefer to use simple label which are easy to understand.</li>
<li>If the search is defined for products then provide it in dropdown. This avoids user to type or misspell it.</li>
<li>Textbox area should be big enough to write.</li>
<li>Narrow down the search results, for example, “items displayed on page 1-15 of 340”.</li>
</ol>
</li>
<li>Use of standard controls should be correctly as users are familiar with the standard controls they see in the built-in applications for example: - A navigation bar should appear at the upper edge of an application window, just below the status bar. Make it bold and highlight it. This space is used for title of the screen and navigation controls.</li>
<li>A toolbar should appear at the bottom edge of the window. It provides functionality within the context of a task.
<p>For example: If I open a photo album application it provides a toolbar that contains items for deleting, next, previous, a typical action sheet for email photo, assign to contact, use as wallpaper features are displayed in this way, users can stay within the photo album-viewing context and still have access to the commands they need to manage their album. Icon size for toolbar should be 44 x 44 pixels, so it is easy for user to tap, also make sure it should not have more than 5 toolbar items and evenly distributed in 320 pixels otherwise it can be difficult for users to tap a specific one.</li>
<li>Different color than regular font color and bold helps to highlight important messages for example:- price of the product.</li>
<li>Show alert pop up in the middle of the screen and float above the application window. Avoid embedding alert messages in the whole screen. Use dark background of screen with some opacity and pop-up alert above it with some drop shadow.
<ol style="padding-left:60px; padding-top:10px; padding-bottom:10px;">
<li>Also include OK button in an alert, so that users can acknowledge the alert message and dismiss the alert. Do not include more than two buttons.</li>
<li>Use title-style capitalization and bold-style font. You should not put a period after the title. Title-style capitalization is the capitalization of every word.</li>
<li>Use bold and highlighted colors like red, yellow on dark backgrounds for alert buttons, for example “Cancel”.</li>
</ol>
</li>
<li>If you need to provide a button which performs a potentially destructive action, such as deleting all the items in a user’s album list, you should use red color. By default, such destructive buttons are displayed at the top of the action sheet where they are most visible.</li>
<li>In a table view, data present in a single-column list of multiple rows. Here each row can contain some combination of icon, text, images, and controls, and rows can be divided into sections or groups. Each row height should be of 44 pixels, so user can tap easily.</li>
<li>For making online shopping, give brief description of product, its availability, rating from other users help to analyze market value of product.</li>
<li>Easy navigation such as customized scroll, back button, next button, save button, cancel button etc should be easy to understand for the user.</li>
<li>WebKit based iPhone applications run on safari browser, thus I advice to check the HTML structure created for the device  in Safari browser and then provide it to development team for further implementation.</li>
</ol>
<p>Soon I will publish the second edition on iPhone User Interface and Usability with more tips</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1131px; width: 1px; height: 1px;"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves /> <w:TrackFormatting /> <w:PunctuationKerning /> <w:ValidateAgainstSchemas /> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF /> <w:LidThemeOther>EN-US</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables /> <w:SnapToGridInCell /> <w:WrapTextWithPunct /> <w:UseAsianBreakRules /> <w:DontGrowAutofit /> <w:SplitPgBreakAndParaMark /> <w:DontVertAlignCellWithSp /> <w:DontBreakConstrainedForcedTables /> <w:DontVertAlignInTxbx /> <w:Word11KerningPairs /> <w:CachedColBalance /> </w:Compatibility> <w:DoNotOptimizeForBrowser /> <m:mathPr> <m:mathFont m:val="Cambria Math" /> <m:brkBin m:val="before" /> <m:brkBinSub m:val=" " /> <m:smallFrac m:val="off" /> <m:dispDef /> <m:lMargin m:val="0" /> <m:rMargin m:val="0" /> <m:defJc m:val="centerGroup" /> <m:wrapIndent m:val="1440" /> <m:intLim m:val="subSup" /> <m:naryLim m:val="undOvr" /> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"   DefSemiHidden="true" DefQFormat="false" DefPriority="99"   LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Normal" /> <w:LsdException Locked="false" Priority="9" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="heading 1" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" /> <w:LsdException Locked="false" Priority="39" Name="toc 1" /> <w:LsdException Locked="false" Priority="39" Name="toc 2" /> <w:LsdException Locked="false" Priority="39" Name="toc 3" /> <w:LsdException Locked="false" Priority="39" Name="toc 4" /> <w:LsdException Locked="false" Priority="39" Name="toc 5" /> <w:LsdException Locked="false" Priority="39" Name="toc 6" /> <w:LsdException Locked="false" Priority="39" Name="toc 7" /> <w:LsdException Locked="false" Priority="39" Name="toc 8" /> <w:LsdException Locked="false" Priority="39" Name="toc 9" /> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" /> <w:LsdException Locked="false" Priority="10" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Title" /> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" /> <w:LsdException Locked="false" Priority="11" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtitle" /> <w:LsdException Locked="false" Priority="22" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Strong" /> <w:LsdException Locked="false" Priority="20" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Emphasis" /> <w:LsdException Locked="false" Priority="59" SemiHidden="false"    UnhideWhenUsed="false" Name="Table Grid" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" /> <w:LsdException Locked="false" Priority="1" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="No Spacing" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 1" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 1" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 1" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 1" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" /> <w:LsdException Locked="false" Priority="34" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" /> <w:LsdException Locked="false" Priority="29" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Quote" /> <w:LsdException Locked="false" Priority="30" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 1" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 1" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 1" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 1" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 1" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 2" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 2" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 2" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 2" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 2" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 2" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 2" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 2" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 3" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 3" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 3" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 3" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 3" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 3" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 3" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 3" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 3" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 4" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 4" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 4" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 4" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 4" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 4" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 4" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 4" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 4" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 5" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 5" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 5" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 5" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 5" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 5" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 5" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 5" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 5" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 6" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 6" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 6" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 6" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 6" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 6" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 6" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 6" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 6" /> <w:LsdException Locked="false" Priority="19" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" /> <w:LsdException Locked="false" Priority="21" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" /> <w:LsdException Locked="false" Priority="31" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" /> <w:LsdException Locked="false" Priority="32" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" /> <w:LsdException Locked="false" Priority="33" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Book Title" /> <w:LsdException Locked="false" Priority="37" Name="Bibliography" /> <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" /> </w:LatentStyles> </xml><![endif]--><!--  /* Font Definitions */  @font-face 	{font-family:"Cambria Math"; 	panose-1:2 4 5 3 5 4 6 3 2 4; 	mso-font-charset:1; 	mso-generic-font-family:roman; 	mso-font-format:other; 	mso-font-pitch:variable; 	mso-font-signature:0 0 0 0 0 0;} @font-face 	{font-family:Calibri; 	panose-1:2 15 5 2 2 2 4 3 2 4; 	mso-font-charset:0; 	mso-generic-font-family:swiss; 	mso-font-pitch:variable; 	mso-font-signature:-1610611985 1073750139 0 0 159 0;}  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-unhide:no; 	mso-style-qformat:yes; 	mso-style-parent:""; 	margin:0in; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:11.0pt; 	font-family:"Calibri","sans-serif"; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Calibri; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi;} .MsoChpDefault 	{mso-style-type:export-only; 	mso-default-props:yes; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Calibri; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi;} @page Section1 	{size:8.5in 11.0in; 	margin:1.0in 1.0in 1.0in 1.0in; 	mso-header-margin:.5in; 	mso-footer-margin:.5in; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --><!--[if gte mso 10]> <mce:style><!   /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Table Normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-priority:99; 	mso-style-qformat:yes; 	mso-style-parent:""; 	mso-padding-alt:0in 5.4pt 0in 5.4pt; 	mso-para-margin:0in; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:11.0pt; 	font-family:"Calibri","sans-serif"; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:"Times New Roman"; 	mso-fareast-theme-font:minor-fareast; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin;} --> <!--[endif]--><span style="font-size: 11pt; font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;;">Native apps use Mac's proprietary language Cocoa to create installable apps.</span></div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/16/basic-iphone-user-interface-and-usability-tips-part-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>e-Commerce Business Models</title>
		<link>http://xebee.xebia.in/2010/07/09/e-commerce-business-models/</link>
		<comments>http://xebee.xebia.in/2010/07/09/e-commerce-business-models/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 11:10:58 +0000</pubDate>
		<dc:creator>Jayant Dhingra</dc:creator>
				<category><![CDATA[e-Commerce]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=3962</guid>
		<description><![CDATA[Have you ever experienced getting yourself photographed by visiting the photographer shop? Realistically, you will be given time slot, you wait, and when your turn comes, photographer takes significant amount of time in setting up and focusing and then finally clicks a photograph. He expects few days of delivery time because of his over-running schedule [...]]]></description>
			<content:encoded><![CDATA[<div style="margin-bottom: 0in; font-weight: normal">Have you ever experienced getting yourself photographed by visiting the photographer shop? Realistically, you will be given time slot, you wait, and when your turn comes, photographer takes significant amount of time in setting up and focusing and then finally clicks a photograph. He expects few days of delivery time because of his over-running schedule and his ever going pending orders. Hopefully, after three or four days you get a call from the shop saying that your photograph is ready and shipped. Imagine there is a dark shade in your frame or any other disliking feature distorting the image which might lead to you again undergo the same procedure and invest your quality time. Isn't it?</div>
<div style="margin-bottom: 0in; font-weight: normal"><span id="more-3962"></span></div>
<div style="margin-bottom: 0in; font-weight: normal">On the other hand, if you were given a chance to have yourself clicked wherever you are, at any given time, having a flexibility of previewing the clicked photograph and options of selecting the frame and the background image etc. then what would be your reaction? Surprisingly, this is how a smart b2B2C business model works!!! An application hosted on a website allowing users to upload the pictures and getting it printed and shipped is the real example of b2B2C model. Basically, a photo studio (b) is partnered with a firm (B) which is hosting an application and catering to consumers (C) needs and other photography services.</div>
<div style="margin-bottom: 0in">Though this appears complex, there are three simple steps for any business model to be successful  which are as follows:</div>
<p><strong>1. Approach your customer rather than customers coming to you</strong></p>
<div style="margin-bottom: 0in">Search for the places where customer would like to look for these things. The studio has approached websites where students and officials would like to visit quite often for their needs.</div>
<p><strong>2. Build relationships</strong></p>
<div style="margin-bottom: 0in">The studio found a way to build on the relationship between customer and the studio by offering them what they want. Similarly, every business must find a way to build emotional connection with the brand which will actually give impetus to the business.</div>
<p><strong>3. Make it easy to transact</strong></p>
<div style="margin-bottom: 0in">This experience with online studio is seamless since customer doesn't have to arrange a photo shoot with the studio, transportation and other hassles. In fact, online transactions are faster, reliable and, most importantly, time savers.</div>
<p style="margin-bottom: 0in"><strong>This type of e-commerce comes in at least three forms</strong>:</p>
<div style="margin-bottom: 0in">1. Auctions portal, such as eBay, which allows online real-time bidding.<br />
2. peer-to-peer systems, such as the Napster which shares (music) data over internet.<br />
3. money exchange models and classified ads at portal sites.</div>
<div style="margin-bottom: 0in">Consumer-to-business (C2B) transactions involve reverse auctions, which allow consumers to drive transactions. For an example, an airlines portal (makemytrip.com) offering various route/booking options to a traveler and online competitive offer study in response to the traveler's travel requests.</div>
<div style="margin-bottom: 0in"><strong>Business models in e-commerce are as follows :</strong></div>
<div style="margin-bottom: 0in">B2C : commercial site (.com)</div>
<p>B2B : large wholesale account site to dealer</p>
<p>B2C / B2B : call center</p>
<p>B2B2b : dealer to distributor portal to small parts dealer</p>
<p>B2b2C : product extranet to distributor portal to dealer B2C shop to consumer</p>
<p>B2B2C–B2B2C platform : .com retailer site</p>
<div style="margin-bottom: 0in"><strong>The major types of e-commerce are : </strong></div>
<div style="margin-bottom: 0in">business-to-business (B2B)</div>
<p>business-to-consumer (B2C)</p>
<p>business-to-government (B2G)</p>
<p>consumer-to-consumer (C2C)</p>
<p>mobile commerce (m-commerce)</p>
<p style="margin-bottom: 0in"><strong>B2B e-commerce</strong></p>
<div style="margin-bottom: 0in">Business-to-Business e-commerce deals with relationships among businesses. The applications that deal in B2B are purchase order processing, inventory management, supply chain management and payment management, CMS software, real time auction solutions, application service providers who provide all the services from a central facility etc.</div>
<p style="margin-bottom: 0in"><strong>B2C e-commerce</strong></p>
<div style="margin-bottom: 0in">Business-to-consumer e-commerce deals with business or trade between companies and consumers. It involves customers gathering information, purchasing physical goods (books or consumer products) or information goods over an electronic network. It is the second largest and the oldest form of e-commerce which was initially started with online retailing. The common B2C business models are the online retailing companies such as Amazon.com, Drugstore.com, Barnes and Noble and ToysRus. The more common applications of this type of e-commerce are in the areas of purchasing products and information, personal finance management which pertains to the management of personal investments and finances with the use of online banking tools. B2C e-commerce reduces transactions costs by increasing access to information and allowing consumers to find the most competitive price for a product or service. B2C e-commerce also reduces market entry barriers since the cost of putting up and maintaining a website is much cheaper than building a physical firm. Moreover online purchasing saves firms from factoring in the additional cost of a physical distribution network.</div>
<p style="margin-bottom: 0in"><strong>B2G e-commerce</strong></p>
<div style="margin-bottom: 0in">Business-to-government e-commerce or B2G is generally defined as commerce between companies and the public sector. It refers to the use of the Internet for government-related activities like public procurement, licensing procedures etc. This kind of e-commerce has widest impact since the public sector has the largest customer base and hence, the greatest need for making its procurement system more effective.</div>
<p style="margin-bottom: 0in"><strong>C2C e-commerce</strong></p>
<div style="margin-bottom: 0in">Consumer-to-consumer e-commerce or C2C is simply a commerce between private individuals or consumers. This type of e-commerce is characterized by the growth of electronic marketplaces and online auctions (e-bay), particularly in vertical industries where firms/businesses can bid for what they want from among multiple suppliers. It perhaps has the greatest potential for developing new markets.</div>
<p style="margin-bottom: 0in"><strong>M-commerce</strong></p>
<div style="margin-bottom: 0in">M-commerce (mobile commerce) is the buying and selling of goods and services through wireless technology i.e., handheld devices such as mobiles and PDAs. As the mobile industry is increasing day-by-day the usage and the belief in the m-commerce is surely going to increase. The content exchanged over wireless devices seems to be faster, secured and even more efficient than that over wired e-commerce platforms.</div>
<div style="margin-bottom: 0in"><strong>Areas affected by m-commerce are as follows:</strong></div>
<div style="margin-bottom: 0in">1. Financial services, mobile banking and stock trading.<br />
2. Telecommunications where service plan changes, bill payment and account reviews can all be conducted from the same mobile device.<br />
3. Service/retail, as consumers are given the ability to place and pay for order on-the-fly like railway reservation through SMS etc.<br />
4. Information services which includes the delivery of entertainment, financial, sports news and traffic updates to a mobile device.</div>
<p style="margin-bottom: 0in"><span style="font-size: medium;"><strong>B2B</strong></span></p>
<p style="margin-bottom: 0in"><strong>Key Business drivers for B2B: </strong></p>
<div style="margin-bottom: 0in">1. The availability of a secure broadband Internet platform which provides platform for private and public B2B e-marketplaces<br />
2. The need for collaborations between suppliers and buyers<br />
3. The objective to save money, reduce delays and improve collaboration</div>
<p style="margin-bottom: 0in"><strong>Virtual Services Industries in B2B</strong></p>
<div style="margin-bottom: 0in">1. Financial services<br />
2. Online services like stock trading, financing products and other services<br />
3. Real estate<br />
4. Travel and entertainment services</div>
<div style="margin-bottom: 0in"><strong>Benefits of B2B</strong></div>
<div style="margin-bottom: 0in">1. Creates new business avenues and opportunities<br />
2. Paperless business transactions<br />
3. Expedites processing and reduces cycle time<br />
4. Lowers search costs and time for buyers to find products and vendors<br />
5. Increases productivity of employees dealing with buying and/or selling<br />
6. Improves quality of services<br />
7. Reduces marketing and sales costs (for sellers)<br />
8. Enables customized online catalogs with different prices for different customers</div>
<div style="margin-bottom: 0in"><strong>Limitations of B2B</strong></div>
<div style="margin-bottom: 0in">1. Channel conflict<br />
2. Elimination of the distributor or the retailer within the chain</div>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/09/e-commerce-business-models/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OSGi &#8211; Modular Development in Java</title>
		<link>http://xebee.xebia.in/2010/07/09/osgi-modular-development-in-java/</link>
		<comments>http://xebee.xebia.in/2010/07/09/osgi-modular-development-in-java/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 20:12:37 +0000</pubDate>
		<dc:creator>Paritosh Ranjan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://xebee.xebia.in/?p=4091</guid>
		<description><![CDATA[OSGi is standard/framework which can provide modularity to any java application. Its believed that there is lack of modularized development support in Java and some points sort of justify it. I’ll list few of them: Low-level code visibility control Java has very low level code visibility controls like private, protected, package, public. If you want [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">OSGi is standard/framework which can provide modularity to any java application. Its believed that there is lack of modularized development support in Java and some points sort of justify it. I’ll list few of them:</p>
<p><strong>Low-level code visibility control</strong></p>
<p>Java has very low level code visibility controls like private, protected, package, public. If you want any code in one package to view any code in another package then it needs to be declared as public which might expose certain functionality at other unwanted places. You either keep everything in same package or expose it through  public methods but both has some trade offs.</p>
<p><strong>Not so intelligent class path concept</strong></p>
<p>Applications are generally composed of various versions of libraries and components. The class path does not deals with different versions in an intelligent way, it simply returns the first version that it finds. Even if it did pay attention, there is no way to explicitly specify dependencies.<br />
<span id="more-4091"></span><br />
<strong>Limited deployment and management support</strong></p>
<p>Java’s support for managing deployments is also not admirable. There is no easy way in Java to deploy the proper transitive set of versioned code dependencies and execute your application. There is no obvious way to evolve your the application and components.The only way to achieve such requests is to use class loaders, which are low level and error prone.</p>
<p><strong>Enough of cursing java. Now, lets see, what OSGi can provide.</strong></p>
<ul>
<li> It can help in satisfying code dependencies before executing code.</li>
<li> It makes sure that the set of dependencies are consistent with respect to required versions.</li>
<li> Package application as logically independent JAR files and be able to deploy only those pieces which are actually need for a given installation.</li>
<li> Package application as logically independent JAR files and also to declare which code is accessible from each JAR file.OSGi enables a new level of code visibility for JAR files that allows to specify what is and what is not visible externally.</li>
<li>Define an extensibility mechanism for your application, like a plug in mechanism.</li>
</ul>
<p style="text-align: justify;">
<strong>So, What is OSGi:</strong></p>
<p>OSGi is a industry standard, defined by OSGi alliance to address the lack of support of modularization in Java. It introduces a service oriented programming model, known as “SOA in VM”.<br />
Modularity is defined as the partition/division of code into parts having separate concerns.</p>
<p><strong>OSGi overview</strong></p>
<p>The OSGi Service Platform is composed of two parts: the OSGi framework and OSGi standard services . The framework is the run time that implements and provides OSGi functionality. The standard services define reusable APIs for common tasks, such as Logging and Preferences.</p>
<p>The OSGi specifications for the framework and standard services are managed by the OSGi Alliance (http://www.osgi.org). It is an industry backed non-profit corporation.</p>
<p><strong>The OSGi Framework</strong></p>
<p>It is the application's execution environment. It provides a well-defined API to program against. The specification also enables the creation of multiple implementations of the core framework; there are a handful of well-known open source projects, such as Apache Felix, Eclipse Equinox, and Knopflerfish.</p>
<p><strong><em>The OSGi framework is basically divided into three layers:</em></strong></p>
<p><strong><em> Module layer</em></strong> – this layer is concerned with packaging and sharing code.<br />
<strong><em>Lifecycle layer</em></strong> – this layer is concerned with providing run-time module management and access to the underlying OSGi framework.<br />
<em><strong> Service layer</strong></em> – this layer is concerned with interaction and communication among modules, specifically the components contained in them.</p>
<p><span style="text-decoration: underline;"><strong>Module layer</strong></span></p>
<p>The module layer defines the OSGi module concept, called a bundle, which is simply a JAR file with extra metadata about the jar. A bundle contains class files and other resources. Bundles are the logical modules that combine to form a given application. Bundles empower you to explicitly declare which contained packages are externally visible.</p>
<p><span style="text-decoration: underline;"><strong>Lifecycle layer</strong></span></p>
<p>The lifecycle layer defines how bundles are dynamically installed and managed in the OSGi framework. the lifecycle layer defines the bundle lifecycle operations (e.g., install, update, start, stop, and uninstall). These lifecycle operations allows to dynamically administer, manage, and evolve applications in a managed way.</p>
<p><span style="text-decoration: underline;"><strong>Service layer</strong></span></p>
<p>The main features are the service-oriented publish, find, and bind : service providers publish their services into a service registry, while clients search the registry for services to use. OSGi services are local to a single VM, so, OSGi is also referred as “SOA in a VM”. OSGi services are simply Java interfaces representing a contract between service providers and clients.This makes the service layer light, since service providers are simple Java objects accessed via direct method invocation.</p>
<p><span style="text-decoration: underline;"><strong>So, to use OSGi:</strong></span></p>
<ul>
<li>Design applications as services exposed and clients implemented (normal interface driven design).</li>
<li>Package service provider and client components into separate JAR files, adding proper meta data in each jar file.</li>
<li>Start the OSGi framework.</li>
<li>Install and start all of your component JAR files.</li>
</ul>
<p style="text-align: justify;">
In the OSGi world, services will publish themselves in the service registry and clients will look up available services in the registry.</p>
<p>I will try to write out a basic example of OSGi implementation soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://xebee.xebia.in/2010/07/09/osgi-modular-development-in-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 4.029 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-20 15:38:43 -->

