tag:blogger.com,1999:blog-69908862024-03-14T11:05:47.040+05:30Sachin's Java and Software BlogThis blog is a collection of my thoughts on the happenings in the software world influenced heavily by having had the opportunity to work in a variety of interesting products and doing some exciting work with very smart people. I hope you find it worth your while.
<br>
Other Blogs :
<a href="http://sachinhejip-general.blogspot.com">general</a> | <a href="http://photomoments.blogspot.com">My Photography</a>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.comBlogger43125tag:blogger.com,1999:blog-6990886.post-950239524878867202011-09-13T11:19:00.000+05:302011-09-13T11:19:53.557+05:30A super smart way to rotate graphics<div dir="ltr" style="text-align: left;" trbidi="on">Wanted to share a very usable way for rotating graphics that I found at <a href="http://zwibbler.com/">zwibbler.com</a>. I'll show you an example -<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-xCJiISiQJ30/Tm7t40PhF2I/AAAAAAAABm0/hWnYhBXqz-Y/s1600/rotate.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="http://1.bp.blogspot.com/-xCJiISiQJ30/Tm7t40PhF2I/AAAAAAAABm0/hWnYhBXqz-Y/s320/rotate.gif" width="320" /></a></div><br />
<br />
I placed the arrow and as is typical in drawing environments like this, I got a handle to use to rotate the arrow (this is the green G like thing you see on the canvas - highlighted by the red ellipse). The neat thing is you can drag the handle so that the further away you drag the handle (indicated by the thin blue line in the UI), the finer is the rotation so you can decide how much control you want over the rotation. Compare this to Powerpoint (which is a pretty good regular use graphics program for me) and the rotation is not as intuitive or easy and requires very careful mouse manipulation to rotate things right.<br />
<br />
Very smart!<br />
<br />
This does have a problem that you are limited by the canvas and in a rectangular canvas if your rotation arc (after you have extended it to almost the edge) passes over the edge, the rotation stops. But it seems to work well - give it at try.</div>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-76791139958041656232011-07-23T19:22:00.006+05:302011-07-23T20:43:36.731+05:30HoverPopup - a JQuery UI PluginFiddling around with <a href="http://www.google.com/url?sa=t&source=web&cd=1&ved=0CCgQFjAA&url=http%3A%2F%2Fjquery.com%2F&ei=odIqTsj8DtDJrAe8wbSyDQ&usg=AFQjCNFA7CZ5sWRDhHPuipmhL7zVksjC2A&sig2=AzHsqrfNiTk2utSbhgaEiQ">JQuery</a>, JavaScript and assorted web development goodies in my spare time, I finally have a JQuery UI plugin I can call my own. This one mimics the behaviour you can find in the Gmail chat window. When you hover over a user, you'll get a panel that has additional details and actions for that context. <div><br /><div>You can <a href="http://www.sachinhejip.com/blogdemos/hoverpopup/testHP.html">try out the plug-in here</a> which is an easier way to understand what it does.</div><div><br /></div><div>It wasn't all that hard and while I was mucking my application code with this UI logic, I figured I would write it as a JQueryUI plugin so it is re-usable and has the added advantage of keeping my code clean. It turned out to be a very fun and satisfying experience. Many thanks to this article for helping me understand what needed to be done - <a href="http://bililite.com/blog/understanding-jquery-ui-widgets-a-tutorial/">http://bililite.com/blog/understanding-jquery-ui-widgets-a-tutorial/</a></div><div><br /></div><div><b>Disclaimer</b>: My first JQueryUI plug-in and not too much after having learnt JavaScript, so use this at your own risk - I expect that an expert in either will be able to provide me good feedback on how things can be improved or written much better.</div><div><br /></div><div>Here's the code for the plug-in. To use JQueryUI you need to follow the guidelines <a href="http://jqueryui.com/docs/Getting_Started">here</a>. Thanks to the wonderful <a href="http://www.tohtml.com/">http://www.tohtml.com</a> for syntax highlighting.</div><br /><pre style="color:#000000;background:#ffffff;"><span style="color:#696969; ">/*</span><br /><span style="color:#696969; "> * $(selector).hoverpopup({</span><br /><span style="color:#696969; "> leftMargin: [optional] - specify how much to the left of the trigger element the hover popup should appear</span><br /><span style="color:#696969; "> getTriggers: function that should return a list of elements to base the popup trigger on.</span><br /><span style="color:#696969; "> getPopupContents: function that is called to populate the popup</span><br /><span style="color:#696969; "> });</span><br /><span style="color:#696969; "> *</span><br /><span style="color:#696969; "> */</span><br /><span style="color:#800000; font-weight:bold; ">var</span> HoverPopup <span style="color:#808030; ">=</span> <span style="color:#800080; ">{</span><br />options<span style="color:#800080; ">:</span> <span style="color:#800080; ">{</span><br /> leftMargin<span style="color:#800080; ">:</span> <span style="color:#008c00; ">3</span><span style="color:#808030; ">,</span><br /><span style="color:#800080; ">}</span><span style="color:#808030; ">,</span><br /><br />_init<span style="color:#800080; ">:</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> _this <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> elem <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>element<span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> triggers <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>getTriggers<span style="color:#808030; ">(</span>elem<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup <span style="color:#808030; ">=</span> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'#hover-popup-1'</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">if</span> <span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>length <span style="color:#808030; ">==</span> <span style="color:#008c00; ">0</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'body'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>append<span style="color:#808030; ">(</span><span style="color:#0000e6; ">"<div id='hover-popup-1' class='hover-popup'></div>"</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup <span style="color:#808030; ">=</span> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'#hover-popup-1'</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>hover<span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> clearTimeout<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>t<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>hide<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'html'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>click<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>clickHandler <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800000; font-weight:bold; ">if</span> <span style="color:#808030; ">(</span>$<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'#hover-popup-1:visible'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.length</span> <span style="color:#808030; ">></span> <span style="color:#008c00; ">0</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> o <span style="color:#808030; ">=</span> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>offset<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> h <span style="color:#808030; ">=</span> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>height<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> w <span style="color:#808030; ">=</span> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>width<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">if</span> <span style="color:#808030; ">(</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">.</span>pageX <span style="color:#808030; ">>=</span> o<span style="color:#808030; ">.</span>left <span style="color:#808030; ">&&</span> evt<span style="color:#808030; ">.</span>pageX <span style="color:#808030; "><</span> o<span style="color:#808030; ">.</span>left <span style="color:#808030; ">+</span> w<span style="color:#808030; ">)</span> <span style="color:#808030; ">&&</span><br /> <span style="color:#808030; ">(</span>evt<span style="color:#808030; ">.</span>pageY <span style="color:#808030; ">>=</span> o<span style="color:#808030; ">.</span>top <span style="color:#808030; ">&&</span> evt<span style="color:#808030; ">.</span>pageY <span style="color:#808030; "><</span> o<span style="color:#808030; ">.</span>top <span style="color:#808030; ">+</span> h<span style="color:#808030; ">)</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#696969; ">// do nothing</span><br /> <span style="color:#800080; ">}</span> <span style="color:#800000; font-weight:bold; ">else</span> <span style="color:#800080; ">{</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>fadeOut<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>hideCallback<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><br /> <span style="color:#800080; ">}</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><br /><br /> <span style="color:#800000; font-weight:bold; ">for</span> <span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">var</span> i <span style="color:#808030; ">=</span> <span style="color:#008c00; ">0</span><span style="color:#800080; ">;</span> i <span style="color:#808030; "><</span> triggers<span style="color:#808030; ">.</span>length<span style="color:#800080; ">;</span> i<span style="color:#808030; ">++</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> $<span style="color:#808030; ">(</span>triggers<span style="color:#808030; ">[</span>i<span style="color:#808030; ">]</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>hover<span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>enter <span style="color:#808030; ">=</span> setTimeout<span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> src <span style="color:#808030; ">=</span> evt<span style="color:#808030; ">.</span>currentTarget<span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>empty<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>append<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>getPopupContents<span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> clearTimeout<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>t<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>fadeIn<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>showCallback<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>offset<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>_calculateOffset<span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span> <span style="color:#008c00; ">200</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>evt<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> clearTimeout<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>enter<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>t <span style="color:#808030; ">=</span> setTimeout<span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>fadeOut<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>hideCallback<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span> <span style="color:#008c00; ">300</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><br /><span style="color:#800080; ">}</span><span style="color:#808030; ">,</span><br /><br />destroy<span style="color:#800080; ">:</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> $<span style="color:#808030; ">.</span>Widget<span style="color:#808030; ">.</span>prototype<span style="color:#808030; ">.</span>destroy<span style="color:#808030; ">.</span>apply<span style="color:#808030; ">(</span><span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">,</span> arguments<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> _this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>unbind<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'body'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>remove<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> $<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'html'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>unbind<span style="color:#808030; ">(</span>_this<span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>clickHandler<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /><br /><span style="color:#800080; ">}</span><span style="color:#808030; ">,</span><br /><br />_calculateOffset<span style="color:#800080; ">:</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> w <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>width<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> h <span style="color:#808030; ">=</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>popup<span style="color:#808030; ">.</span>height<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> jsrc <span style="color:#808030; ">=</span> $<span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> off <span style="color:#808030; ">=</span> jsrc<span style="color:#808030; ">.</span>offset<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> l <span style="color:#808030; ">=</span> off<span style="color:#808030; ">.</span>left <span style="color:#808030; ">-</span> w <span style="color:#808030; ">-</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>leftMargin<span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">if</span> <span style="color:#808030; ">(</span>l <span style="color:#808030; "><</span> <span style="color:#008c00; ">0</span><span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> l <span style="color:#808030; ">=</span> off<span style="color:#808030; ">.</span>left <span style="color:#808030; ">+</span> jsrc<span style="color:#808030; ">.</span>width<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#808030; ">+</span> <span style="color:#800000; font-weight:bold; ">this</span><span style="color:#808030; ">.</span>options<span style="color:#808030; ">.</span>leftMargin<span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> t <span style="color:#808030; ">=</span> off<span style="color:#808030; ">.</span>top<span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">var</span> pageH <span style="color:#808030; ">=</span> $<span style="color:#808030; ">(</span>window<span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>height<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800000; font-weight:bold; ">if</span> <span style="color:#808030; ">(</span>t <span style="color:#808030; ">+</span> h <span style="color:#808030; ">></span> pageH<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span><br /> t <span style="color:#808030; ">-</span><span style="color:#808030; ">=</span> <span style="color:#808030; ">(</span>t <span style="color:#808030; ">+</span> h <span style="color:#808030; ">-</span> pageH <span style="color:#808030; ">-</span> <span style="color:#008c00; ">5</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /> <span style="color:#800080; ">}</span><br /> <span style="color:#800000; font-weight:bold; ">return</span> <span style="color:#800080; ">{</span> <span style="color:#0000e6; ">"top"</span> <span style="color:#800080; ">:</span> t<span style="color:#808030; ">,</span> <span style="color:#0000e6; ">"left"</span> <span style="color:#800080; ">:</span> l<span style="color:#800080; ">}</span><span style="color:#800080; ">;</span><br /><span style="color:#800080; ">}</span><span style="color:#808030; ">,</span><br /><span style="color:#800080; ">}</span><br /><br />$<span style="color:#808030; ">.</span>widget<span style="color:#808030; ">(</span><span style="color:#0000e6; ">"ui.hoverpopup"</span><span style="color:#808030; ">,</span> HoverPopup<span style="color:#808030; ">)</span><span style="color:#800080; ">;</span><br /></pre><br />The CSS code follows - which is not much really. You can style the contents of the popup which is your UI code. I suppose I could add this to the component itself and reduce the number of files.<div><br /><pre style="color:#000000;background:#ffffff;"><span style="color:#808030; ">#</span>hover-popup-1 <span style="color:#800080; ">{</span><br /><span style="color:#bb7977; font-weight:bold; ">display</span><span style="color:#808030; ">:</span> <span style="color:#074726; ">block</span><span style="color:#800080; ">;</span><br /><span style="color:#bb7977; font-weight:bold; ">position</span><span style="color:#808030; ">:</span> <span style="color:#074726; ">absolute</span><span style="color:#800080; ">;</span><br /><span style="color:#bb7977; font-weight:bold; ">z-index</span><span style="color:#808030; ">:</span> <span style="color:#008c00; ">10000</span><span style="color:#800080; ">;</span><br /><span style="color:#800080; ">}</span><br /></pre><br /><br /><div><br /><b>Usage:</b><br /></div></div><div>Apply hoverpopup on the jquery object - an instance will get instantiated for each element in the jquery object. The "getTriggers" function is called which gets the context element to work with. This function is expected to return a jquery object that has all the triggers in it. When the mouse hovers over one of the triggers, the popup is shown and its contents are populated by calling "getPopupContents" which can return anything that works in the JQuery "append" function.</div><div>leftMargin just controls where the popup is located - maybe this should be in a function of its own</div><div><br /></div><div>Here's an example - </div><div><br /></div><div><div><pre style="color:#000000;background:#ffffff;">$<span style="color:#808030; ">(</span><span style="color:#0000e6; ">"#div1"</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>hoverpopup<span style="color:#808030; ">(</span><span style="color:#800080; ">{</span></pre></div><div> getTriggers<span style="color:#800080; ">:</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>elem<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span></div><div> <span style="color:#800000; font-weight:bold; ">return</span> $<span style="color:#808030; ">(</span>elem<span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>find<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'.hp-test-tr'</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span></div><div> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span></div><div> getPopupContents<span style="color:#800080; ">:</span> <span style="color:#800000; font-weight:bold; ">function</span><span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span> <span style="color:#800080; ">{</span></div><div> <span style="color:#800000; font-weight:bold; ">return</span> <span style="color:#0000e6; ">'<div>'</span> <span style="color:#808030; ">+</span> $<span style="color:#808030; ">(</span>src<span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>find<span style="color:#808030; ">(</span><span style="color:#0000e6; ">'.data'</span><span style="color:#808030; ">)</span><span style="color:#808030; ">.</span>html<span style="color:#808030; ">(</span><span style="color:#808030; ">)</span> <span style="color:#808030; ">+</span> <span style="color:#0000e6; ">'<div>'</span><span style="color:#800080; ">;</span></div><div> <span style="color:#800080; ">}</span><span style="color:#808030; ">,</span></div><div> leftMargin<span style="color:#800080; ">:</span> <span style="color:#008c00; ">10</span><span style="color:#808030; ">,</span></div><div><span style="color:#800080; ">}</span><span style="color:#808030; ">)</span><span style="color:#800080; ">;</span></div><div></div></div><div><br /></div><div><b>Some more details</b></div><div>The reason I added in getTriggers, which is probably a deviation from the JQuery way of doing this - i.e. the pattern $(selector).hoverpopup would normally apply on the selector, was because I felt that instantiating a HoverPopup object for each trigger was excessive. Take a look at the demo page source to get an idea of how it was used.</div><div><br /></div><div><b>Let me know what you think and I am open to suggestions on improvements and feedback on the code.</b></div><div><br /></div></div>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-87300787934878293712009-11-01T23:50:00.005+05:302009-11-02T00:10:57.640+05:30Something product feature comparisons won't tell...<span style="font-family:trebuchet ms;">Try this in Idea - </span><br /><br /><span style="font-family:courier new;"><pre>public class MyClass {<br /> private static abstract class MyAbstractClass {<br /> public void method() {<br /> someMethod(); <--- hit alt enter on someMethod <br /> } <br /> } <br />} </pre><br /><span style="font-family:trebuchet ms;">When you hit alt-enter at someMethod and hit enter without looking at the list of options, the sheer brilliance of the implementation is to create an abstract method "someMethod" - absolutely lovely! The actual list demotes the usual default "create method someMethod()" as a second option while promoting to first (and default because of the enclosing abstract class) option "create abstract method someMethod()".<br /><br />Ya I'm sure sometimes one doesn't want abstract method but the point is that it works surprisingly well and its a choice someone though was worth promoting above the plain simple "create method someMethod()" option. Love it!<br /><br />The problem with product comparisons is that <a href="http://sachinhejip.blogspot.com/2008/12/pure-idea-joy.html?showComment=1230585300000#c8021303223876675402">someone</a></span></span><span style="font-family:courier new;"><span style="font-family:trebuchet ms;"> is bound to turn around and say - oh you can do this in Eclipse - but you really can't. Maybe you can generate abstract methods - but the sheer joy and surprise of having your IDE generate the exact thing you wanted without any additional user gestures cannot be captured in a product comparison where you go specifically choose the option. There might be a feature to do the exact same thing but when it pops up and the defaults the system uses makes it stand apart.<br /><br />Oh and yeah - <a href="http://www.jetbrains.org/pages/viewpage.action?pageId=983211">IntelliJ Idea is free and open source now</a>.<br /></span></span>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com1tag:blogger.com,1999:blog-6990886.post-60209180118287492162009-05-20T12:34:00.003+05:302009-05-20T12:51:06.756+05:30FUSE Integration Designer 1.2 is out!FUSE Integration Designer 1.2 has <a href="http://fusesource.com/products/fuse-integration-designer/">released</a>. This product marks a significant improvement in the capabilities from the preview release. The product is designed specifically for development on the Progress FUSE products which are based on the <a href="http://fusesource.com/products/enterprise-camel/">Apache Camel</a>, <a href="http://fusesource.com/products/enterprise-activemq/">ApacheMQ</a>, <a href="http://fusesource.com/products/enterprise-servicemix/">Apache ServiceMix</a> and <a href="http://fusesource.com/products/enterprise-cxf/">Apache CXF</a> products.<br /><br />I am very proud of this release. We have built this product from scratch at <a href="http://web.progress.com/Careers/india-careers.html">Progress Software India</a> (amongst many others) but what has been achieved in this product in the short time that we have worked on it makes it special!<br /><br />The product is an Eclipse SOA development toolkit focused around the <a href="http://fusesource.com">FUSE product set</a> and includes a full-featured <a href="http://www.enterpriseintegrationpatterns.com/">Enterprise Integration Patterns</a> editor specifically meant for <a href="http://fusesource.com/products/enterprise-camel/">FUSE Mediation Router (Apache Camel)</a>. Here's a screen shot of how a route will look. <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fusesource.com/images/shorter-chain.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 640px; height: 241px;" src="http://fusesource.com/images/shorter-chain.jpg" alt="" border="0" /></a>The editor now supports almost all the processors and patterns in Camel. We are actively working on adding additional endpoint support and enhancing it via usability tests and other feedback.<br /><br />We also have a host of features and improvements we are planning in the coming releases. In addition to creating routes and exporting them to Spring you can also -<br />a. Deploy them to FUSE ESB (ServiceMix)<br />b. Run and Debug them - we have full Eclipse debug integration.<br />c. Import existing routes from Spring into the editor and view/edit them<br /><br />In addition to the center piece EIP editor the product has some key features for FUSE developers -<br />a. Support for Java DSL based development<br />b. Support for ESB 4.x and 3.x deployment (all JBI packaging aspects are taken care of automatically)<br />c. Support for CXF deployment on ESB in addition to Tomcat<br />d. JMS Tooling for ActiveMQ (this is actually based on a completely extensible framework so it can support any JMS vendor - more on this in another blog).<br />e. Improved documentation to help you along with cheat sheets and stuff!<br /><br />Give the product a spin and let us know what you think <a href="http://fusesource.com/forums/forum.jspa?forumID=7">here</a>.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-57810748329143868882009-01-13T09:46:00.005+05:302009-01-13T18:51:10.707+05:30Eclipse Development at Progress Software IndiaI keep seeing google keyword searches for jobs at Progress land at this site. My group is hiring and we are looking for smart and capable Java people who would love to make a dent in the Eclipse world. We are working on <a href="http://fusesource.com/">FUSE tooling</a> amongst many other things. If you like being challenged and would like to work in a high caliber team - <a href="http://www.progress.com/careers/india/index.ssp">We are hiring</a>!<br /><br />Some of the things we have worked on in the recent past - <a href="http://en.wikipedia.org/wiki/Service_Data_Objects">SDO</a>, DAS, XSL/XQuery Mapper tools, Refactoring tools, JMS Tooling, Distributed Debugging, Tracking tools, <a href="http://activemq.apache.org/camel/">Camel</a>, <a href="http://en.wikipedia.org/wiki/BPEL">BPEL</a>, Asynchronous Web-Services, <a href="http://www.actional.com/">Actional</a>. My group is very active in the local Hyderabad Eclipse community with frequent talks and demo-camps.<br /><br />We do some pretty amazing ActionScript and Web development work here at PSI (Progress Software India). So if you are a top-notch web developer, we would love to talk to you.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VJek7wnrLwU/SWwa_jJKDlI/AAAAAAAABK8/g9Gg3bKlJtg/s1600-h/Hording4a.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 400px;" src="http://3.bp.blogspot.com/_VJek7wnrLwU/SWwa_jJKDlI/AAAAAAAABK8/g9Gg3bKlJtg/s400/Hording4a.png" alt="" id="BLOGGER_PHOTO_ID_5290633341321219666" border="0" /></a>We are based in Hyderabad, Andhra Pradesh. The Progress bill board above is up on a uni-pole on Road# 36 Jubilee Hills all this month. Look at my <a href="http://sachinhejip.blogspot.com/2007/06/progress-job-posting-on-joel-india-jobs.html">blog</a> on our previous job posting for some additional details.<br /><br />Check out <a href="http://jroller.com/rameshl/">Ramesh's blog</a> while you are at it.<br /><br />Interested? Apply <a href="http://www.progress.com/careers/india/index.ssp">here</a>.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com2tag:blogger.com,1999:blog-6990886.post-90080377791756265532009-01-11T20:58:00.006+05:302009-01-11T21:30:22.024+05:30Extending the Java Console<span style="font-family:verdana;">The lack of a good way to be able to interact with the console in Java is extremely annoying. I have been working on a small project (hopefully the content of another blog eventually) which would work best if it had good access to the console. It is frustrating that even after all these years, Java has no good way of writing a decent console based application. I can only guess that the reason for this is perhaps <a href="http://www.google.co.in/search?q=WORA&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a">WORA</a> goals are compromised? I have created an extension to the Console API which allows for better access and additional features. This blog entry is about that project.</span><span style="font-family: verdana;font-size:180%;" ><br /></span><br /><span style="font-family: verdana;font-size:180%;" >The limitations</span> <span style="font-family:verdana;"><br />Java has no equivalent of the C <a href="http://opengroup.org/onlinepubs/007908775/xcurses/getch.html">getch()</a> API which allows you to read a single character from the input buffer. The only way to get System.in.read() to return is to hit enter after typing in your input which makes it an extremely clunky way to read characters and every character is then on a new line – like a newbie Java program. Java is just not meant for console input unless you are doing simple things like “Enter Name : “.</span> <span style="font-family:verdana;"><br /><br />If you did somehow get past the lim</span><span style="font-family:verdana;">itations (and if you know a way how to do this with plain ol’ Java 6.0, please educate me) you get stuck with the lack of ability to be able to control your output. The introduction of Console.printf does add some significant output formatting capabilities, however there is no ability to move the cursor around to position your text right. Say you wanted to overwrite the current word under the cursor when Tab is pressed (like the command prompt does when you want to complete paths) – you can’t do that. </span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VJek7wnrLwU/SWoS_ojbeDI/AAAAAAAABKE/78n1rNoq1EQ/s1600-h/maven-download.GIF"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 82px;" src="http://2.bp.blogspot.com/_VJek7wnrLwU/SWoS_ojbeDI/AAAAAAAABKE/78n1rNoq1EQ/s400/maven-download.GIF" alt="" id="BLOGGER_PHOTO_ID_5290061596727146546" border="0" /></a><br /><span style="font-family:verdana;">There have been a couple of solutions to these problems - there is a hack which partially works. Maven does this neat thing when downloading anything significant from a repository where it shows the download progress.</span> <span style="font-family:verdana;"><br /><br />Maven does this by using \r at the end of the System.out.print() which allows it to overwrite the previous line. Another hack - If you wanted to do the Tab-should-overwrite-current-word-under-the-cursor thing you could do System.out.print(“\b”) as many times are required to overwrite the letters under the cursor. This would work BUT both these techniques are limited by the start of the current line – i.e. they are unable to go to the previous line which limits their usage.</span> <br /><br /><span style="font-family:verdana;">What is really required is an addition to the Console API in Java. The Console API was introduced in Java 6.0 and provides some much needed additions to Java’s capabilities to deal with character based applications. Console introduces methods to read passwords (without echo) and adds the printf method I talked about earlier. However, it still lacks the ability to read individual characters and to position the cursor and therefore was still insufficient for me.</span> <span style="font-family: verdana;font-size:180%;" ><br /><br />The solutions</span> <span style="font-family:verdana;"><br />Like every lazy developer, I did Google away for a Java curses or Console implementation. The most promising one I found was <a href="http://sourceforge.net/projects/javacurses/">JCurses</a> – a Java Curses implementation for Windows and Unix (using JNI). </span> <span style="font-family:verdana;"><br /><br />This is a nice little project that provides the curses API in Java. It provides a bunch of widgets and layouts and containers for creating UI in character mode. It’s nice but that’s not what I wanted. However, it did have a lower level API (that was not recommended for use but that’s just an invitation, isn’t it?) that allowed character input and character output. The input could be retrieved one character at a time just like I wanted but the output forced me to provide an x, y location. That in it self would be fine if I had an idea of where I was on the screen. The API lacked the ability to get and set the cursor location – basically I think the idea was to create character UIs (probably full-screen) so it wasn’t that important in the context of the JCurses project. Also, the output methods did not move the cursor which made the whole thing look and feel rather weird. I wanted something that will make the user retain his feel of the command line – not a character mode UI.<br /><br />There has been a similar project in the past which seems to have moved or died - at least I couldn't find it - here's the <a href="http://www.ethannicholas.com/enigma/">link</a>. </span><span style="font-family:verdana;">Sun has been introducing features bit by bit as mentioned above. Here's the <a href="http://java.sun.com/features/2002/09/pword_mask.html">link</a> to the discussion on the password entry. This is nothing close to what I want and continues to have the clunky enter-for-input behaviour.<br /></span><br /><span style="font-family:verdana;">Then I figured what I only wanted was really a small Console API with supporting classes. I got the Windows SDK and looked up the Console support and Windows has Console API that did exactly what I wanted that would work just fine. Writing the JNI library to get the basic console API wasn’t that hard.<br /><br /></span><span style="font-family:verdana;">The next step was to have the Java API that provided basic extensions to the Console. It has very few methods – </span> <span style="font-family:verdana;"><br /></span><ul><li><span style="font-family:verdana;">to read characters with or without echo</span><br /></li><li><span style="font-family:verdana;">to output characters at the cursor location or at a specified location</span> </li><li><span style="font-family:verdana;">to retrieve the current cursor location</span><br /></li><li><span style="font-family:verdana;">to set the cursor location</span><br /></li><li><span style="font-family:verdana;">to retrieve the screen size</span>.</li></ul><span style="font-family:verdana;">The Console library has all capabilities to let me do console input and output. What I have is lean and does exactly what I want – a useful Console extension that provides basic capabilities that were missing.<br /><br /><span style="font-size:130%;">Project - help wanted!</span><br />The project is available on Google Code <a href="http://code.google.com/p/java-console-api/">here</a>. I will try contributing back to the JCurses project when I am done. If you are interested look at console.Console. console.ConsoleBuffer provides a higher level abstraction allowing the console to be treated as a text field with an index into the text instead of dealing with the row-column nature of the cursor.<br /><br /></span><span style="font-family:verdana;">I would like some help with a few things though –<br /></span><ol><li><span style="font-family:verdana;">I used to be a good C programmer but am significantly rusty so my C code could use a good code review to look for leaks and such or any suggestions on doing thing better.</span> </li><li><span style="font-family:verdana;">I am basically on Windows so I didn’t write anything for Linux – so someone to provide a Linux port and build would be great.<br /></span></li><li><span style="font-family:verdana;">I need to get the Maven build working completely. It builds the Java part but I had trouble with the <a href="http://mojo.codehaus.org/maven-native/native-maven-plugin/">native-maven-plugin</a> to get it compile the native parts. So that is done as a bunch of batch files right now :-(</span></li></ol><span style="font-family:verdana;">If someone would like to help me with these please drop me a line. The project is using Apache License 2.0 so is available for re-use in other projects.<br /><br />If you do use the library and have any feedback, I would love to hear it. </span><span style="font-family:verdana;"><br /><br />I really think functionality should be added to the Console class in Java. There are a couple of RFE’s in the Java Bug Database that request for more capabilities in the Console API – <a href="http://bugs.sun.com/view_bug.do?bug_id=6672641">6672641</a>, <a href="http://bugs.sun.com/view_bug.do?bug_id=6552816">6552816</a>, <a href="http://bugs.sun.com/view_bug.do?bug_id=4050435">4050435</a>.</span>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com6tag:blogger.com,1999:blog-6990886.post-18388331007787120742008-12-30T00:16:00.002+05:302008-12-30T00:37:57.670+05:30Pure Idea JoyOne of the reasons why I love IntelliJ Idea. Look at the text in red below.<br /><div style="border: 1px solid darkgray;"><pre><span style="color: rgb(160, 32, 240);">package</span> com.msh.ui;<br /><br /><span style="color: rgb(160, 32, 240);">import</span> java.util.ArrayList;<br /><span style="color: rgb(160, 32, 240);">import</span> java.util.List;<br /><br /><span style="color: rgb(0, 0, 255);">/**</span><br /><span style="color: rgb(0, 0, 255);"> *</span><span style="color: rgb(106, 90, 205);"> User: sachinh</span><br /><span style="color: rgb(0, 0, 255);"> *</span><span style="color: rgb(106, 90, 205);"> Date: 28-Dec-2008</span><br /><span style="color: rgb(0, 0, 255);"> *</span><span style="color: rgb(106, 90, 205);"> Time: 17:22:38</span><br /><span style="color: rgb(106, 90, 205);"> </span><span style="color: rgb(0, 0, 255);">*/</span><br /><span style="color: rgb(46, 139, 87);"><b>public</b></span> <span style="color: rgb(46, 139, 87);"><b>class</b></span> ParsedCommand {<br /><span style="color: rgb(46, 139, 87);"><b>private</b></span> List<Property> props = <span style="color: rgb(128, 64, 64);"><b>new</b></span> ArrayList<Property>(<span style="color: rgb(255, 0, 255);">5</span>);<br /><span style="color: rgb(46, 139, 87);"><b>private</b></span> List<PluginInfo> mojos = <span style="color: rgb(128, 64, 64);"><br /> <b>new</b></span> ArrayList<PluginInfo>(<span style="color: rgb(255, 0, 255);">5</span>);<br /><br /><span style="color: rgb(46, 139, 87);"><b>public</b></span> ParsedCommand(String cmd) {<br />parseCommand(cmd);<br />}<br /><br /><span style="color: rgb(46, 139, 87);"><b>public</b></span> List<Property> getUnusedProperties() {<br /><span style="color: rgb(128, 64, 64);"><b>for</b></span> (PluginInfo p : <span style="color: rgb(255, 0, 0);"><ctrl+shift+space> fills in </span>mojos) {<br /><br />}<br /></pre><br /></div><br />Just brilliant - the fact that it picks up the right collection field<br />based on the Iterator's type. I think its called Smart Code Completion.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com3tag:blogger.com,1999:blog-6990886.post-58410170728015544332007-08-02T23:52:00.001+05:302007-08-03T00:21:55.690+05:30Rising to the topRecently, I posted a one line, grammatically incorrect (actually it just had a typo - a missing 'of') <a href="http://sachinhejip.blogspot.com/2007/07/managing-expectations.html">blog</a> in which all I did was praise Seth Godin's article and point to it. I didn't think anything I had to say about the topic could really add any additional value so I refrained from putting in any of my comments. I didn't think much about it then but afterwards I found out, interestingly, this article had reached the top of the Popular Entries for the last 24 hours at <a href="http://www.javablogs.com/">JavaBlogs.com</a>. This is not really such a big deal but I have an <a href="http://www.javablogs.com/ViewHotBlogEntries.action?view=rss">RSS feed</a> to the popular entries and it is always interesting to see what rises to the top in that list. Because Mozilla's Live Bookmarks shows only the title, I have to judge whether I want to read the article based on the title.<br /><br />Despite it being a collection of Java blogs, it is infrequent that anything seriously technical about Java manages to hold popular attention. It is always the more interestingly worded title that starts to move up rapidly (perhaps the only exceptions are the latest buzzwords and the word 'performance'). More technical titles generally languish somewhere in the middle of the list which at the top is crowded by articles that are inflammatory in their title or simply very vague about their content. The advantage of the latter (which mine must've inadvertently become) is that you have to click on the link to find out what's in the blog. This makes the blog more 'popular'. This, of course, makes it go up higher in the list allowing reaching more people and setting off a chain reaction.<br /><br />So, here's (deliberately this time) a rather vague title for this blog to test this theory :-)Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com4tag:blogger.com,1999:blog-6990886.post-5734615224976660422007-07-31T17:50:00.000+05:302007-07-31T17:53:55.710+05:30Managing ExpectationsSeth Godin has this truly wonderful blog which is always very interesting to read and <a href="http://sethgodin.typepad.com/seths_blog/2007/07/benefit-of-the-.html">this piece advice</a> is true gold.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-67173508412605422232007-07-18T12:13:00.000+05:302007-07-18T12:26:31.667+05:30Another reason to have X-GOOGLE-TOKEN?In my previous post <a href="http://sachinhejip.blogspot.com/2006/08/jabbering-with-google-talk-over-xmpp.html">here </a>about XMPP I had linked to a blog (<a href="http://dystopics.dump.be/2006/02/04/the-mysteries-of-x-google-token-and-why-it-matters/">here</a>) that describes the X-GOOGLE-TOKEN mechanism of authentication. dJOEk asks a question "Why does Google use a proprietary authentication mechanism" and then goes on to make a point about how X-GOOGLE-TOKEN could be one of the first steps twoards a Single Sign On solution from Google. This point of view has received a lot of coverage with a several people commenting about the merits of this idea or its feasibility.<br /><br />I have recently noticed another possible reason for X-GOOGLE-TOKEN to be made available and this is what I am putting forth here -<br />I had written in my blog that when I tried to sniff out the conversation between Google Talk and the server using Ethereal I found that it was using TLS and not X-GOOGLE-TOKEN and therefore all conversation was encrypted. Several people have since asked for ways around this but the whole point of TLS is to prevent such sniffing and decryption is practically (at least to me) impossible.<br /><br />Since then my current company has installed an auditing software (I know :-() for compliance reasons and interestingly Google Talk is back to using X-GOOGLE-TOKEN. When using X-GOOGLE-TOKEN only the authentication part goes over TLS while the rest of the conversation does not which means that conversations are in plain text and can be intercepted, audited and archived. So, another possible reason for supporting a different authentication mechanism could be to be able to support auditing and monitoring software?Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com7tag:blogger.com,1999:blog-6990886.post-57756519698484502022007-06-29T10:05:00.000+05:302007-06-29T17:08:02.988+05:30Progress job posting on Joel India Jobs BoardJoel from <a href="http://www.joelonsoftware.com/">JoelOnSoftware</a> has this<a href="http://jobs.joelonsoftware.co.in/"> jobs board specific to India jobs</a> which we are trying for the first time. The idea is that we will either get a bunch of resumes from the kind of people we like to hire or hear from or we will not get anything at all. Our usual experience from recruitment agencies and job sites like Monster is that we get a lot of resumes (with less than 10 percent being the ones we seriously consider and interview) and sifting through them just kills us.<br /><br />Here's the link to the job post <a href="http://jobs.joelonsoftware.com/?2202">http://jobs.joelonsoftware.com/?2202</a><br /><br />I would love to hear from people who have tried the Joel India Jobs Board and hear their experiences. If this works for us we'll do more job posts here.<br /><br />This is the text of the job post -<br /><br /><h2> Software Engineer </h2> <h3 id="at"> at <a href="http://www.progress.com/sonic">Progress Software</a> </h3> <h4> Hyderabad, India </h4> <div id="description"> We are a small and focussed engineering team in Hyderabad developing the next wave of SOA development tools for our product, the Sonic Enterprise Service Bus. We have been involved in writing Eclipse based high-end editor plug-ins for open standards based technologies such as XML, XPath, WSDL, etc using a variety of Eclipse frameworks such as EMF, GEF, etc. We have developed code generators and graphical tools for generic mapping capabilities, developing BPEL, etc, amongst many others.<br /><br />We are looking for smart and competent people to join and enhance the experience of SOA development for our users. The next few releases are going to be very exciting as we add features to improve developer productivity, including refactoring distributed applications, visual development, and on-line assistants.<br /><br />We are looking for excellent programmers in Java with up to 3 years in experience who also possess these qualities -<br />Creativity - we like people who can think of new features for our products and make a difference to our users<br />Capability - we want people who are very good at programming and can demonstrate it to us<br />Self-driven - we are self-driven people who are expected to work with minimal supervision and get things done<br /><br />Any in-depth Swing or Eclipse development experience is a plus but not a requirement.<br /><br />The team is completely based out of Hyderabad and has a QA to developer ratio of over 1-to-1. We participate in local college internship programs and in various forums.<br /><br />Comments about the Joel Test: We fix all test blockers before we write new code. The "quiet working conditions" implies offices as per the Joel Test - we have workspaces and we like to mingle and have some fun.<br /><br /><br />Our interview process is heavily biased towards programming skills so please apply only if you are serious and think of yourself to be an excellent programmer.<br /> </div> <div id="joeltest"> <h3> Joel Test Score: 11/12 </h3> <div>The <a href="http://www.joelonsoftware.com/articles/fog0000000043.html" target="_blank" title="Link opens in new window">Joel Test</a> is a twelve-question measure of the quality of a software team.</div><br /> <div id="joeltest1"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you use source control? </div> <div id="joeltest2"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Can you make a build in one step? </div> <div id="joeltest3"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you make daily builds? </div> <div id="joeltest4"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you have a bug database? </div> <div id="joeltest5"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you fix bugs before writing new code? </div> <div id="joeltest6"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you have an up-to-date schedule? </div> <div id="joeltest7"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you have a spec? </div> <div id="joeltest8"> <img src="http://jobs.joelonsoftware.com/images/x.jpg" alt="No." align="bottom" height="16" width="16" /> Do programmers have quiet working conditions? </div> <div id="joeltest9"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you use the best tools money can buy? </div> <div id="joeltest10"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you have testers? </div> <div id="joeltest11"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do new candidates write code during their interview? </div> <div id="joeltest12"> <img src="http://jobs.joelonsoftware.com/images/check.jpg" alt="Yes!" align="bottom" height="16" width="16" /> Do you do hallway usability testing? </div> </div> <h3 id="toapply"> Interested? </h3> If working with a small, focussed, informal team that is completely engaged in every aspect of product development starting from product direction and requirements gathering to engineering excites you then send us your resume at joeljobs@progress.comSachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com3tag:blogger.com,1999:blog-6990886.post-75537036407000561752007-03-09T10:27:00.000+05:302007-03-09T10:41:43.191+05:30Who cares about the chronological ordering of blogs?There is a new way of designing blogs at Blogger and in general it is very easy - point and click, move around, group - the usual goodies associated with good Web-UI these days. The new blogger re-design also has a different mechanism of listing previous posts. They now group it by chronological order. I have spent some time trying to understand why this is useful to people who come to my site? And I have been completely defeated in understanding its purpose. Before I go into a litany of my issues with this new way of organizing posts I want to show what I mean -<br /><br />This is the old way it used to be -<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VJek7wnrLwU/RfDqWzY9WAI/AAAAAAAAAE4/jbkmMhUxaws/s1600-h/oldBlogs.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_VJek7wnrLwU/RfDqWzY9WAI/AAAAAAAAAE4/jbkmMhUxaws/s400/oldBlogs.JPG" alt="" id="BLOGGER_PHOTO_ID_5039785660500498434" border="0" /></a><br />And this is the new format (which you can see in the right pane of this page if you are at the original blog site and not seeing this through a reader) -<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VJek7wnrLwU/RfDqnjY9WBI/AAAAAAAAAFA/CMI8-ICoGj4/s1600-h/blogs.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_VJek7wnrLwU/RfDqnjY9WBI/AAAAAAAAAFA/CMI8-ICoGj4/s400/blogs.JPG" alt="" id="BLOGGER_PHOTO_ID_5039785948263307282" border="0" /></a>I don't see why this useful for anyone other the blog author - and even for the author it is only informative (ah February 2007 was a good month for me - Oh Gosh! I didn't post a single thing between October 2005 and August 2006).<br /><br />Here's what is lost by going to this format -<br />a. Earlier visitors (especially first-time visitors which are the majority of the visitors according to <a href="http://www.statcounter.com">Statcounter</a>'s indication of the abysmal popularity of this blog :-)) cannot see a quick list of other posts which might catch their attention. They now have to do a deliberate task of expanding those date nodes to see what I might have written previously. I might just stop putting in titles altogether.<br />b. And really what is the reason to group it by month or date - do any of my readers really relate to the dates that I published my articles? How is August 2006 any more important than Jan 2007?<br /><br />I am sure that there is way somewhere to hack out of it and maybe I'll have to sit down and hunt for it. I searched for it in the options and could not find a way to switch this off.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com1tag:blogger.com,1999:blog-6990886.post-1559123875944117862007-02-26T17:15:00.000+05:302007-02-26T17:41:20.381+05:30Accepting the Q factorhttp://www.w3.org/2000/09/xmldsig# is the namespace for the schema for XML Signatures - one of the many, many schemas you end up accessing if you do XML Schema based completion for WS-SecurityPolicy (2005) (part of our WSDL policy editor in the Eclipse plugins for Sonic ESB Workbench). Why is this one special? For the following reason -<br /><br />If you access <a href="http://www.w3.org/2000/09/xmldsig#"><span style="font-family:courier new;">http://www.w3.org/2000/09/xmldsig#</span></a> from <a href="http://www.mozilla.com/products/download.html?product=firefox-2.0.0.2&os=win&lang=en-US">Mozilla Firefox</a> you will get back the schema at <span style="font-family:courier new;">http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd</span> (through an HTTP re-direct response code 303) but if you use Java's <span style="font-family:courier new;">java.net.URL.openConnection()</span> (basically through HttpURLConnection) you get an HTML page and not the Schema (XML) which our Schema loader does not particularly appreciate.<br /><br />It took a while for me to understand why the same URL is behaving differently. Using Eclipse 's TCP/IP Monitor I captured the headers sent by my code and used <a href="http://livehttpheaders.mozdev.org/installation.html#">LiveHTTPHeaders</a> for Firefox.<br /><br />This is what Firefox sends -<br /><br /><span style="font-size:85%;"><span style="color: rgb(51, 51, 255);font-family:courier new;" >GET /2000/09/xmldsig HTTP/1.1</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Host: www.w3.org</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2) Gecko/20070219 Firefox/2.0.0.2</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Accept-Language: en-us,en;q=0.5</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Accept-Encoding: gzip,deflate</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Keep-Alive: 300</span><br /><span style="color: rgb(51, 51, 255);font-family:courier new;" >Connection: keep-alive</span><br /></span><br />and this is what it receives -<br /><br /><span style="color: rgb(204, 153, 51);font-size:85%;" ><span style="font-family:courier new;">HTTP/1.x 303 See Other</span><br /><span style="font-family:courier new;">Date: Mon, 26 Feb 2007 11:50:20 GMT</span><br /><span style="font-family:courier new;">Server: Apache/1.3.37 (Unix) PHP/4.4.5</span><br /><span style="font-family:courier new;">WWW-Authenticate: Basic realm="W3CACL"</span><br /><span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" >Location: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd</span><br /><span style="font-family:courier new;">Keep-Alive: timeout=2, max=99</span><br /><span style="font-family:courier new;">Connection: Keep-Alive</span><br /><span style="font-family:courier new;">Transfer-Encoding: chunked</span><br /><span style="font-family:courier new;">Content-Type: text/html; charset=iso-8859-1</span></span><br /><br /><br />But when HttpURLConnection sends the request this is what it sends -<br /><br /><span style="color: rgb(51, 51, 255);font-size:85%;" ><span style="font-family:courier new;">GET /2000/09/xmldsig HTTP/1.1</span><br /><span style="font-family:courier new;">User-Agent: Java/1.4.2_12</span><br /><span style="font-family:courier new;">Host: www.w3.org</span><br /><span style="font-family:courier new;">Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2</span><br /><span style="font-family:courier new;">Connection: keep-alive</span></span><br /><br />and this is what it receives -<br /><br /><span style="color: rgb(204, 153, 51);font-size:85%;" ><span style="font-family:courier new;">HTTP/1.1 303 See Other</span><br /><span style="font-family:courier new;">Date: Mon, 26 Feb 2007 11:56:47 GMT</span><br /><span style="font-family:courier new;">Server: Apache/1.3.37 (Unix) PHP/4.4.5</span><br /><span style="font-family:courier new;">WWW-Authenticate: Basic realm="W3CACL"</span><br /><span style="color: rgb(153, 102, 51); font-weight: bold;font-family:courier new;" >Location: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html</span><br /><span style="font-family:courier new;">Keep-Alive: timeout=2, max=99</span><br /><span style="font-family:courier new;">Connection: Keep-Alive</span><br /><span style="font-family:courier new;">Transfer-Encoding: chunked</span><br /><span style="font-family:courier new;">Content-Type: text/html; charset=iso-8859-1</span></span><br /><br />Notice the difference in the Location header<br />Firefox : <span style="color: rgb(204, 153, 51);font-size:85%;" ><span style="font-family:courier new;">Location: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd</span></span><br />Java URLConnection : <span style="color: rgb(204, 153, 51);font-size:85%;" ><span style="font-family:courier new;">Location: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html<br /></span></span><br />The problem turns out to be in the Accept header set by Java URLConnection by default (or I guess the Sun HttpURLConnection implementation). <span style="color: rgb(51, 51, 255);font-size:85%;" ><span style="font-family:courier new;"><br /><br />Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 </span></span><br /><br />Note no text/xml as in Firefox. Although there is a */* its 'q' value is lower than text/html and the nice server at www.w3.org uses this to change its output to suit what is best accepted by the user-agent. I guess since they are the standards organization they should do this :-). Fixing the accept header fixes this behaviour. Is there something I am missing in my understanding of how URLConnection works?Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com1tag:blogger.com,1999:blog-6990886.post-650474127749547832007-02-24T18:28:00.000+05:302007-02-26T17:50:13.133+05:30Experiments with development on the Nokia 6265I recently got myself the <a href="http://www.nokia-asia.com/nokia/0,1522,,00.html?orig=/6265">Nokia 6265 CDMA</a> phone. It is a nice phone and I intend to write a reveiw of it in my other blog one of these days. The phone supports the Nokia's Series 40 3rd Edition development platform and I am trying out developing Java Micro Edition applications for it. I hit some interesting problems and found some solutions - I am trying to chronicle them here.<br /><br />Firstly, I have never done development for a mobile phone so I had to start from scratch. I wanted to know what I could do with my phone and Nokia had quite a lot of information. They have these videos of their Eclipse integration called Carbide.j which seemed interesting although a little painful (being a graphical modeling like UI and all).<br /><br />I found the Nokia site a tad vague about what exactly is needed for what but eventually I figured I needed the Nokia Series 40 3rd Edition SDK. Now, Nokia has 3rd Edition Feature Pack 1 and 3rd Edition Feature Pack 2. It wasn't very clear to me which one would work and I chose the base version and thankfully that is the right one. Only one phone so far supports Feature pack 1 as far as I know.<br /><br />After installing the SDK, the documentation said that I need a JDK, Eclipse, NDS for Java ME, and then I should install SDK. Did I mention that the Nokia site is slightly confusing? :-) I went off in search for NDS and found out that it is now renamed to Carbide.j and is a 135+ MB download. While it was downloading, I thought I would try and locate J2ME support in IntelliJ Idea.<br /><br /><span style="font-size:130%;">IntelliJ Idea J2ME integration</span><br /><span style="font-size:100%;"><br />Now, this is the nice part.<br /><br />I went through the IntelliJ Idea documentation which described how to set up a J2ME module and the only part that looked a little hard was the Mobile JDK configuration. I crossed my fingers and pointed at the Nokia installation and IntelliJ found all it needed - bootclasspath, javadocs, emulator, etc. It is really sweet!!<br /><br />Everything works out of the box - compile works great, and <span style="font-weight: bold;">when you run it runs against the Nokia emulator</span>. Even debugging is seamlessly supported!! Fantastic - and no need for Eclipse or the Eclipse plugins! Needless to say I cancelled my Carbide.j download. You do not need it for development on the Nokia phones. I hope the Nokia guys put this on their documentation.<br /><br /><span style="font-weight: bold;">One strange problem</span> so far (in my HelloWorld application) has been that the jad and jar generated by IntelliJ is not working on my phone or on the emulator. It fails with an error message saying "Application invalid. Delete?". There is a temporary file that Idea is generating which seems to work. I think I am missing something here. I would appreciate any help.<br /><br /><br /></span>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com6tag:blogger.com,1999:blog-6990886.post-77421289079377272602007-02-24T17:11:00.000+05:302007-02-24T17:21:50.596+05:30Annoying UI Change in Firefox 2.0<a href="http://www.mozilla.com/en-US/">Firefox</a> 2.0 is out and I upgraded from 1.5.x to 2.0. While closing a tab I realized something was amiss. In 1.5.0 there are two ways to close a tab - each tab is associated with a close button and the tab bar has a close button at its extreme right which is applicable to the most active tab. That is the button I use the most and that is gone from 2.0.<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VJek7wnrLwU/ReAlpIuRaLI/AAAAAAAAAEo/UU0SsHsye58/s1600-h/Firefox-no-close.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_VJek7wnrLwU/ReAlpIuRaLI/AAAAAAAAAEo/UU0SsHsye58/s400/Firefox-no-close.JPG" alt="" id="BLOGGER_PHOTO_ID_5035065772046641330" border="0" /></a><br />Why do I think this is an annoying change? The old button on the right of the task bar never moved - which meant irrespective of which tab I was on I could aim my mouse over it (a centimeter square area that my hand and wrist manage to reach magically) and close without having to think too much about it. Now, I have to look for the close button and my target has just expanded horizontally to unpredictably include my entire horizontal resolution. Another reason was I could close many consecutive windows one after the other just pressing the button multiple times because the selection automatically moves to the next tab. No longer possible. Arghhh! Hopefully there is a preference somewhere which can get it back - but so far I haven't found it. In its place there is a drop down of all windows to quickly navigate to it.<br /><br />Well...sigh...I still love Firefox and I'll just use Ctrl+F4 more frequently...Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com5tag:blogger.com,1999:blog-6990886.post-73511382662635413072007-01-14T10:27:00.000+05:302007-01-15T09:52:34.564+05:30What I don't like about the iPhoneApple has hit that elusive textbook-class marketing success. iPhone has the same buzz that Gmail had when Google decided that their Beta product is available only by invitation. iPhone is 6 months away from release but look at the talk around it. Everyone has heard of it now because everyone wants to talk to someone else about it . And everyone is blogging about the iPhone - and here's my two cents on it.<br /><br />You've heard the comments - it is a gorgeously styled phone but has not much new to offer - it is just slickly packaged and marketed. It is quite possible that the actual product might be fantastic. A lot of the magic is in the User Interface and there is only so much you can say about it - like the Apple iPod. The fact that the click wheel makes a clicking sound (by the small speaker only for it) is best when used and not when you read it. So, final judgements on how great it is can probably only be passed once the product comes out. It does look very nice.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VJek7wnrLwU/Ram9nvpLCPI/AAAAAAAAACo/10Py0PKcbWc/s1600-h/iPhone-keyboard.JPG"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://1.bp.blogspot.com/_VJek7wnrLwU/Ram9nvpLCPI/AAAAAAAAACo/10Py0PKcbWc/s320/iPhone-keyboard.JPG" alt="" id="BLOGGER_PHOTO_ID_5019751750182832370" border="0" /></a><br />So, what is this blog about - just a couple of points about the UI from the demos I saw on the apple site.<br /><br />Take a look at this screen - I know the iPhone does not have a keyboard and provides a software keyboard which you can use like a regular one. That is a fine idea but look at the keyboard.<br /><br />What I don't like about it is that although it is a QWERTY keyboard it does not have a full keyboard - the digits and symbols have to be accessed much like an old phone which had menu options for 123, Symbols, etc. Unfortunate.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VJek7wnrLwU/RanARPpLCQI/AAAAAAAAAC0/MawW153mnLk/s1600-h/Blackberry-email.JPG"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_VJek7wnrLwU/RanARPpLCQI/AAAAAAAAAC0/MawW153mnLk/s320/Blackberry-email.JPG" alt="Blackberry keyboard and screen together" id="BLOGGER_PHOTO_ID_5019754662170659074" border="0" /></a>The next thing that strikes me is that there is not enough space to see or read what is on the screen after the keyboard pops up - most of the screen is taken up by the keyboard and the effective space is down to a couple of lines. My age-old phone has more space than that. My wife's Blackberry (left - I couldn't capture a better image of email and keyboard together - it isn't meant to be Blackberry marketing! :), despite its not so good-looks, has a practical amount of screen real-estate. Definitely a win for the Blackberry here. Usually, phones in this category support hand-writing recognition using a stylus which allows them to provide larger screen estate without the keyboard in the way or they do it the Blackberry way. With no stylus the iPhone loses space.<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VJek7wnrLwU/Ram8r_pLCOI/AAAAAAAAACc/x99Hs4bswqc/s1600-h/iPhone-SMS.JPG"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://2.bp.blogspot.com/_VJek7wnrLwU/Ram8r_pLCOI/AAAAAAAAACc/x99Hs4bswqc/s320/iPhone-SMS.JPG" alt="" id="BLOGGER_PHOTO_ID_5019750723685648610" border="0" /></a><br /><br />This is the SMS screen (right). Looks cute but if the demo follows the product faithfully the ordering of messages seems wrong. I believe it should be in reverse chronological order so that the most relevant messages (the recent ones) are on top versus having to scroll down. Also, this is perhaps the most wasteful of screen layout designs - nice but wasteful. Hardly a good idea considering how little of it you have. But then perhaps these are just preferences that you can set - like Google Talk.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VJek7wnrLwU/Ram75PpLCNI/AAAAAAAAACQ/v04B9hWI87s/s1600-h/iPhone-call.JPG"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://3.bp.blogspot.com/_VJek7wnrLwU/Ram75PpLCNI/AAAAAAAAACQ/v04B9hWI87s/s320/iPhone-call.JPG" alt="" id="BLOGGER_PHOTO_ID_5019749851807287506" border="0" /></a>What I like is the interface you get when you are in a call. The large buttons that come up for Speaker, Mute, Hold, etc are excellent for usability. I have the hardest time figuring out which button is which on my phone and even on the Blackberry you have to know what button does what - this is so much more elegant and usable.<br /><br />All said, the Apple iPhone is definitely going to be a serious contender in the phone market and like in the case of music players might cause the other competition to provide a host of new features. Most people have predicted that the iPhone will not have the same impact that iPod did - which is probably very easy to predict because the phone market is quite mature and a tie in to a service provide (Cingular) restricts the user-base but I still expect the iPhone to make quite an impact. Whether the Blackberry users switch - can't say - those things are quite addictive.<br /><br />The overall iPhone UI theme is large, informal text which looks aesthetically pleasing and is very readable but wastes space. In contrast, business phones like the Blackberry are all business-like keeping everything to efficient levels while compromising on looks, jazz and style.<br /><br />Btw, I wonder if I am the only one who finds QWERTY keyboards a strange feature on mobile phones when people type with their thumbs. So quickly now - Where is the D key, the P key, or the N key, the X key - can you answer without looking at the keyboard? For people who can type with all fingers it is quite useless because the fingers keep the memory of the letters they type and not the thumbs (in fact the thumb only knows the space key) and definitely not the eyes so they have to hunt for the letters. For people who can't type and look at the keys when they type, I wonder if they do they find QWERTY layout any easier than a ABCDEF layout? Seems to me that for either group the ABCDEF layout makes more sense than having to hunt the entire screen.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com1tag:blogger.com,1999:blog-6990886.post-21274491463325225362006-10-24T17:04:00.000+05:302006-10-24T17:39:27.169+05:30Part 3: Jabbering with Google Talk over XMPPThis is part 3 of a series of blogs on getting IM working with a Google Talk client using XMPP. Parts 1 and 2 are here -<br /><a href="http://sachinhejip.blogspot.com/2006/08/jabbering-with-google-talk-over-xmpp.html">Jabbering with Google Talk over XMPP</a><br /><a href="http://sachinhejip.blogspot.com/2006/08/part-2-jabbering-with-google-talk-over.html">Part2: Jabbering with Google Talk over XMPP</a><br /><br />This one is going to be short one because I managed the last part of the Google Talk basic IM interaction which was presence and messaging without too much effort.<br /><br /><span style="font-weight: bold;">Presence</span><br />Presence is how you announce that you are available/unavailable/busy/whatever. It is through presence that people tell you that they have stepped away for a quick cuppa mocha - the part where you can have witty remarks show up against your name - basically your network availability.<br /><br />The basic presence part is easy - requiring sending only a <presence> stanza. If you are already on the "roster" (XMPP's name for a buddy list) then your presence will be indicated by your id going "online" in Google Talk. You would have to be invited and on the users' roster for that.<br /><br />Doing the presence part itself is optional - you can still send messages even if you have not announed your presence. The only difference is that messages directed to you are not sent by Google Talk because it is not aware of your avaiability and your friends won't know if you are online.<br /><br />Presence has a bunch of interesting details which I won't go into mostly because I skipped most of them :-) but here's a quick list of what it can do -<br /></presence><ul><li>announce availability/unavailability plus a bunch of sub-states</li><li>provide comments along with status</li><li>allow for subscription (notification of presence of others on the server)</li><li>change subscription</li><li>etc</li></ul><span style="font-weight: bold;">Instant Messaging<br /></span>The whole IM bit is where I was leading through and here it is. I did cover in <a href="http://sachinhejip.blogspot.com/2006/08/part-2-jabbering-with-google-talk-over.html">Part 2</a> the messaging part which was basically <span style="color: rgb(51, 102, 255);font-family:courier new;font-size:85%;" ><br /><br /><message from=\"XXXXXXXX@gmail.com/D922F673\" to=\"YYYY@gmail.com\" type='chat' xml:lang=\"en\"><body>TESTING!!!</body></message><br /><br /></span>and this is pretty much it actually. You can have the following in the message though - subject(s), body and a thread.<br /><br />So once you have set up a Thread reading from your response stream you get message stanzas from all your friends and you can send them your messages on the request stream - thats it. Google Talk behaves just fine identifying the program as a non-Google Talk client.<br /><br />Here's a silly picture of the two clients talking to each other.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/3110/853/1600/xmpp.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger2/3110/853/320/xmpp.jpg" alt="" border="0" /></a>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com1tag:blogger.com,1999:blog-6990886.post-70689576225707989012006-10-07T17:50:00.000+05:302006-12-19T14:12:13.993+05:30Answers to some seemingly common Java questionsWhenever I go through the Keyword Analysis page of <a href="http://www.statcounter.com/">Statcounter</a>, which manages my blog web usage statistics for me, I see a bunch of Java questions which I can answer. However the page that people land on to never has the relevant answer to the query. With my recent Repetitive Stress Injury I am pretty much staying away from doing any more work than is required to help my hands heal faster. This is keeping me from working on my <a href="http://sachinhejip.blogspot.com/2006/08/part-2-jabbering-with-google-talk-over.html">Google Talk </a>programs. So, having nothing better to do I am going to try and answer some of the questions or searches that I saw coming to my blog.<br /><br /><span style="font-weight: bold;">Search Keywords: Java printStackTrace does not show line number<br /></span>Happens if the classes that are part of the stack trace have not been compiled with the debugging option (-g) on. Here's <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javac.html#options">the link for details on javac's options.</a><span style="font-weight: bold;"> </span>The solution is to re-compile the classes with this option on and then recreate the exception. If it is not code you can build then there is not much you can do here unfortunately - you will have to <a href="http://sachinhejip.blogspot.com/2005/05/reflections-on-debugging.html">analyze</a> the code to figure out where it went wrong. Not having debug information while compiling usually also means that you won't get any local variable information while debugging in a JPDA debugger (to be complete precise that would mean that the -g:vars option has not been specified).<br /><br /><span style="font-weight: bold;">Search Keywords: how can i tell what caused a concurrentmodificationexception?<span style="font-weight: bold;"><span style="font-weight: bold;"><span style="font-weight: bold;"></span></span></span><br /></span>A ConcurrentModificationException happens if a java.util.Collection is modified while an Iterator is iterating over it. There are many ways you can end up doing this - I am going to try and list the situations that I believe are most common.<br /><br /><span style="font-size:78%;">Disclaimer: Code snippets do not use generics which won't make any difference anyway.</span><br />1.] Listeners<br />Consider this listener interface -<br /><pre><br /><span style="color: rgb(0, 0, 153);font-size:85%;" ><span style="font-family:courier new;">XYZListener.java</span><br /><span style="font-family:courier new;"> 1 public interface XYZListener {</span><br /><span style="font-family:courier new;"> 2 void eventOccurred(Event evt);</span><br /><span style="font-family:courier new;"> 3 }</span></span><br /></pre><br /><br />and this implementation -<br /><pre><br /><span style="font-size:85%;"><span style="color: rgb(0, 0, 153);font-family:courier new;" >XYZListenerImpl.java</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 4 public class XYZListenerImpl.java {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 5 public void eventOccurred(Event evt) {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 6 evt.getEventSource().removeXYZListener*this);</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 7 // do something useful</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 8 }</span><br /><span style="font-family:courier new;"><span style="color: rgb(0, 0, 153);"> 9 }</span><br /></span></span></pre><br />where <span style="font-size:85%;"><span style="font-family:courier new;">Event.getEventSource()</span></span> returns the object against whict XYZListenerImpl's instance was registed as a listener.<br /><br />Now, you will get a ConcurrentModificationException if the EventSource is implemented this way -<br /><pre><br /><span style="color: rgb(0, 0, 153);font-size:85%;" ><span style="font-family:courier new;">EventSource.java</span></span><br /><span style="font-size:85%;"><span style="color: rgb(0, 0, 153);font-family:courier new;" > 10 public class EventSource {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 11 private List listeners = Collections.synchronizedList(new LinkedList());</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 12 public void addXYZListener(XYZListener l) {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 13 if (!listeners.contains(l))</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 14 listeners.add(l)</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 15 }</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 16</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 17 public void removeXYZListener(XYZListener l) {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 18 listeners.remove(l);</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 19 } </span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 20</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 21 protected void fireEvent(Event evt) {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 22 for (Iterator iter = listeners.iterator(); iter.hasNext();) {</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 23 XYZListener listener = (XYZListener)iter.next();</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 24 listener.eventOccurred(evt);</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 25 }</span><br /><span style="color: rgb(0, 0, 153);font-family:courier new;" > 26 }</span><br /><span style="font-family:courier new;"><span style="color: rgb(0, 0, 153);"> 27 }</span><br /></span></span></pre><br />This is going to cause a <span style="font-size:85%;"><span style="font-family:courier new;">ConcurrentModificationException </span></span>at line 24 (assuming that there are more than one listeners registered and <span style="font-size:85%;"><span style="font-family:courier new;">XYZListenerImpl </span></span>is not the last one ;-)) because in line 6 the <span style="font-size:85%;"><span style="font-family:courier new;">listeners </span></span>List is modified while it is being iterated over in <span style="font-size:85%;"><span style="font-family:courier new;">EventSource.fireEvent</span></span>'s Iterator.<br />The solution in this case is to use the right pattern for firing events -<br /><pre><br /><span style="color: rgb(0, 0, 153);font-size:85%;" ><span style="font-family:courier new;">protected void fireEvent(Event evt) {</span><br /><span style="font-family:courier new;"> List clonedList = new ArrayList(listeners);</span><br /><span style="font-family:courier new;"> for (Iterator iter = clonedList.iterator(); iter.hasNext();) { // [19 Dec] edited - thanks to Anon comment</span><br /><span style="font-family:courier new;"> XYZListener listener = (XYZListener)iter.next();</span><br /><span style="font-family:courier new;"> try {</span><br /><span style="font-family:courier new;"> listener.eventOccurred(evt);</span><br /><span style="font-family:courier new;"> } catch(Exception ex) {</span><br /><span style="font-family:courier new;"> // this prevents one bad listener from preventing the event from going to others</span><br /><span style="font-family:courier new;"> // log the exception</span><br /><span style="font-family:courier new;"> ex.printStackTrace();</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;">}</span></span><br /></pre>2.] Incorrect coding<br />This will cause a ConcurrentModificationException -<br /><pre><br /><span style="color: rgb(0, 0, 153);font-size:85%;" ><span style="font-family:courier new;">public void someMethod(List l) {</span><br /><span style="font-family:courier new;"> for (Iterator iter = l.iterator(); iter.hasNext();) {</span><br /><span style="font-family:courier new;"> Object o = iter.next();</span><br /><span style="font-family:courier new;"> if (someCondition()) {</span><br /><span style="font-family:courier new;"> l.remove(o);</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;">}</span></span><br /><br /></pre><br />Fix this by using Iterator.remove() instead of doing a list.remove()<br /><br />3.] Concurrency<br />The trickiest one is when the Collection gets modified by another thread while it is being iterated upon. One solution is to clone the collection (e.g. new ArrayList(list)) and then iterate upon it. To find out where the List got modified -<br /><ol><li>Create a wrapper List similar to Collections.SynchronizedList which delegates all methods to the enclosed List.</li><li>In the add/remove and any other method that modifies the List dump the current Thread's stacks using Thread.dumpStack. Refer to <a href="http://sachinhejip.blogspot.com/2005/05/reflections-on-debugging.html">this</a>. I suggest printing the current timestamp and the Thread's id for easy collating and the List's hashCode() to identify operations against each List instance.<br /></li><li>When you get the ConcurrentModificationException print the List's hashCode and look for the last print from the List modification logs for a list of this hashCode and you should know which two threads are the "culprits".</li></ol><br /><span style="font-weight: bold;">Search Keywords: how do you add a print statement ever 5 minutes in java</span><br />This is quite easy. Create a java.util.Timer class and add a TimerTask and set it to fire every 5 minutes and write the print statements in the TimerTask.<br /><br /><span style="font-weight: bold;">Search Keywords: using ethereal to capture google talk</span><br />This is not really possible after TLS is set up as I discussed in the comments <a href="http://sachinhejip.blogspot.com/2006/08/jabbering-with-google-talk-over-xmpp.html">here</a>. Google Talk mandates TLS and once the stream gets encrypted the whole point of that is to not be able to sniff out the contents using something pretty much like Ethereal.<br /><br />There are a couple of other interesting queries that I have not taken up<br /><span style="font-weight: bold;">what are some things that made java so popular?</span><br /><span style="font-weight: bold;">java 5 why </span><br /><span style="font-size:85%;">(I would say - Generics)</span><br /><span style="font-weight: bold;">why isn't java used for games</span><br /><span style="font-size:85%;"> (I really don't know if it is or it is not used for games and what kind of games?)</span><br /><span style="font-weight: bold;"><br /><br /></span>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com2tag:blogger.com,1999:blog-6990886.post-1156588665601733752006-08-26T15:25:00.000+05:302006-08-26T16:12:38.543+05:30Part 2: Jabbering with Google Talk over XMPPThis is Part 2 of the posts that describe my attempts to do something interesting (eventually) with Google Talk using XMPP. Part 1 is <a href="http://sachinhejip.blogspot.com/2006/08/jabbering-with-google-talk-over-xmpp.html">here</a>.<br /><br />So finally I had my test Google Talk account successfully send a test message to my regular Google Talk account. The XML for that is<br /><br /><span style="color: rgb(51, 102, 255);font-family:courier new;font-size:85%;" ><message from=\"XXXXXXXX@gmail.com/D922F673\" to=\"YYYY@gmail.com\" type='chat' xml:lang=\"en\"><body>TESTING!!!</body></message><br /><span style="color: rgb(153, 153, 153);"><br />Note that the from value is the JID returned by the Gmail server.</span><br /></span><br />I am still quite far from where I want this to go. However, I am glad I am making progress. The last time (in Part 1) my quickly-put-together test code was reaching a point where it could no longer be used because I needed to save conversation <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/714/408/1600/XMPPClassDiag.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/714/408/320/XMPPClassDiag.jpg" alt="" border="0" /></a>state like the jid which it didn't allow.<br /><br />Now, with a design and a framework in place I hope I can move on to newer things with Google Talk. Here's a brief class design diagram. I am not very formal with UML diagrams - I pick and choose what I like from UML so if it is not classic UML I apologize to those who may get irked by it. Let me know what you think of the design. I haven't seen what the Jive XMPP library design looks like yet.<br /><br /><br /><span style="font-weight: bold;font-size:130%;" >XML Parsing Challenges</span><br />An interesting implementation challenge was XML Pull Parsing. I tried (briefly) the Stax parser in J2SE but I found it to be a little inconvenient with its event id based mechanism. I might be quite wrong though because I am sure I didn't spend as much time exploring its fit into my solution as I should have. I found myself thinking in terms of iterating over available pieces of XML as required.<br /><br />The XMPP response stream is like an XML document where each response is another child of the document element. And you don't get the next child until you have sent a request. (I don't know how one receives messages yet so there might be some twist to this story later).<br /><br />So, an XMLIterator which allowed me get the details of the current element and then waited until I asked it move to the next one was what I wanted and <a href="http://xmliter.sourceforge.net">this open source project</a> does pretty much that. Thank you very much <i>Mark.<br /><br /></i>What I also wanted was an API that returned DOM nodes (preferably) as it saw them in the stream. Of course, the document element node will remain incomplete until the end is reached but thats just a technicality because all that is required to "complete" it is the end-tag which has no real information. I was looking for something like this -<br /><br /><span style="color: rgb(255, 204, 51);font-family:courier new;font-size:85%;" ><span style="color: rgb(0, 51, 51);">XmlIterator iter = new XmlIterator(source);</span><br /><span style="color: rgb(0, 51, 51);">iter.advance();</span><br /><span style="color: rgb(0, 51, 51);">// we are now on the document element node</span><br /><span style="color: rgb(0, 51, 51);">XmlIterator children = iter.children();</span><br /><span style="color: rgb(0, 51, 51);">while (children.advance()) {</span><br /><span style="color: rgb(0, 51, 51);"> Node node = children.next();</span><br /><span style="color: rgb(0, 51, 51);">}</span><br /></span><br />I have a simple XML Node structure built over XmlIterator which works for me - maybe that's a project for later.<br /><br /><br /><br />Next post I aim to be able to maintain a conversation with a Google Talk client and hope to have enhanced the framework to be able to do more things than just chat.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-1154937951978496602006-08-07T11:54:00.000+05:302006-08-11T21:53:24.416+05:30Jabbering with Google Talk over XMPPI am writing an XMPP client that can talk to Google and maybe implement some cool things on top of it. So this weekend I began exploring the specs and intend to maintain an account of how it is going. XMPP is a widely discussed/implemented topic and has many many clients - so it is no research topic. Why did I choose to do this? Just for fun to try something new (for me) out. I know I can get the XMPP library from <a href="http://www.jivesoftware.com">Jive Software</a> but thats no fun. Sometimes re-inventing the wheel has its own pleasures :-).<br /><br />The <a href="http://www.xmpp.org/specs/">XMPP specs</a> are an open standard on which <a href="http://www.jabber.org">Jabber</a> and <a href="http://talk.google.com">Google Talk</a> are based. There are a number of extensions which are under consideration and most of the cool things have already been thought of such as RPC over XMPP.<br /><br />So far as a prototype, I have managed to get connected to talk.google.com, perform starttls and authenticate myself followed by resource binding and initiating a session. Now, my prototype code is hitting its limitations and I will have to spend some time fixing it to be able to do some serious talking with XMPP. I have also managed to get my account successfuly blocked for authenticating incorrectly as well - but got out of that mess. :-)<br /><br />I was hoping to sniff out the conversation that the Google Talk client is having with the server using Ethereal as per <a href="http://dystopics.dump.be/2006/02/04/the-mysteries-of-x-google-token-and-why-it-matters/">this blog</a> that describes X-GOOGLE-TOKEN, a Google mechanism for Single Sign-on. As per that blog, the Google Chat client does not do starttls but does an XMPP authentication over an un-secure socket using a Google generated token (the actual authentication with the Google token server is over https) so all the communication can be sniffed. However, my client seems to be doing a starttls and I can't sniff any details out after the proceed response. Too bad - appears that Google Talk has changed since the blog was written.<br /><br />Here's the sequence of communication with the Google Talk server - (formatted for readability with text sent from me in <span style="color: rgb(51, 102, 255);">this </span>colour and the response in <span style="color: rgb(255, 102, 102);">this </span>colour and comments in <span style="color: rgb(153, 153, 153);">this </span>colour).<br /><br /><span style=";font-family:courier new;font-size:85%;" ><br /><pre><br /><span style="color: rgb(51, 102, 255);"><stream:stream</span><br /><span style="color: rgb(51, 102, 255);"> to='gmail.com'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns='jabber:client'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns:stream='http://etherx.jabber.org/streams'</span><br /><span style="color: rgb(51, 102, 255);"> version='1.0'></span><br /><span style="color: rgb(255, 102, 102);"><?xml version="1.0" encoding="UTF-8"?></span><br /><span style="color: rgb(255, 102, 102);"><stream:stream from="gmail.com" id="X0B367FC8A9597BA4" version="1.0" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client"></span><br /><span style="color: rgb(255, 102, 102);"> <stream:features></span><br /><span style="color: rgb(255, 102, 102);"> <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/></span><br /><span style="color: rgb(255, 102, 102);"> <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></span><br /><span style="color: rgb(255, 102, 102);"> <mechanism>X-GOOGLE-TOKEN</mechanism></span><br /><span style="color: rgb(255, 102, 102);"> </mechanisms></span><br /><span style="color: rgb(255, 102, 102);"> </stream:features></span><br /><br /><span style="color: rgb(51, 102, 255);"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" /> <span style="color: rgb(153, 153, 153);"><--- Start TLS - basically the rest of the communication is over SSL</span></span><br /><span style="color: rgb(255, 102, 102);"><proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/></span><br /><br /><span style="color: rgb(153, 153, 153);">TLS Succeeded - we are good to go...</span><br /><br /><span style="color: rgb(51, 102, 255);"><stream:stream</span><br /><span style="color: rgb(51, 102, 255);"> to='gmail.com'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns='jabber:client'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns:stream='http://etherx.jabber.org/streams'</span><br /><span style="color: rgb(51, 102, 255);"> version='1.0'></span><br /><span style="color: rgb(255, 102, 102);"><?xml version="1.0" encoding="UTF-8"?></span><br /><span style="color: rgb(255, 102, 102);"><stream:stream from="gmail.com" id="X1A565C1E8E3FD7CA" version="1.0" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client"></span><br /><span style="color: rgb(255, 102, 102);"> <stream:features></span><br /><span style="color: rgb(255, 102, 102);"> <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></span><br /><span style="color: rgb(255, 102, 102);"> <mechanism>PLAIN</mechanism>\</span><br /><span style="color: rgb(255, 102, 102);"> <mechanism>X-GOOGLE-TOKEN</mechanism></span><br /><span style="color: rgb(255, 102, 102);"> </mechanisms></span><br /><span style="color: rgb(255, 102, 102);"> </stream:features><br /><br /></span><span style="color: rgb(153, 153, 153);">Now we get the PLAIN auth mechanism which is basically base64 encoded \u0000username\u0000password string which I have blacked out here.</span><br /><span style="color: rgb(51, 102, 255);"><auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>XXXXXXXXXXXXXXXXXX</auth></span><br /><span style="color: rgb(255, 102, 102);"><success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/> <span style="color: rgb(153, 153, 153);"><--- authenticated</span></span><br /><br /><span style="color: rgb(51, 102, 255);"><stream:stream</span><br /><span style="color: rgb(51, 102, 255);"> to='gmail.com'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns='jabber:client'</span><br /><span style="color: rgb(51, 102, 255);"> xmlns:stream='http://etherx.jabber.org/streams'</span><br /><span style="color: rgb(51, 102, 255);"> version='1.0'></span><br /><span style="color: rgb(255, 102, 102);"><?xml version="1.0" encoding="UTF-8"?></span><br /><span style="color: rgb(255, 102, 102);"><stream:stream from="gmail.com" id="X77D6827CD0B365BA" version="1.0" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client"></span><br /><span style="color: rgb(255, 102, 102);"> <stream:features></span><br /><span style="color: rgb(255, 102, 102);"> <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></span><br /><span style="color: rgb(255, 102, 102);"> </stream:features></span><br /><br /><span style="color: rgb(51, 102, 255);"><iq type='set' id='bind_1'></span><br /><span style="color: rgb(51, 102, 255);"> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></span><br /><span style="color: rgb(51, 102, 255);"></iq></span><br /><span style="color: rgb(255, 102, 102);"><iq id="bind_1" type="result"></span><br /><span style="color: rgb(255, 102, 102);"> <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></span><br /><span style="color: rgb(255, 102, 102);"> <jid>XXXXXXXX@gmail.com/D922F673</jid></span><br /><span style="color: rgb(255, 102, 102);"> </bind></span><br /><span style="color: rgb(255, 102, 102);"></iq></span><br /><br /><br /><span style="color: rgb(51, 102, 255);"><iq to='gmail.com' type='set' id='sess_1'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq></span><br /><span style="color: rgb(255, 102, 102);"><iq from="gmail.com" type="result" id="sess_1"/></span><br /><br /><span style="color: rgb(153, 153, 153);">Authenticated, Resource bound and Session created. Now, I need to send a message!<br /><br /></span><span style="color: rgb(51, 102, 255);"></stream:stream></span><br /></pre></span><br /><br /><br />Next article on this, I hope to have successfully sent a message.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com10tag:blogger.com,1999:blog-6990886.post-1154071941597530172006-07-28T12:34:00.000+05:302006-07-28T13:05:31.576+05:30Usability in MS Outlook TasksI really love the way the MS Outlook's Task List Due Date field works. You can input dates in a variety of fashions and I am not talking about the MMDDYYYY, DDMMYY formats. Here are a few examples -<br /><br />So if today is 28 July 2006 (Friday)<br />You can type<br /><ol><li>W - (next week) - 4 Aug 2006 (Friday)</li><li>2W - (n weeks from now) - 11 Aug 2006 (Friday)<br /></li><li>Y, nY - (n years from now) - 28 July 2007 (Saturday)</li><li><span style="font-weight: bold;">3D - (n Days from today) -31 July 2007 (Monday)</span><br /></li><li>Aug - (next August, and other months work) - 28 Aug 2006 (Monday)</li><li><span style="font-weight: bold;">Monday - (next Monday) - 31 July 2006 (Monday) </span>(works for all the days of the week)</li><li>Today - 28 July 2006 (Friday)</li><li>29 - 29 July 2006 (Saturday)</li><li>2007 - 28 July 2007 (Saturday)</li><li>Aug 3 - 3 Aug 2006 (Thursday)</li><li>2 Wed - (n Wednesdays from the next one :-) ) - 16 Aug 2006 (Wednesday)</li></ol>Some behave unexpectedly e.g. 3 Aug gives me a 3 Aug 2007 while 16 Aug gives me 16 Aug 2006. Not sure why.<br /><br />M also behaves unexpectedly always returning today's date.<br /><br />W1D, 2D3W work as well :-) I am sure there are many more that I missed.<br /><br />I readily agree that some examples are extreme but what I found quite interesting was that someone put so much effort in making this component so you can type dates in an extraordinary number of ways and most times I find it does what you expect it to.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-1150092656911328082006-06-12T11:32:00.000+05:302006-06-17T06:55:15.323+05:30Finally some new things to doAfter a long time dealing with software development pressures at work which consumed my energy to do little else, this weekend I dappled in new technologies (new for me). Feels so good - I have a high from it this Monday morning!<br /><br />Got introduced to <a href="http://code.google.com/webtoolkit/">Google Web Toolkit (GWT)</a> which looks very promising. The UI I am ending up with is very clunky and I'll have to work hard on writing (stealing?) some good style-sheets to make the UI look nice. This lead to getting re-introduced to <a href="http://www.csszengarden.com/">Cascading Style Sheets (CSS)</a> and a whole bunch of related <a href="http://www.mezzoblue.com/zengarden/resources/">resources</a>. The whole research can be done rather nicely on <a href="http://www.google.com/notebook/">Google Notebook</a>.<br /><br /> More on GWT as I get more familiar with it.Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com0tag:blogger.com,1999:blog-6990886.post-1125121339146555922005-08-27T11:05:00.000+05:302005-08-27T11:34:09.933+05:30A Strange Situation With Buffered Socket StreamA common technique to buffer socket output stream is to wrap it in a BufferedOutputStream<br /><br /><span style="font-family:courier new;"><span style="font-size:85%;">OutputStream os = new BufferedOutputStream(socket.getOutputStream(), BUF_SIZE);</span><br /><span style="font-family:arial;"><br />where BUF_SIZE is the size of the buffer to be used. This works great except in one strange situation where it seems to fail.<br /><br />Before I get any further, I would like to stress that this piece of information would only be useful to people for who network performance is critical. In applications where it is not, it is best to leave things as they are. Also, this is not related to NIO and might not be an issue in that case. If any one is aware of this please post it in the comments.<br /><br />Consider an application that writes a small amount of data (say the content length of the data to follow, just a few bytes), followed by larger chunks. (HTTP Chunked encoding is a good example). BufferedOutputStream's write(byte b[], int off, int len) has the following implementation of buffering -<br /><br /><pre><br /><span style="font-size:85%;"><span style="font-family:courier new;"> 0 if (len >= buf.length) {</span><br /><span style="font-family:courier new;"> 1 /* If the request length exceeds the size of the output buffer,</span><br /><span style="font-family:courier new;"> 2 flush the output buffer and then write the data directly.</span><br /><span style="font-family:courier new;"> 3 In this way buffered streams will cascade harmlessly. */</span><br /><span style="font-family:courier new;"> 4 flushBuffer();</span><br /><span style="font-family:courier new;"> 5 out.write(b, off, len);</span><br /><span style="font-family:courier new;"> 6 return;</span><br /><span style="font-family:courier new;"> 7 }</span><br /><span style="font-family:courier new;"> 8 if (len > buf.length - count) {</span><br /><span style="font-family:courier new;"> 9 flushBuffer();</span><br /><span style="font-family:courier new;">10 }</span><br /><span style="font-family:courier new;">11 System.arraycopy(b, off, buf, count, len);</span><br /><span style="font-family:courier new;">12 count += len;<br /></span></span></pre><br /><br /><span style="font-size:100%;"><span style="font-family:arial;">The if conditions in lines 0 and 8 are for cases where the data being written does not fit into the buffer.<br /><br />Now, consider our case -<br />a) Application writes 4 bytes - buffer has 4 bytes.<br />b) Application writes a larger chunk that exceeds buffer capacity. To prevent needless data copies, BufferedOutputStream flushes its buffer (writing only 4 bytes to the socket stream) and then either copies or writes the chunk based on the conditions in lines 0 and 8.<br /><br />If this repeats then you see, on the socket stream, writes of size - 4, CHUNK_SIZE, 4, CHUNK_SIZE. (The assumption is that CHUNK_SIZE is atleast BUF_SIZE - 4 for this behaviour) - net effect - the advantage of buffering is lost.<br /><br />If the application cannot control CHUNK_SIZE, one solution is to override the write in BufferedOutputStream and ensure that a full BUF_SIZE worth of data is written and the remaining (CHUNK_SIZE - BUF_SIZE) is filled in to the buffer.<br /><br /></span></span></span></span>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com2tag:blogger.com,1999:blog-6990886.post-1115024618856255282005-05-02T14:11:00.000+05:302005-05-02T15:00:01.386+05:30Reflections On DebuggingThis rather pedagogically worded article is a collection of my thoughts on debugging Java software, the programming patterns I have used, some useful API and techniques.<br /><br />What it is not - it is definitely not complete in terms of information on debugging, its techniques, styles, etc. It is primarily a list of things that have worked for me time and again and a few tools that I keep in my toolkit to use when the situation demands it. I think they will be of use to you as well.<br /><br />I have been fortunate to work in environments where I touched upon various facets of Java, used various APIs and generally did extremely satisfying work. In all these years, debugging has stood out as an activity that everybody has to perform almost as much as they code or design. I have noticed time and again that being able to debug well is an extremeley useful skill. It can be learnt over time and honed and it is to a large extent the ability to match problem patterns to past issues. People like <a href="http://www.me.umn.edu/%7Eshivane/blogs/cafefeed/">Rajiv </a>can uncannily pinpoint a problem's cause when they hear its description. This ability comes from years of experience and the intent to learn from every new debugging experience.<br /><br /><span style="font-weight: bold;">Debugging</span><br /><br />Debugging is the act of locating and fixing a flaw in software. A flaw can manifest itself in multiple ways. Sometimes it is apparent such as cases when the program crashes or does not do the intended action or does not return the intended result. Sometimes it is hard to say what's wrong when a program does not return or the CPU keeps processing something or when the program does something unexpected in addition to the right action. Debugging, of course, is the action we take post having seen a flaw.<br /><br /><span style="font-weight: bold;">Isolating the problem to code : Identifying where to look for a problem</span><br /><br />The problem or flaw appears as a failure of the software to do something it should have. When you encounter a flaw, to debug it, you need to form a mental model of the code to identify where is the code that failed. Debugging largely follows the process of elimination and this process is helped by any symptoms that you can find.<br /><br />When you have the piece of code that failed you try and find the cause by asking and answering questions - what is occuring? What possible causes could result in this problem? E.g. If something should've happened and it didn't perhaps the code was not reached. Why would the code not be reached? Maybe the <span style="font-family:courier new;">if </span>condition under which the method gets called did not evaluate to true or perhaps the<span style="font-family:courier new;"> if (something != null) </span>check was called when <span style="font-family:courier new;">something</span> had the value <span style="font-family:courier new;">null</span>.<br /><br />Another example - If there is an exception then there is additional information about the location of failure and the steps that led to it. The type of Exception will tell you the nature of failure. So if you see a <span style="font-family:courier new;">ConcurrentModificationException</span> thrown by an <span style="font-family:courier new;">Iterator</span>'s <span style="font-family:courier new;">next()</span> method you will have to -<br />a) Find out under what conditions this happens.<br />b) How could these conditions have been created in your program?<br />c) Maybe you removed something using <span style="font-family:courier new;">list.remove()</span> in your loop, or perhaps you passed reference to the list to some other thread which is modifying it.<br />Once you have a mental picture of the surroundings of the problem and why it might be occuring, it’s a matter of eliminating the reasons one by one starting from the most likely cause.<br /><br />Even if you intend to use a debugger, this is a necessary step. You have to always backtrack mentally from the point of failure to locate all possiible causes of failure. A lot of debugging skill relies on this one ability alone.<br /><br /><span style="font-weight: bold;">Reading an Exception</span><br /><br />Java Exceptions have a lot of information in them and should be a very well understood to debug problems. Often, I have noticed programmers use the following template for exceptions.<br /><span style="font-family:courier new;">try {</span><br /><span style="font-family:courier new;"> // do stuff here</span><br /><span style="font-family:courier new;">} catch(Exception ex) {</span><br /><span style="font-family:courier new;"> System.out.println(ex);</span><br /><span style="font-family:courier new;">}</span><br />If you wish to print the exception to know when a problem has occurred then you must consider using <span style="font-family:courier new;">ex.printStackTrace()</span>. There are multiple advantages -<br />A) When using System.out.println(ex), several times there is no message printed other than the class name of the exception that occurred. Imagine having this piece of code in multiple locations, how will you ever know which catch handler printed <span style="font-family:courier new;">java.lang.NullPointerException</span>.<br />B) An exception when printed stands out in a log file or the console. It is several lines long and just the pattern of an exception stack trace print is so different from other message, it is much easier to find than an exception message that looks like other logging statements.<br />C) Following JDK1.4, chained exceptions get printed as well and you don't have to manage them manually. Root cause gets carried along with the exception.<br />D) Lastly and most importantly, the stack trace contains a wealth of information that can be used to create a mental picture of what happened.<br /><br />There have been lots of times when I have looked at a stack trace and said - it should not have come here and been able to trace the problem to a wrong check in an earlier part of the code. You must know how to read an exception. Here's a Java exception printed out.<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">: Output generated by System.out.println() :</span><br /><span style="font-family:courier new;">java.lang.ArrayIndexOutOfBoundsException: 0</span><br /><br /><br /><span style="font-family:courier new;">: Output generated by ex.printStackTrace() :</span><br /><span style="font-family:courier new;">java.lang.ArrayIndexOutOfBoundsException: 0</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.processArgs(ThrowException.java:32)</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.main(ThrowException.java:21)</span></span><br /><br /><br />1) <span style="color: rgb(153, 0, 0);font-size:85%;" ><span style="font-family:courier new;">java.lang.ArrayIndexOutOfBoundsException: 0</span></span><br />The first part of printStackTrace is to do a print out the exception similar to the System.out.println so already you have gotten that for free. This part of the exception stack trace is formatted according to the type of exception and the information printed varies from exception to exception. Some exceptions print nothing more than the class of the exception. Some exceptions (specially custom ones) print a lot of context information that led to this exception.<br />2) <span style="color: rgb(153, 0, 0);font-size:85%;" ><span style="font-family:courier new;">at com.sonicsw.tools.test.ThrowException.processArgs(ThrowException.java:32)</span></span><br />The rest of the exception is the stack trace starting with the location that threw the exception at the top and the caller of the method in which the exception was thrown below it and so on until the executing thread's run method or the main method. The information provided on this line consists of -<br />the fully qualified class name - <span style="font-size:85%;"><span style="font-family:courier new;">com.sonicsw.tools.test.ThrowException</span></span><br />the method - <span style=";font-family:courier new;font-size:85%;" >processArgs</span><br />the file - <span style=";font-family:courier new;font-size:85%;" >ThrowException.java</span><br />line number - <span style="font-size:85%;"><span style="font-family:courier new;">32</span></span>.<br />Obviously, these are great nuggets of information. In some cases, when compilation does not include debugging information, you can end up with stack traces that do not have line numbers. That’s usually a bummer but atleast you have the stack of methods to locate where the problem occurred.<br /><br />Other variations for method names are <clinit> for a static initializer - (this is also an example of exception chaining - note the "Caused by:")<br /><span style="font-size:85%;"><span style="font-family:courier new;">java.lang.ExceptionInInitializerError</span><br /><span style="font-family:courier new;">Caused by: java.lang.IllegalArgumentException</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.<clinit></span></span><span style="font-size:85%;"><span style="font-family:courier new;">(ThrowException.java:21)</span></span><br /><br /><init> for constructors and initializers<br /><span style="font-size:85%;"><span style="font-family:courier new;">java.lang.IllegalArgumentException</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.<init></span></span><span style="font-size:85%;"><span style="font-family:courier new;">(ThrowException.java:20)</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.main(ThrowException.java:24)</span></span><br /><br />and the $number convention for anonymous classes -<br /><span style="font-size:85%;"><span style="font-family:courier new;">java.lang.IllegalArgumentException</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException$1.actionPerformed(ThrowException.java:25)</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.</span></span><init><span style="font-size:85%;"><span style="font-family:courier new;">(ThrowException.java:23)</span><br /><span style="font-family:courier new;"> at com.sonicsw.tools.test.ThrowException.main(ThrowException.java:31)</span></span><br /><br />Ofcourse, if the line number is available it makes it a lot easier.<br /><br />Sometimes, to understand why an exception occurred, you have to understand how control got to that point. The easy exceptions are always the ones which have a localized problem and you can easily catch the problem by the exception. But things can get really hard. E.g. The culprit could lie several methods below and might not even be caused in this thread of execution. A previous event might have generated a bad value which was stored in a field and was picked up by this thread of execution in which the exception occurred. To get to the bottom of these, you need to create a mental back map of methods and events that might have occurred. It always helps to see what methods were called to get to the point of failure.<br /><br /><span style="font-weight: bold;">Trapping Exceptions</span><br /><br />Sometimes, something you expected to execute does not occur and there is no information on why it failed. For some reason, control got transferred out of your method. Once you have eliminated any if conditions that are failing it could be an exception getting thrown from somewhere deep inside your code. No exception gets printed though. This usually happens, when you are implementing a piece that fits into a framework. Perhaps, the framework has a logging switch that’s set too low for exceptions to get printed. Or perhaps, the framework is faulty and is not printing exceptions being thrown by overridden methods. Perhaps, the framework is failing because of the unexpected exception being thrown by your method. In such cases, it is best to eliminate this possibility by wrapping the entire method by a try-catch block. For such debugging situations, I prefer to wrap with a <span style="font-family:courier new;">try … catch(Throwable t) </span>block because you want to be sure that no Exception or Error is being thrown. Sometimes, when Errors get thrown (such as a <span style="font-family:courier new;">NoClassDefFoundError</span> because of a faulty classpath) it will slip through all <span style="font-family:courier new;">catch(Exception)</span> blocks.<br /><br />Debugging is often an exercise in eliminating possibilities and locating the faulty piece of code. This is one technique to achieve that.<br /><br /><span style="font-weight: bold;">When to use Thread.dumpStack</span><br /><br />Another neat tool to keep in your toolkit is using <span style="font-family:courier new;">Thread.dumpStack()</span> or equivalently <span style="font-family:courier new;">new Exception().printStackTrace()</span>. What either of these methods do is to do a <span style="font-family:courier new;">printStackTrace()</span> at this line without actually throwing an exception. The usual reason you do this is because you want to know what caused control of execution to come to this point. Problems caused by a method being called unexpectedly can be identified by this.<br /><br /><span style="font-weight: bold;">Using VM Thread dumps and understanding them</span><br /><br />My biggest complaint with a lot of experienced Java developers is that they have never heard of the most amazing debugging tool called the VM Thread dump. You can use this technique in innovative ways -<br />A) To detect deadlocks<br />B) To diagnose UI hanging problems<br />C) To diagnose slow UI issues<br />D) To diagnose spinning/infinite loops<br />E) For quick and dirty profiling<br />F) To get an understanding of what the VM is doing at that instant<br /><br />I cannot do better than this excellent article on this topic available <a href="http://www.me.umn.edu/%7Eshivane/blogs/cafefeed/2004/06/of-thread-dumps-and-stack-traces.html">here</a>.<br /><br /><span style="font-weight: bold;">Classpath problems</span><br /><br />Another class of problems are classpath issues. There are times when you are not sure if there is another version of a class in the classpath that is getting picked up before yours. Usually a result of a bad environment setup. To eliminate this possibility a simple check is to add a print statement to see if your new code gets picked up. If it isn't getting picked up you need to locate the other class that is getting picked up. One neat API in Java that allows you to locate where a class is being picked up is<br /><br /><span style="font-family:courier new;">Class.getProtectionDomain().getCodeSource().getLocation()</span><br /><br />In most cases, depending on the class loader being used you will get the location of the class which is being executed and you can correct your environment setup.<br /><br /><span style="font-weight: bold;">When to use a debugger and when to print</span><br /><br />There are times when you should use a debugger and there are times when a print statement is more useful. When you can use what is very well described by the brilliant pieces of work mentioned in the references section. The point I want to make here is that you must know what can be achieved using a debugger. It is an extremely powerful tool and can reduce debugging time quite a bit. It is applicable in many cases but is not suitable for a certain set of problems such as threading issues or issues that show up in long running tasks in which case a log with good print statements is essential.<br /><br /><span style="font-weight: bold;">Good debug printing</span><br /><br />Once you have a mental check-list of what the causes might be, you need to eliminate them. Debug prints can tell you quickly if your assumption is right or wrong. Ensure that your debug prints are not causing any side effects inadvertantly. E.g.<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">System.out.println("value.getCode() = " + value.getCode());</span><br /><span style="font-family:courier new;">if (value == null)</span><br /><span style="font-family:courier new;"> return;</span><br /><span style="font-family:courier new;">switch(value.getCode()) {</span><br /><span style="font-family:courier new;">…</span><br /><span style="font-family:courier new;">}</span><br /><br /></span>It is important to print sufficient information about the object you are interested in. Perhaps your code is falling through a switch statement without firing any of the case clauses. You will need to print the value of the switch condition. Think a little before you decide to type in any debug print statements. Often when using good debug print statements, the code gets peppered at useful locations with debug statements which can be switched off with a boolean for future use. An easy to use pattern is<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">private static boolean DEBUG = Boolean.getBoolean("</span></span><classname><span style="font-size:85%;"><span style="font-family:courier new;">.debug").booleanValue();</span></span><br /><br />So e.g. if the class is com.test.ArgumentsProcessor then you would write<br /><span style="font-size:85%;"><span style="font-family:courier new;">private static boolean DEBUG = Boolean.getBoolean("com.test.ArgumentsProcessor.debug").booleanValue();</span></span><br /><br />The advantage is that you can switch on debugging for this class without recompiling anything by specifying <span style="font-family:courier new;">-Dcom.test.ArgumentsProcessor.debug=true</span> when starting your VM.<br />E.g. <span style="font-family:courier new;">java -Dcom.test.ArgumentsProcessor.debug=true <main-class> <args></span><br /><br />However, the compiler will not remove your debug statements during code optimization in this case.<br /><br /><span style="font-weight: bold;">Using Logging</span><br /><br />There is not much that I can add on using Logging that is not already covered by a vast amount of material. You can take a look at the References section below for other information on this subject. The point I would like to make here is that when you are writing print statements that go to a log for debugging purposes, maybe as a patch to a customer to diagnose a particularly tricky problem, think about how the log file might look when it is sent to you. What we think the output would be like when we write log print statements changes dramatically in a live system with multiple threads executing the same log messages. Maybe you need to print the Thread id to bunch all logs or an operation together or perhaps some business data structure id needs to printed with each statement to understand what's happening. You may need to print out the execution path leading to the suspected problem location to know what conditions caused control flow to get there. Another thing to keep in mind is that log files can get so verbose and have so many messages that it becomes very difficult to scan them for problems later.<br /><br /><span style="font-weight: bold;">References</span><br /><br /><a href="http://www.amazon.com/exec/obidos/tg/detail/-/020161586X/qid=1115023627/sr=8-1/ref=pd_csp_1/002-9411596-7848812?v=glance&s=books&n=507846">The Art of Programming (Brian Kernighan, Rob Pike)<span style="font-weight: bold;"></span></a> Highly recommended reading<br /><a href="http://samizdat.mines.edu/howto/HowToBeAProgrammer.pdf">How to be a Programmer (Robert L Read)</a> The first chapter is on debugging and is really well written.</init>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com5tag:blogger.com,1999:blog-6990886.post-1114154027563645052005-04-22T12:03:00.000+05:302006-07-29T21:34:03.806+05:30Swing fighting back<div style="text-align: justify;">Being a veteran Swing programmer and a recent Eclipse plugin developer, I seem to have seen either side of the UI toolkit war.<br /><br />I have a few interesting observations I would like to share.<br /><br /><span style="font-weight: bold;">Swing Knowledge</span><br />We have been trying to hire a few developers with past UI experience (Swing experience is more easily available) but I am apalled at how little the people we have talked to know about Swing. Most people seem to hack in a UI and know just about enough to manage to get the UI working. How a renderer works and what you can and cannot do with it is not understood. Neither did these guys understand that you can write your own TableModel implementation and wire it to your data model and it doesn't have to always be backed by ArrayLists or arrays. I agree that these are not the most knowledgeable Swing programmers out there but when they see a DefaultTableModel they just do whatever they need to to populate it and get their JTable working.<br /><br />JFace (MV framework over SWT) on the other hand enforces an interface such as a IContentProvider (this has its own limitations though) which needs to be implemented and keeps the model to itself. This is interesting because people then don't think in terms of populating Vectors but consider returning their business objects. I suspect that this might really help in writing better models to their UI. I haven't been able to verify this because of the complete lack of SWT profiles that we have received.<br /><br /><span style="font-weight: bold;">Swing's fight back</span><br />I have done a lot of Swing programming in the past and this goes past the regular hack-a-UI. I have been involved in several interesting Swing UIs (IDEs, applications, etc). I have had my share of issues with Swing but over time you learn to work around them. SWT definitely looks good and there are enough articles describing the virtues and problems with either. What is really nice is to see how strongly Swing is fighting back. Several Swing developers are openly defending false accusations (primarily performance related) and there is serious effort at fixing other issues that have remained unfixed over years (probably because there was always something more important to do).<br /><ul> <li>NetBeans is being treated by Sun as their flagship Swing product and the competition has really done it (and Swing) a lot of good. </li> <li>Take a look at the <a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/mustang/index.html">new Desktop Java features</a>.</li> <li>Some very important perceived performance fixes such as <a href="http://weblogs.java.net/blog/zixle/archive/2005/04/no_more_gray_re_1.html">this</a>.</li> </ul> Swing Performance has been steadily improving and this is an interesting comment on the EclipseWiki<br /><blockquote> For most of the time that Eclipse was under development, all of the above were very true. It has only been a very recent development (~JDK 1.4) that Swing has gotten fast enough to be acceptable. The look and feel emulations built into Swing are still lacking in terms of platform fidelity (although this is mitigated somewhat by the existence of high-quality 3rd party Swing look and feels).<br /></blockquote>available <a href="http://eclipsewiki.editme.com/WhySWT">here</a>.<br /><br />All in all I think we'll see very strong improvements in Swing over the next few releases. I am really looking forward to it.<br /><br /><span style="font-weight: bold;">Swing Image</span><br />What has still not happened and I am hoping that it will be fixed in the future is that Sun should make sure that any UI they dole out is really good and this also goes for things like Windows Control Panel Java Applet which doesn't look very polished. Sun cannot have any excuses for shipping badly designed UI. Swing's image is affected by such UI and it can potentially undo (to an extent) all the hard work being done.<br /><br /><br />Check this <a href="http://www.swingwiki.org/table_of_contents#best_practices">list of Swing best practises</a> out.<br /><br /><br /></div>Sachinhttp://www.blogger.com/profile/17218289326440085577noreply@blogger.com7