<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D0AEQnc7fCp7ImA9WhRQE0o.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206</id><updated>2011-12-09T01:51:43.904+05:30</updated><category term="technology" /><category term="functional test" /><category term="mod jk" /><category term="intern" /><category term="graphical org chart" /><category term="pageXOffset" /><category term="javascript" /><category term="firefox internet explorer browser firebug DOM CSS HTML inspector" /><category term="pseudocode" /><category term="attach events" /><category term="img" /><category term="tomcat 5.5" /><category term="coding standards" /><category term="annotations" /><category term="graphs" /><category term="ooad" /><category term="exceptions" /><category term="firefox" /><category term="grails" /><category term="page reloads" /><category term="object oriented analysis and design" /><category term="unit test" /><category term="stringbuffer" /><category term="window" /><category term="neo4j" /><category term="browser" /><category term="installing multiple tomcat instances on windows" /><category term="no src" /><category term="org chart" /><category term="services" /><category term="performance" /><category term="coding practices" /><category term="code" /><category term="strings" /><category term="EJB3 JPA Hibernate HSQLDB Hello World" /><category term="soad" /><category term="performance tuning" /><category term="apache" /><category term="ajp" /><category term="zimoz postcard web2.0" /><category term="visualization" /><category term="coverage" /><category term="arbor.js" /><category term="java" /><category term="refactoring" /><category term="page loads twice" /><category term="internet explorer" /><category term="programming" /><category term="jsp" /><category term="onload" /><category term="scrollLeft" /><category term="runtime exceptions" /><category term="multiple tomcat instances" /><category term="pageYOffset" /><category term="scrollTop" /><category term="gae" /><category term="graphical organization chart" /><category term="ie" /><category term="multiple simultaneous user sessions" /><category term="experience commerce" /><category term="scroll position" /><category term="service oriented analysis and design" /><category term="appengine" /><category term="load balancing" /><category term="optimization" /><category term="coding" /><category term="HTML" /><category term="design" /><category term="testing" /><category term="marker interface" /><category term="equals" /><category term="ide" /><title>Thought Bytes</title><subtitle type="html">Technology 1's and 0's</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://thought-bytes.blogspot.com/" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ThoughtBytes" /><feedburner:info uri="thoughtbytes" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUEDQHo_fCp7ImA9Wx9VF08.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-2686516064693567786</id><published>2011-02-03T13:24:00.011+05:30</published><updated>2011-02-03T14:31:11.444+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-03T14:31:11.444+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="graphs" /><category scheme="http://www.blogger.com/atom/ns#" term="visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="org chart" /><category scheme="http://www.blogger.com/atom/ns#" term="neo4j" /><category scheme="http://www.blogger.com/atom/ns#" term="graphical organization chart" /><category scheme="http://www.blogger.com/atom/ns#" term="graphical org chart" /><category scheme="http://www.blogger.com/atom/ns#" term="arbor.js" /><title>Graph visualization with Neo4J and Arbor.js</title><content type="html">&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;As you might have gathered from my previous post, I have been tinkering with &lt;/span&gt;&lt;a style="font-family: georgia;" href="http://neo4j.org/"&gt;Neo4J&lt;/a&gt;&lt;span style="font-family:georgia;"&gt; lately and I am beginning to appreciate the power and elegance of graphs.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I also came across &lt;/span&gt;&lt;a style="font-family: georgia;" href="http://arborjs.org/"&gt;Arbor.js&lt;/a&gt;&lt;span style="font-family:georgia;"&gt; and was bowled over by it. Loved the force directed layouts and the fact that if you are patient, you will watch your nodes traveling far and wide to settle in their final destination. No need to drag, drop or re-organize the graph- what emerges is a visual pattern, obvious to the eye. I can think of tons of usages for such a visualization, but thought I'd start with something simple just to get the feel of it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;I decided to model a simple organization chart or graph. So off I went to create that model in Neo4J, fed data into it, and my graph was ready very quickly.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;On to Arbor.js- I must admit, I was rather stumped, even with the reference doc they publish. I did not know where to start and where to end- of course, my lack of knowledge around jQuery syntax contributed a lot.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;So, I did the next best thing which was to get the &lt;/span&gt;&lt;a style="font-family: georgia;" href="https://github.com/samizdatco/arbor/tree/master/docs/sample-project"&gt;sample project&lt;/a&gt;&lt;span style="font-family:georgia;"&gt; working locally. Tweak main.js to play with the layout and understand what's really happening. Scroll right down to the $(document).ready function to see the 'ParticleSystem' getting initialized. The sample project initializes with three parameters: repulsion, stiffness  and friction. There are more available like frames per second and precision, but I have not tried them yet. Play with those values to see how they affect the graph. I settled on: &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;var sys = arbor.ParticleSystem(500, 600, 0.5)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I also left&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt; gravity=true&lt;/span&gt; since I definitely want the settling graph.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;You can then add edges and nodes to the ParticleSystem object you just initialized.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Adding a node is as simple as sys.addNode(name,data).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;The name you supply functions as an identifier of the node and the data is an object you can use to associate any set of parameters with this node. These are especially useful when you need additional information about the node to render it- for example, set its color.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Adding an edge is just as simple: sys.addEdge(source,target,data). Source and target nodes are identified by their node names, and data again is an object of parameters to associate with the edge.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Now the sample project displays little black boxes for nodes. I was looking for something more like circular nodes with their labels in them- much like the arbor.js home page.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;br /&gt;&lt;br /&gt;Just adding nodes and edges does not do anything- the ParticleSystem needs a renderer to well, render the graph. The arbor.js reference will tell you that you need to create an object with two methods- init and redraw, and set your ParticleSystem renderer to this object.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;If you look at &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:georgia;font-size:100%;"  &gt;main&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:georgia;"&gt;.js, this is exactly what it does (viewport is the canvas object in which to render the graph)-&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre  style="font-family:georgia;"&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="nx"  &gt;sys&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="p"  &gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="nx"  &gt;renderer&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;"  &gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="o"  &gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;"  &gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="nx"  &gt;Renderer&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="p"  &gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:100%;" class="s2"  &gt;"#viewport"&lt;/span&gt;&lt;span class="p"  style="font-size:100%;"&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The init method in this case simply sets up screen dimensions.&lt;br /&gt;The redraw method is the one responsible for painting nodes and edges. You will see those in the&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="nx"&gt;particleSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eachEdge&lt;/span&gt;&lt;span class="p"&gt; and &lt;/span&gt;&lt;span class="nx"&gt;particleSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eac&lt;/span&gt;&lt;span class="p"&gt;hNode loops.&lt;br /&gt;&lt;br /&gt;So then this is the place to tweak the actual representation of nodes and edges.&lt;br /&gt;Borrowing from the source of the arbor.js home page, I changed the code to:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;particleSystem.eachNode(function(node, pt){&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;var w = Math.max(20, 20+gfx.textWidth(node.name) )&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;if (node.data.alpha===0) return&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  if (node.data.shape=='dot'){&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.oval(pt.x-w/2, pt.y-w/2, w, w, {fill:node.dat&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="p"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;a.color, alpha:node.data.alpha})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.text(node.name, pt.x, pt.y+7, {color:"white", align:"center", font:"Arial", size:12})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.text(node.name, pt.x, pt.y+7, {color:"white", align:"center", font:"Arial", size:12})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }else{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.rect(pt.x-w/2, pt.y-8, w, 20, 4, {fill:node.data.color, alpha:node.data.alpha})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.text(node.name, pt.x, pt.y+9, {color:"white", align:"center", font:"Arial", size:12})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.text(node.name, pt.x, pt.y+9, {color:"white", align:"center", font:"Arial", size:12})&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;})&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;You will note that the color of the node is pulled from the data object attached to the node.&lt;br /&gt;The font, size, width etc. can all be parametrized by setting them in the data object when you create the node.&lt;br /&gt;This example uses the graphics library, so be sure to include graphics.js in your html.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For the edges, I changed the color and also parametrized the thickness of the connector line by the width parameter.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;particleSystem.eachEdge(function(edge, pt1, pt2){&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;if (edge.source.data.alpha * edge.target.data.alpha == 0) return&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      gfx.line(pt1, pt2, {stroke:"#151B8D", width:(edge.data.weight/2), alpha:edge.target.data.alpha})&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;       })&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That is sufficient for a basic graph representation. Now to get the data out of Neo4J and into the graph.&lt;br /&gt;The ParticleSystem has a graft method which accepts an object in the form &lt;/span&gt;&lt;code&gt;{nodes:{}, edges:{}}.&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;These nodes and &lt;/span&gt;&lt;/code&gt;edges are added to the particle system.&lt;br /&gt;I navigated through my Neo4J graph and spat out the data in this json like format.&lt;br /&gt;&lt;br /&gt;Then, in the JS, you simply do a&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:85%;"  &gt;var data = $.getJSON("orgChart.json",function(data){&lt;br /&gt;  sys.graft({nodes:data.nodes, edges:data.edges})&lt;br /&gt;})&lt;/span&gt;&lt;br /&gt;and you're done.&lt;br /&gt;Just make sure you enclose each attribute in quotes- for example, color and shape in the code below.&lt;br /&gt;And it also freaks if you supply a .8 instead of a 0.8 for the length attribute in this example.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The final graph rendered in my browser looks like this(click to enlarge)-&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span&gt;&lt;span class="p"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="p"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="p"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="p"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_MAfUGsnuVtw/TUpqZXWzeyI/AAAAAAAAABo/kZ7ExYJDe3I/s1600/orgChart.PNG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 482px; height: 207px;" src="http://1.bp.blogspot.com/_MAfUGsnuVtw/TUpqZXWzeyI/AAAAAAAAABo/kZ7ExYJDe3I/s320/orgChart.PNG" alt="" id="BLOGGER_PHOTO_ID_5569380873195977506" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;This really just scratches the surface of what you can do with arbor.js&lt;br /&gt;Add to it the various types of graphs or models you can extract out of Neo4J, and you could build some great stuff!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;orgChart.json contains the following-&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;{"nodes":{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Aidan":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Sofia":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Liam":{"color":"GoldenRod", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Charlotte":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Noah":{"color":"GoldenRod", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Ava":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Jackson":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Addison":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Ethan":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Olivia":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Kayden":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Amelia":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Mason":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Lily":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Logan":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Isabella":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Jacob":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Emma":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Benjamin":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Abigail":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Caleb":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Scarlet":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Owen":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Audrey":{"color":"GoldenRod", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Gavin":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Grace":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Connor":{"color":"green", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Claire":{"color":"GoldenRod", "shape":"dot", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Riley":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Emily":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Nolan":{"color":"lightblue", "shape":"rectangle", "alpha":1},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Quinn":{"color":"red", "shape":"dot", "alpha":1}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"edges":{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Quinn":{"Liam":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Audrey":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Noah":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Claire":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Liam":{"Sofia":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Ethan":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Amelia":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Audrey":{"Aidan":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;               "Ava":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Jackson":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Claire":{"Charlotte":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Olivia":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Noah":{"Addison":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Kayden":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Olivia":{"Mason":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Lily":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Ethan":{"Logan":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Isabella":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Addison":{"Jacob":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Emma":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Benjamin":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   "Emma":{"Abigail":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Caleb":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    "Logan":{"Scarlet":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Owen":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Gavin":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    "Lily":{"Connor":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Grace":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Nolan":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    "Connor":{"Riley":{"length":2.5,"weight":2},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           "Emily":{"length":2.5,"weight":2}},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:85%;"  &gt;&lt;span class="p"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;font-size:85%;"  &gt;   &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-2686516064693567786?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3XFoL0IaHjTP9ELVvo_B3SLXnEo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3XFoL0IaHjTP9ELVvo_B3SLXnEo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3XFoL0IaHjTP9ELVvo_B3SLXnEo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3XFoL0IaHjTP9ELVvo_B3SLXnEo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/5kP8Oh7Uulk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/2686516064693567786/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=2686516064693567786" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2686516064693567786?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2686516064693567786?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/5kP8Oh7Uulk/graph-visualization-with-neo4j-and.html" title="Graph visualization with Neo4J and Arbor.js" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_MAfUGsnuVtw/TUpqZXWzeyI/AAAAAAAAABo/kZ7ExYJDe3I/s72-c/orgChart.PNG" height="72" width="72" /><thr:total>20</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2011/02/graph-visualization-with-neo4j-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08GSH08eCp7ImA9Wx9REk4.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-4259985205666759511</id><published>2010-12-13T16:52:00.006+05:30</published><updated>2010-12-13T17:00:29.370+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-13T17:00:29.370+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="neo4j" /><category scheme="http://www.blogger.com/atom/ns#" term="runtime exceptions" /><category scheme="http://www.blogger.com/atom/ns#" term="exceptions" /><title>RuntimeExceptions and Neo4J</title><content type="html">I'm currently working with Neo4J(&lt;a style="color: rgb(51, 51, 255);" href="http://www.neo4j.org/"&gt;http://www.neo4j.org&lt;/a&gt;) - in the evaluation stage really, trying out various use cases. TestNG is my test framework of choice, so most of my work is driven by it.&lt;br /&gt;What really irritated me is the fact that some tests failed. When I looked at the TestNG report, I found that in some cases my test data was bad, so in effect, I was creating a self relationship (which Neo4J frowns upon). There were also cases where, during trial and error, I did not clean the db so I ended up doing a node.getSingleRelationship and instead of one relationship, there were more.&lt;br /&gt;&lt;br /&gt;So why was I irritated? My test cases did fail due to an exception. However, they were Runtime exceptions. When I wrote the code, I did not think they may be thrown- I did not look at the JavaDoc in detail- just used IntelliJ to show me what I could possibly do with Node, and winged it from there. So, when my test failed, I was a bit disbelieving. First checked the exception- and it was a Runtime exception (duh). Then pulled up the JavaDoc and saw that Neo4J does indeed indicate an exception can be thrown in these cases.&lt;br /&gt;This caused me to tweet about Neo4J and their runtime exception philosophy. (Pleasantly surprised to see&lt;span style="color: rgb(51, 102, 255);"&gt; &lt;/span&gt;&lt;a style="color: rgb(51, 51, 255);" href="http://twitter.com/emileifrem"&gt;@emileifrem&lt;/a&gt; respond to it)&lt;br /&gt;&lt;br /&gt;Anyway, somewhere in one of many open windows, I happened to search for any such issues related to Neo4J. I came across Stephen Colebourne's blog instead (&lt;a style="color: rgb(51, 51, 255);" href="http://www.jroller.com/scolebourne/entry/checked_exceptions_bijava"&gt;http://www.jroller.com/scolebourne/entry/checked_exceptions_bijava&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;So really, did it matter whether Neo4J threw RuntimeExceptions or not? Apart from the test results, which were surprising because I neglected to read the JavaDoc in detail, I went through some exceptions that Neo4J throws (leaving out the very obvious Runtime exceptions).&lt;br /&gt;Now if a DeadlockDetectedException, HaCommunicationException, NotFoundException(thrown if a request is made to a node, relationship or property that does not exist), NotInTransactionException, ReadOnlyIndexException or TransactionFailureException were thrown, what would I really do about it? Nothing much, unfortunately. There is no way I could be smart and recover from these. At the most I'd log it and re-throw it.&lt;br /&gt;&lt;br /&gt;Now on to the ones I was disturbed with- methods mostly on the Node.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;getSingleRelationship()&lt;/span&gt; which (as the name indicated) returns the only relationship of a given type and direction. Well, the fact that I'm using this method does mean that I really expect there to be just one relationship, so when a runtime exception is thrown, there is no way to recover from it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;delete() &lt;/span&gt;throws a RuntimeException if it has relationships attached to it. Can I do anything about it? Maybe- depending on functionality, I might attempt to do a cascade delete and re-try the operation. Not sure how many use cases would really want a cascade delete though.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;createRelationshipTo() &lt;/span&gt;throws a RuntimeException if you try to create a self relationship. Note here, that the JavaDoc does not specify this in the Throws, but rather in the description. This arguably could be dealt with by creating an intermediate node- but at the same time, this situation can easily be avoided by defensively coding for it.&lt;br /&gt;&lt;br /&gt;So did it really matter that Neo4J threw Runtime exceptions? After a lot of thought, not really. Why some exceptions are true classes of RuntimeException and why some (the Node exceptions) are just RuntimeExceptions in themselves, I am not sure. The source does not indicate that they do anything over and above being a RuntimeException.&lt;br /&gt;Does it really matter that there is a split convention? I'd think if I needed to recover from a delete exception, then it does matter.&lt;br /&gt;It will be interesting to see as I develop more with Neo4J, how much these Runtime exceptions come into play and whether they are really as disturbing as I initially thought.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Disclaimer: &lt;/span&gt;I still do not believe that we should do away with checked exceptions altogether :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-4259985205666759511?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/92Kdw-Q32hdWh-pR8pb79s3YZ88/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/92Kdw-Q32hdWh-pR8pb79s3YZ88/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/92Kdw-Q32hdWh-pR8pb79s3YZ88/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/92Kdw-Q32hdWh-pR8pb79s3YZ88/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/-ANMOK9OwJg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/4259985205666759511/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=4259985205666759511" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4259985205666759511?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4259985205666759511?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/-ANMOK9OwJg/runtimeexceptions-and-neo4j.html" title="RuntimeExceptions and Neo4J" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2010/12/runtimeexceptions-and-neo4j.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QBQn85eyp7ImA9WxFSE0U.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-1403854574057269240</id><published>2010-04-16T08:47:00.003+05:30</published><updated>2010-04-16T09:12:33.123+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-16T09:12:33.123+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="coding practices" /><category scheme="http://www.blogger.com/atom/ns#" term="coverage" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><title>If you aint going to use it, don't write it</title><content type="html">It's interesting to see how engineers "follow processes" that they don't agree with. They might not agree with it because maybe they haven't understood the value it provides to them (after all, they are typically not dumb guys), or they are not provided with adequate time to follow them, or they are just plain stupid (the processes- not the engineers).&lt;br /&gt;&lt;br /&gt;I've written about testing before. Once I realized its value, I don't go anywhere without my tests (so to speak). Now you can preach about it all you want but unless engineers try it, do it properly, and realize the value they lend to our complicated lives, they're not going to write them. Now take those engineers and tell them that they &lt;span style="font-style: italic;"&gt;must &lt;/span&gt;write tests. First, everyone ignores the new law. Then they're reminded and now it's an exit criteria with one more requirement- coverage numbers.&lt;br /&gt;So, what happens? They produce tests. They run them and get them to pass and management is happy. But what are the value of those tests? Are they maintained? Are they used to help verify that they didn't break anything when the next feature comes along? There are even interesting cases where tests haven't been run as part of builds for months on end and nobody noticed. Which says to me "delete those tests". If nobody cares about those poor things, it is more merciful to end their lives.&lt;br /&gt;&lt;br /&gt;If you're not going to get value out of code you've written, then it is better not to have written it in the first place. I'm sure you can think of better ways to use your time (even if it's taking a nap).&lt;br /&gt;&lt;br /&gt;-Luanne&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-1403854574057269240?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-wODMt5wcUyswGEoTrtMJ6wUirs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-wODMt5wcUyswGEoTrtMJ6wUirs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-wODMt5wcUyswGEoTrtMJ6wUirs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-wODMt5wcUyswGEoTrtMJ6wUirs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/In-uibhT4uU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/1403854574057269240/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=1403854574057269240" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1403854574057269240?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1403854574057269240?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/In-uibhT4uU/if-you-aint-going-to-use-it-dont-write.html" title="If you aint going to use it, don't write it" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2010/04/if-you-aint-going-to-use-it-dont-write.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4ASHc6fyp7ImA9WxFTEUk.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-5265388059385037648</id><published>2010-04-01T22:42:00.003+05:30</published><updated>2010-04-01T23:32:29.917+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-01T23:32:29.917+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="marker interface" /><category scheme="http://www.blogger.com/atom/ns#" term="annotations" /><title>Marker Interfaces- what are they marking?</title><content type="html">This might be a controversial statement, but I dislike marker interfaces. Yes, I get that the Serializable marker interface, for example, has a purpose. Let me amend that statement to 'I dislike marker interfaces with no clear intent'.&lt;br /&gt;&lt;br /&gt;An interface specifies a contract. &lt;span style="font-style: italic;"&gt;If you implement me, then you must provide these services. &lt;/span&gt;&lt;br /&gt;An empty interface cannot specify a contract because, well, it doesn't have one to offer. It is more of a tagging mechanism. It says, if you implement me, then you're tagged in this manner. But, in most of the cases I've seen, nothing is done with this information. OK, so the class is tagged- but what the heck does that mean? Does it mean the class behaves in a certain manner? Does it mean the class can offer these services? Who knows? More often than not, marker interfaces are used as a handy mechanism to refer to classes that implement it, in a uniform manner, without the hassle of inheritance. That's about it. Which is why you'll find code riddled with if-then-elses that do an instanceOf. Kind of defeats the purpose.&lt;br /&gt;&lt;br /&gt;What is worse about  these badly designed marker interfaces, is that it's one large, no-invite-needed party; anyone and their pet elephant can tag along. Not that having the elephant would break up the party. But it isn't appropriate for the elephant to be there- the party wasn't really meant for him and passers-by would have a hard time figuring out what exactly was going on.&lt;br /&gt;&lt;br /&gt;Let's take this very example. Your event planning application has people that are invited to parties. Just as you finish designing your Person class, along comes someone and says, we also invite entertainers to the party. The entire group is to be a single guest. Of course, they're paid and they're not expected to eat the snacks, but they're on the invite list. All your nice API's that returned collections of Person to represent the entire guest list is now left wondering what to do.&lt;br /&gt;&lt;br /&gt;So what is usually done? Simple, lets introduce this marker interface:&lt;br /&gt;public interface Invitee {} and have Person and EntertainmentGroup implement it. Then all we do is change our API to return Invitees and we're done.&lt;br /&gt;What does it mean to be an invitee? &lt;span style="font-style: italic;"&gt;Nothing&lt;/span&gt;.&lt;br /&gt;Now you need to find out how many snacks to order assuming that each person will eat 5. The code I see more often than not is, get a collection of Invitees from the guest list, iterate through them, check if the Invitee is an instanceOf Person- and increment the snack counter by 5.&lt;br /&gt;What did it mean to be an invitee? &lt;span style="font-style: italic;"&gt;Nothing&lt;/span&gt;.&lt;br /&gt;Tomorrow when the zoo keeper is invited to the party and insists on bringing his pet elephant, what do you do? Simple. Have Elephant implement Invitee. Then when you calculate the amount of snacks to order, you add yet another check to see if the Invitee is an instanceOf Elephant and you add 50 kilos of bananas to the list.&lt;br /&gt;Ideally the Invitee class would specify what it means to be an invitee. It's behavior is predictable. When the event manager gets rich and decides that only movie stars can attend his parties, then you can no longer have Invitee extend MovieStar, unless you only know elephants that are movie stars.&lt;br /&gt;&lt;br /&gt;Unless you are doing something very concrete with the marker interface, unless you are processing that tag information in some manner, I consider it a Bad Thing.&lt;br /&gt;Tagging can be accomplished using annotations. You can selectively tag classes/methods and actually process them to do or mean something useful.&lt;br /&gt;&lt;br /&gt;What do you think? Do you see marker interfaces being used as convenience mechanisms?&lt;br /&gt;&lt;br /&gt;-Luanne&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-5265388059385037648?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/afJ6lunA1LnsTm5yzphYnsTpaUY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/afJ6lunA1LnsTm5yzphYnsTpaUY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/afJ6lunA1LnsTm5yzphYnsTpaUY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/afJ6lunA1LnsTm5yzphYnsTpaUY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/PkHOHY2cQuQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/5265388059385037648/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=5265388059385037648" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/5265388059385037648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/5265388059385037648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/PkHOHY2cQuQ/marker-interfaces-what-are-they-marking.html" title="Marker Interfaces- what are they marking?" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2010/04/marker-interfaces-what-are-they-marking.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcFSHc6eCp7ImA9WxBWGE8.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-1025620352378595557</id><published>2010-02-10T23:45:00.003+05:30</published><updated>2010-02-10T23:50:19.910+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-10T23:50:19.910+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><category scheme="http://www.blogger.com/atom/ns#" term="gae" /><category scheme="http://www.blogger.com/atom/ns#" term="appengine" /><title>DeadlineExceededException on GAE with Grails</title><content type="html">Grails on the Google App engine takes substantial time to startup and will probably exceed the hard deadline limit set by GAE. If you see a lot of "DeadlineExceededException" errors in your logs, you should be aware of this. There is a jira for this - &lt;a href="http://jira.codehaus.org/browse/GRAILSPLUGINS-1736"&gt;http://jira.codehaus.org/browse/GRAILSPLUGINS-1736&lt;/a&gt; . Vote this up if it matters to you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-1025620352378595557?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/l6g7SmKBw9zSRveC7DMm_Y9ukT0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l6g7SmKBw9zSRveC7DMm_Y9ukT0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/l6g7SmKBw9zSRveC7DMm_Y9ukT0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l6g7SmKBw9zSRveC7DMm_Y9ukT0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/7M_y4On-aOw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/1025620352378595557/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=1025620352378595557" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1025620352378595557?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1025620352378595557?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/7M_y4On-aOw/deadlineexceededexception-on-gae-with.html" title="DeadlineExceededException on GAE with Grails" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2010/02/deadlineexceededexception-on-gae-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8HRHY7eCp7ImA9WxBWEk0.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-8028315126278343540</id><published>2010-02-03T17:57:00.007+05:30</published><updated>2010-02-03T18:43:55.800+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-03T18:43:55.800+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><category scheme="http://www.blogger.com/atom/ns#" term="gae" /><category scheme="http://www.blogger.com/atom/ns#" term="appengine" /><title>Notes on Google AppEngine 1.3, Grails 1.2.1, and app engine plugin 0.8.8.</title><content type="html">Currently in the process of upgrading a grails project to grails 1.2.1. Noted down some observations (and will keep updating as i test stuff)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt;&lt;br /&gt;There doesn't seem to be a need to add the following to the Config log4j anymore (this was needed in grails 1.x see http://jira.codehaus.org/browse/GRAILSPLUGINS-1184)&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;'null' name:'stacktrace'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;2.&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;Had some trouble with the sessions and kept getting this error&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;[java] WARNING: Nested in org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: Session support is not enabled in appengine-web.xml.  To enable sessions, put &lt;/span&gt;&lt;sessions-enabled style="font-style: italic;"&gt;true&lt;/sessions-enabled&gt;&lt;span style="font-style: italic;"&gt; in that file.  Without it, getSession() is allowed, but manipulation of sessionattributes is not.:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As advised in the plugin &lt;a href="http://grails.org/plugin/app-engine"&gt;documentation&lt;/a&gt;, added the following to Config, but it still didn't work!&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;google.appengine.sessionEnabled = true&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Had to eventually update the /web-app/WEB-INF/appengine-web.xml file and uncomment the line below&lt;projecthome&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;!-- &amp;lt;sessions-enabled&amp;gt;true&amp;lt;/sessions-enabled&gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/projecthome&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3.&lt;/span&gt;&lt;br /&gt;Can now user &lt;span style="font-style: italic;"&gt;grails run-app&lt;/span&gt; to run the development server instead of &lt;span style="font-style: italic;"&gt;grails app-engine&lt;/span&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;projecthome&gt;&lt;br /&gt;&lt;/projecthome&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-8028315126278343540?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CcsV48ic0fM7I2LGtOJyiP26alo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CcsV48ic0fM7I2LGtOJyiP26alo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CcsV48ic0fM7I2LGtOJyiP26alo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CcsV48ic0fM7I2LGtOJyiP26alo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/SRqPXzyKXqQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/8028315126278343540/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=8028315126278343540" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8028315126278343540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8028315126278343540?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/SRqPXzyKXqQ/notes-on-google-appengine-13-grails-121.html" title="Notes on Google AppEngine 1.3, Grails 1.2.1, and app engine plugin 0.8.8." /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2010/02/notes-on-google-appengine-13-grails-121.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4BRX45fyp7ImA9WB5aEEU.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-693489208147569426</id><published>2007-09-06T14:13:00.000+05:30</published><updated>2007-09-06T17:45:54.027+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-09-06T17:45:54.027+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title>The Refactoring Quandary</title><content type="html">&lt;span style=";font-family:georgia;font-size:100%;"  &gt;&lt;span style="font-family:arial;"&gt;We all know by now that refactoring is important. The problem is- when do you refactor?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;In my opinion, the time to refactor is when the thought first crosses your mind.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Let's say you're implementing a new feature or fixing a bug. You think 'hmm, I seem to be duplicating code' or 'looks like we could reorganize a bit of this'. Instead of pushing the thought 'this could be refactored later' to the back of your head where it will stay there for a very long time and come back to haunt you once your code is so messy that even you don't know how it got that way, the answer is to refactor &lt;/span&gt;&lt;span style="font-style: italic;font-family:arial;" &gt;immediately&lt;/span&gt;&lt;span style="font-family:arial;"&gt;.  Do what you can to improve your code. If you don't, then you and everybody else just pass the buck on and say "X will do that someday", and soon you are in programming hell. Moreover, if you refactor regularly, you most often need to just refactor small areas at a time. It's much better then saying we'll refactor this entire application- more often than not, throwing it out and restarting would be more appealing.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Of course there are reasons why people are frightened of refactoring. Acknowledging the need to refactor does not mean saying to the world "I have bad code". You do not have to have glaring bugs to think of refactoring. Think of it as general housekeeping. Just because the hotel housekeeping staff cleans your room every morning does not mean you left it looking like a pig sty the night before.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Another important reason is the fear of breaking code. Which is why to refactor confidently, you need to be backed by a solid suite of test cases. If you don't, then this is a very real risk you run.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Refactoring is easier said than done. You rarely find that you've been told to spend the next week refactoring. There are always more pressing tangible deliverables. However, it is extremely important to realize that the intangible ones will actually affect your tangible deliverables in the near future. Just as we need to consciously budget time to write  automated tests, refactoring does not happen magically either.  A small bit of effort regularly will go a long way to contributing to better manageable, extensible and flexible code.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;-Luanne&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-693489208147569426?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/EF2zfjoqD0p_KxdM9ZN1J4EqkkI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EF2zfjoqD0p_KxdM9ZN1J4EqkkI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/EF2zfjoqD0p_KxdM9ZN1J4EqkkI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EF2zfjoqD0p_KxdM9ZN1J4EqkkI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/Z-6YA_s_LBA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/693489208147569426/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=693489208147569426" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/693489208147569426?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/693489208147569426?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/Z-6YA_s_LBA/refactoring-quandary.html" title="The Refactoring Quandary" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>7</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/09/refactoring-quandary.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEADRXo5eyp7ImA9WB5UGUg.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-4943175487959523080</id><published>2007-08-24T15:10:00.000+05:30</published><updated>2007-08-24T17:29:34.423+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-24T17:29:34.423+05:30</app:edited><title>At the local Udipi...</title><content type="html">So I'm sitting in this udipi fast food restaurant waiting for my lunch (rawa idli - highly recommended), and I find myself observing the waiters going about their jobs. This is what typically happens:&lt;br /&gt;&lt;br /&gt;1. Customer enters, sits, decides what he wants and tells the waiter.&lt;br /&gt;&lt;br /&gt;2. Customer asks the waiter how long it will takes and the waiter gives an approximate waiting time.&lt;br /&gt;&lt;br /&gt;3. Waiter heads over to the kitchen and bellows the order to the cooks.&lt;br /&gt;&lt;br /&gt;4. If a customer gets impatient, the waiter goes to the kitchen to check and assures the customer 'it's almost done!'.&lt;br /&gt;&lt;br /&gt;5. Once the order is ready, the waiter takes it to the customer's table and serves it to him.&lt;br /&gt;&lt;br /&gt;6. If the customer didn't like the meal, the waiter gets a earful. He smiles and goes back and abuses the cook.&lt;br /&gt;&lt;br /&gt;7. Waiter handles many customers at the same time.&lt;br /&gt;&lt;br /&gt;8. Finally the waiter hands over the bill.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With a start I realise - it's no different from my current job. I'm sort of a Project Lead. This is what I do:&lt;br /&gt;&lt;br /&gt;1. The client sends me the requirements.&lt;br /&gt;&lt;br /&gt;2. Client asks me how long it would take to deliver it. I estimate and return a figure.&lt;br /&gt;&lt;br /&gt;3. I hand the requirements over to my team, who then start working on it.&lt;br /&gt;&lt;br /&gt;4. Client gets impatient and eager to see 'anything', so I tell them 'it's 90% done!'&lt;br /&gt;&lt;br /&gt;5. When it's actually done then it's released to the client&lt;br /&gt;&lt;br /&gt;6. If it's a poor quality release, then I get a earful from the client and I pass it on to my team.&lt;br /&gt;&lt;br /&gt;7. Many such requirements are being handled simultaneously.&lt;br /&gt;&lt;br /&gt;8. End of the month, I total up the time sheets for the billing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;!!!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I ate quickly, tipped the waiter handsomely and left.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Someday, I want to go back into the kitchen and be the cook...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;Aldrin&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-4943175487959523080?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Qr7pqLZUjaHnbWKBzVDGqMECwaE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Qr7pqLZUjaHnbWKBzVDGqMECwaE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Qr7pqLZUjaHnbWKBzVDGqMECwaE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Qr7pqLZUjaHnbWKBzVDGqMECwaE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/9kJaPpmaXKQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/4943175487959523080/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=4943175487959523080" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4943175487959523080?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4943175487959523080?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/9kJaPpmaXKQ/at-local-udipi.html" title="At the local Udipi..." /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/08/at-local-udipi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8CQnY8eCp7ImA9WB5SFUg.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-6939723526593125582</id><published>2007-06-11T09:22:00.000+05:30</published><updated>2007-06-11T15:44:23.870+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-06-11T15:44:23.870+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="functional test" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="unit test" /><title>How much can we test?</title><content type="html">A couple of years back, I was introduced to unit testing. At the time, I found it rather tedious. Though it did expose bugs in our code early in the cycle, maintenance of test cases were becoming a nightmare. So the question is, what should you test, and how much should you test it? I've formed some opinions along the way- tell me what your experience has been...&lt;br /&gt;&lt;br /&gt;First, every automated test is NOT a unit test. A unit test is simply a test that validates the smallest "unit" in your application. It could be a class, and you would be validating each operation of that class by testing its methods, for example. A test which tries to validate a business operation that spans more than one class would probably be a functional test.&lt;br /&gt;A simple example would be a Shopping Cart class. A unit test could verify that deleting items from an empty cart is not possible. A functional test would be one that validates the shopping process- add items to cart, checkout, verify bill amount.&lt;br /&gt;&lt;br /&gt;Which kinds of tests should you write? Only unit? Functional? Both?&lt;br /&gt;&lt;br /&gt;Well, unit tests are no doubt good. You should ideally write them before you write your actual code. &lt;font style="font-style: italic;"&gt;Ideally&lt;/font&gt;. In the real world of the services industry at least, there are very many projects whose scope and functionality change so fast that programmers are always playing catch up with unit tests. It is simply not possible to maintain a vast number of test cases. So writing unit tests become an afterthought. And they are the very first thing axed from the budget :-)&lt;br /&gt;If we were to write comprehensive unit tests that really add value, teams would require time to do so. They would also require time to maintain them. That time is rarely granted.&lt;br /&gt;&lt;br /&gt;So, what is the next option? What about writing functional tests? Agreed, they will not provide 100% coverage, but let us assume that we could test major business flows/processes. The amount of test cases decrease, but the ROI is visible earlier on because major flaws can be uncovered before moving into system testing. There will always be bugs. Subtle bugs that even unit tests will fail to pick up. So is it worth spending time trying to think of many, many ways to break the code when the code will certainly break somewhere in a place you did not expect it to?&lt;br /&gt;I personally would write functional tests, and enhance the suite over time. For example, when a bug is reported, a test could be written for it. It could very well be a unit test. But with bugs and change requests, the suite will grow in sensible proportions.&lt;br /&gt;&lt;br /&gt;What do you think?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-6939723526593125582?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/J1D3oTCT-tcX1lvWRlx7GlgGmV0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J1D3oTCT-tcX1lvWRlx7GlgGmV0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/J1D3oTCT-tcX1lvWRlx7GlgGmV0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J1D3oTCT-tcX1lvWRlx7GlgGmV0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/V0K9B6FKc3I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/6939723526593125582/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=6939723526593125582" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/6939723526593125582?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/6939723526593125582?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/V0K9B6FKc3I/how-much-can-we-test.html" title="How much can we test?" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/06/how-much-can-we-test.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMNRnoyfSp7ImA9WBFaGE8.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-268816201480926416</id><published>2007-05-22T08:30:00.000+05:30</published><updated>2007-05-22T14:31:37.495+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-05-22T14:31:37.495+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="multiple simultaneous user sessions" /><title>Preventing multiple user sessions with the same user account</title><content type="html">Often you want to prevent the same user account being used simultaneously in different sessions (business license restrictions being one reason, complex technical synchronisation problems being another)। There are two typical strategies to prevent थिस :-&lt;br /&gt;#1. Prevent any new sessions while a session with the same user account exists.&lt;br /&gt;#2. Allow a new session, but disconnect any previous sessions if they exists.&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Imho&lt;/span&gt;, I think #1 can be very problematic for the user. If the user faces a system crash during his session, his subsequent attempts to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;login&lt;/span&gt; after recovery will be thwarted. Until his previous session times out, he will be left twiddling his thumbs. Using cookies to maintain the session information would be a good idea here. If you are supporting auto-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;login&lt;/span&gt;, then you are already doing something like this. A session id stored in the cookie, would be enough clue to server to reconnect to the same session. You need to ensure however, that the user does a proper '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;logout&lt;/span&gt;' - even going to the extent of hooking your '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;logout&lt;/span&gt;' into the body unload event if the user chooses to shut the browser window, without clicking on your '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;logout&lt;/span&gt;' link.&lt;br /&gt;Now what happens when a user logs into your site, shuts his browser, deletes his cookies and tries to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;login&lt;/span&gt; again, before his session times out ?? Let him suffer, i say ! :)&lt;br /&gt;&lt;br /&gt;#2 is much easier to implement. All you need to do is maintain a Map of user accounts with their sessions in application scope. Add a listener for session timeouts, to remove these entries from the map when the session times out. When a new session if being created, simply look up the map for previous sessions by the user and invalidate them if present and also remove them from the map.&lt;br /&gt;&lt;br /&gt;I'd like to hear your comments on how you &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_7"&gt;achieved&lt;/span&gt; similar requirements।&lt;br /&gt;&lt;br /&gt;&lt;span class=""&gt;Cheers&lt;br /&gt;&lt;/span&gt;Aldrin&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-268816201480926416?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/o74RBCnvl9-Jgsp9-CKrzQELzQ0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/o74RBCnvl9-Jgsp9-CKrzQELzQ0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/o74RBCnvl9-Jgsp9-CKrzQELzQ0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/o74RBCnvl9-Jgsp9-CKrzQELzQ0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/4Z9Gp6aO9TM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/268816201480926416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=268816201480926416" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/268816201480926416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/268816201480926416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/4Z9Gp6aO9TM/preventing-multiple-user-sessions-with.html" title="Preventing multiple user sessions with the same user account" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/05/preventing-multiple-user-sessions-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEABQnY6cCp7ImA9WBFVF0U.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-7337018043206694617</id><published>2007-04-16T11:07:00.000+05:30</published><updated>2007-04-17T09:35:53.818+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-17T09:35:53.818+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ide" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>You minus IDE=helpless?</title><content type="html">Nowadays, the IDE is your workbench. You can generate your UML, debug, run embedded servers, inspect your code, read the Dilbert strip...all from within a single application.&lt;br /&gt;&lt;br /&gt;With each release boasting nifty features, there is very little reason to leave the comfort of your IDE.&lt;br /&gt;&lt;br /&gt;Or is there?&lt;br /&gt;&lt;br /&gt;In the good old days, we had no such pleasures. I remember writing code in Notepad, and was thrilled when I discovered EditPlus. Debugging meant compiling on the command line, fixing error by error till you had a successful compile, starting tomcat and testing your web app. Today, you can do all this and more at the click of a button.&lt;br /&gt;This is certainly great news for the developer...and a very bad habit as well.&lt;br /&gt;No doubt IDE's save you a lot of trouble and time. IntelliJ IDEA has increased my productivity tremendously and helps me with a whole lot of things- including reading the Dilbert strip ;-)&lt;br /&gt;But, if I had no IntelliJ for a day, then I would still be able to code in EditPlus and look up the JavaDoc from wherever if need be, deploy my application and debug it. And that is the difference.&lt;br /&gt;&lt;br /&gt;Too often I see IDE whizzes who can do almost anything with CTRL, SHIFT or ALT and one or two keys. But take the IDE away...and they are helpless. This is Bad Thing in my opinion. The fallout of not knowing the basics is terrible. And this doesn't just apply to software.&lt;br /&gt;&lt;br /&gt;I have seen cases where for some reason, the embedded web server plugin fails for whatever reason. Everyone is examining their code and can find nothing wrong...and they're re-examining it for hours and hours. I say shut it down and deploy manually...but few know how to :-)&lt;br /&gt;In fact, very few know how to run javac !!! Turns out that the code base is fine...it was the embedded web server....hours and hours of valuable time wasted because we refused to abandon our beloved IDE.&lt;br /&gt;&lt;br /&gt;Consider this scenario- you've developed this fantastic application, deployed it using your IDE, debugged it and it runs like a dream. Then you go to install it at the clients site. And horror of horrors, they don't have your IDE. And won't let you install it. Now what???&lt;br /&gt;You should be able to say so what? You'd roll up your sleeves, check your code out of CVS or wherever, set your build properties, run ANT, deploy, start your webserver and go home in a couple of hours to have a nice drink.&lt;br /&gt;But if you know no such thing...then you'll be pleading with IT to install your IDE and when they refuse you'll have to call someone in your team and have them guide you step by step. And you'll be drowning your sorrows in many drinks after many, many tense hours. Which is a better option??&lt;br /&gt;&lt;br /&gt;I am not condemning IDE's. On the contrary. I have used a couple (and IntelliJ by far is THE best...though beware, after using it, like me, you will hate the likes of Eclipse). They are huge help. But use them after you know how to get up and running without their help. If you are developing a simple webapp, can you code a servlet for example, without the IDE? Can you compile it? Can you deploy it? Do you know how to run Tomcat? Where to find the log files?&lt;br /&gt;If yes, then go ahead...open up your IDE and be happy :-)&lt;br /&gt;&lt;br /&gt;-Luanne&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-7337018043206694617?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jvzSAjfOoQxKZlzmleDXqTqpUK0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jvzSAjfOoQxKZlzmleDXqTqpUK0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jvzSAjfOoQxKZlzmleDXqTqpUK0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jvzSAjfOoQxKZlzmleDXqTqpUK0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/4zjLO8Ke4LA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/7337018043206694617/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=7337018043206694617" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/7337018043206694617?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/7337018043206694617?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/4zjLO8Ke4LA/you-minus-idehelpless.html" title="You minus IDE=helpless?" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>12</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/04/you-minus-idehelpless.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EER345fip7ImA9WBFWFko.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-8041330506905710006</id><published>2007-04-03T17:53:00.000+05:30</published><updated>2007-04-04T14:03:26.026+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-04T14:03:26.026+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EJB3 JPA Hibernate HSQLDB Hello World" /><title>Hello World with standalone Java Persistence, Hibernate and HSQLDB</title><content type="html">Lately just started reading (&amp; learning) EJB3. Because of a slow PC at home, I needed to be able to run code for the Java Persistence API in the standalone mode, without the overhead of a huge database or app server. So, I rustled up this guide to get up and running with Java Persistence. Basically all you need is a database and an implementation of the persistence API. We will use HSQL and Hibernate Entity Manager respectively. Hibernate Entity Manager runs on the Hibernate core, so will need that too.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 1: &lt;/span&gt;You will need Java 5. Get it from &lt;a href="http://java.sun.com"&gt;http://java.sun.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/"&gt;&lt;br /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;Step 2:&lt;/span&gt; Download HQSLDB from &lt;a href="http://hsqldb.org/"&gt;http://hsqldb.org&lt;/a&gt;. Extract into some folder (eg. D:\hsqldb)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 3: &lt;/span&gt;Download the Hibernate Entity Manager from &lt;a href="http://hibernate.org/"&gt;http://hibernate.org&lt;/a&gt;. Extract into some folder. (eg. D:\hibernate-entitymanager-3.2.1.GA)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 4:&lt;/span&gt; Download the Hibernate Core from &lt;a href="http://hibernate.org/"&gt;http://hibernate.org&lt;/a&gt;. Extract into some folder. (eg. D:\hibernate-3.2)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 5:&lt;/span&gt; Set up the database&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Create a new folder for all database related files we will create in this step. Lets call it 'db_stuff'.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;          Create a &lt;span style="font-weight: bold;"&gt;server.properties&lt;/span&gt; file. We will name our database 'think'. Configuration parameters should be as below:&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    server.database.0 file:./think&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    server.dbname.0 think&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;          Start the database in the server mode by running the following from the command line (Better still put this in a batch file)&lt;/li&gt;&lt;/ul&gt;                   &lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;blockquote&gt;java -cp D:\hsqldb\lib\hsqldb.jar org.hsqldb.Server&lt;/blockquote&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;              You can use the HSQLDB DatabaseManager to view this database. Run the following from the command line to invoke the tool.&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;blockquote&gt;    java -cp D:\hsqldb\lib\hsqldb.jar org.hsqldb.util.DatabaseManager&lt;/blockquote&gt;&lt;/span&gt;&lt;blockquote&gt;        In the "Connect" dialog, select the following options:&lt;br /&gt;    Type: &lt;span style="color: rgb(0, 0, 153);"&gt;HSQL Database Engine Server&lt;/span&gt;&lt;br /&gt;    Driver: &lt;span style="color: rgb(0, 0, 153);"&gt;org.hsqldb.jdbcDriver&lt;/span&gt;&lt;br /&gt;    URL: &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;jdbc:hsqldb:hsql://localhost/think&lt;/span&gt;&lt;br /&gt;    User: &lt;span style="color: rgb(0, 0, 153);"&gt;sa&lt;/span&gt;&lt;br /&gt;    Password:&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 6:&lt;/span&gt; Now the standalone. Add the following jars to your project classpath:&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;hsqldb.jar&lt;/span&gt; from D:\hsqldb\lib\hsqldb.jar&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;hibernate3.jar&lt;/span&gt; from D:\hibernate-3.2&lt;/li&gt;&lt;li&gt;all jars from D:\hibernate-3.2\lib\&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;hibernate-entitymanager.jar&lt;/span&gt; from D:\hibernate-entitymanager-3.2.1.GA&lt;/li&gt;&lt;li&gt;all jars from D:\hibernate-entitymanager-3.2.1.GA&lt;/li&gt;&lt;li&gt;Whew!&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Step 7: &lt;/span&gt;Create the persistence configuration&lt;br /&gt;&lt;blockquote&gt;   Create a file named &lt;span style="font-weight: bold;"&gt;persistence.xml&lt;/span&gt;, the persistence configuration file. This file needs to be within a META-INF folder in your classpath. If you are compiling all your classes into a folder, say 'classes', create a META-INF folder under 'classes', then create the persistence.xml file in META-INF. The file should look like below:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&amp;lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence" version="1.0"&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  &amp;lt;persistence-unit name="think" transaction-type="&lt;span style="font-weight: bold;"&gt;RESOURCE_LOCAL&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    &amp;lt;properties&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      &amp;lt;property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;            &amp;lt;property name="hibernate.hbm2ddl.auto" value="update"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;      &amp;lt;property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;     &amp;lt;property name="hibernate.connection.username" value="sa"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;     &amp;lt;property name="hibernate.connection.password" value=""/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;     &amp;lt;property name="hibernate.connection.url" value="&lt;span style="font-weight: bold;"&gt;jdbc:hsqldb:hsql://localhost/think&lt;/span&gt;"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;        &amp;lt;/properties&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    &amp;lt;/persistence-unit&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&amp;lt;/persistence&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;Note that the transaction-type is &lt;span style="font-weight: bold;"&gt;RESOURCE_LOCAL&lt;/span&gt;. This is required for standalone environments. Also note the "hibernate.connection.url" matches the URL you use to connect from the HSQL DB Manager to the database, &lt;span style="font-weight: bold;"&gt;jdbc:hsqldb:hsql://localhost/think&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 8:&lt;/span&gt; Create an entity class, &lt;span style="font-weight: bold;"&gt;BroadcastMessage.java&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;package com.blogspot.thought_bytes;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.Entity;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.Id;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;@Entity&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;public class BroadcastMessage {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  @Id&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  private long id;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  private String message;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  public long getId() {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    return id;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  public void setId(long id) {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    this.id = id;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  public String getMessage() {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    return message;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  public void setMessage(String message) {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    this.message = message;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 9:&lt;/span&gt; Create a harness to interact with the persistence layer, &lt;span style="font-weight: bold;"&gt;ClientHarness.java&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;package client;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import com.blogspot.thought_bytes.BroadcastMessage;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.EntityManager;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.EntityManagerFactory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.Persistence;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;import javax.persistence.EntityTransaction;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;public class ClientHarness {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;public static void main(String[] args) {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;//Use the persistence.xml&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;EntityManagerFactory emf = Persistence.createEntityManagerFactory("think");&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;EntityManager em = emf.createEntityManager();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;EntityTransaction tx = em.getTransaction();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;tx.begin();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;//Create and initialize an entity instance&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;BroadcastMessage mb = new BroadcastMessage();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;mb.setId(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;mb.setMessage("Hello World");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;//Persist using the entity manager&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;em.persist(mb);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;//Save&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;tx.commit();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;em.close();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;emf.close();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Run the above.&lt;br /&gt;&lt;br /&gt;Go back to the database manager and refresh the view. You should be able to see a new tabel "broadcastmessage". If you query this table you should get the following:&lt;br /&gt;&lt;br /&gt;ID   MESSAGE&lt;br /&gt;--   -------&lt;br /&gt;1    Hello World&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;That's it! And now the real hard work begins... :)&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;Aldrin&lt;br /&gt;&lt;br /&gt;&lt;screenshot&gt;&lt;/screenshot&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-8041330506905710006?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZZYhI6avvk0FbErM-geOlvZ7jv4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZZYhI6avvk0FbErM-geOlvZ7jv4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZZYhI6avvk0FbErM-geOlvZ7jv4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZZYhI6avvk0FbErM-geOlvZ7jv4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/M_CZJ8dm_KE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/8041330506905710006/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=8041330506905710006" title="35 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8041330506905710006?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8041330506905710006?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/M_CZJ8dm_KE/hello-world-with-standalone-java.html" title="Hello World with standalone Java Persistence, Hibernate and HSQLDB" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>35</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/04/hello-world-with-standalone-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcNSHw8cSp7ImA9WBFWEkk.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-4691046954909710904</id><published>2007-03-30T13:32:00.000+05:30</published><updated>2007-03-30T14:11:39.279+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-30T14:11:39.279+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pseudocode" /><category scheme="http://www.blogger.com/atom/ns#" term="coding practices" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Write pseudocode!</title><content type="html">&lt;span style="font-family:georgia;"&gt;Writing pseudocode is a good thing.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Just as it is not recommended that you dive into writing code before your analysis and design are done, so should you not dive into code before you have some sort of pseudocode in place. Unless of course you are writing trivial code.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Even if your design is all laid out before you, then there are many cases where pseudocode is a huge advantage.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Simply listing out the steps gives me a lot of clarity about the way forward. I will most likely find that I've discovered areas that were not thought of during design e.g. if X event takes place, or  the application state changes to Y, then how do I handle it?&lt;br /&gt;When I'm coding I am in a different mindset- purely focused on code. Side issues like these are unlikely to pop into my head. And worse, if I haven't worked out the steps, then I will most likely miss something.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Getting stuck on a code issue is very common- at that point, all you can think about is how to solve it/work around it. By the time you've achieved this, your train of thought is lost.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I still use paper and a pencil. Whether you prefer electronic pseudocode or hand written, is up to you but in my opinion, it is an invaluable practice.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I am amazed at the number of people who jump into code and flounder along the way and just refuse to write pseudocode like it's some demeaning activity. What is more amazing is the number of tech leads who prohibit it of their juniors-- saying things like "the client wants to see code".  It is well worth the time investment- the bugs will definitely be less. And the amount of patching needed on that code will decrease.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;So, it's not a "waste of time" or "an activity that only freshers do". Some of the best engineers I know write pseudocode.  It would be worth getting into this habit to help you understand your problem, eliminate ambiguities, reduce bugs and above all, write cleaner code.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-4691046954909710904?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qk_taWeRr1E_L9E6T7LppigXyPU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qk_taWeRr1E_L9E6T7LppigXyPU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qk_taWeRr1E_L9E6T7LppigXyPU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qk_taWeRr1E_L9E6T7LppigXyPU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/9kbhWWK20LE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/4691046954909710904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=4691046954909710904" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4691046954909710904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4691046954909710904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/9kbhWWK20LE/write-pseudocode.html" title="Write pseudocode!" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/03/write-pseudocode.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYFQHo9eip7ImA9WBFVEkU.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-582598632150746999</id><published>2007-03-07T17:18:00.000+05:30</published><updated>2007-04-11T15:55:11.462+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-11T15:55:11.462+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="multiple tomcat instances" /><category scheme="http://www.blogger.com/atom/ns#" term="mod jk" /><category scheme="http://www.blogger.com/atom/ns#" term="tomcat 5.5" /><category scheme="http://www.blogger.com/atom/ns#" term="load balancing" /><category scheme="http://www.blogger.com/atom/ns#" term="ajp" /><category scheme="http://www.blogger.com/atom/ns#" term="apache" /><category scheme="http://www.blogger.com/atom/ns#" term="installing multiple tomcat instances on windows" /><title>How to load balance Tomcat 5.5 with Apache on Windows</title><content type="html">It's rather amazing that I could not find a single how-to that could detail the steps for using the Apache web server to load balance multiple Tomcat 5.5 instances on Windows. I found tons of articles- but they were either for older versions of Tomcat or Apache or for Unix flavors and none were accurate enough. Apache itself has fragmented documentation on the subject, and after much trial and error and pulling of hair, I succeeded.&lt;br /&gt;&lt;br /&gt;The least I can do is list the steps here for all others who have had trouble getting it right.&lt;br /&gt;The goal of this blog is to set up two Tomcat 5.5 instances with Apache in front, load balancing them. Please note that this does not cover clustering. I'll save that for another blog once I actually do it :-)&lt;br /&gt;Also, this is not a tutorial on load balancing. It will get you up and running- then you might want to look at the Tomcat documentation to find out what exactly all those options do.&lt;br /&gt;&lt;br /&gt;So, this is what you need to download:&lt;br /&gt;1. &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;Apache HTTP server 2.2.4&lt;/span&gt;  from  &lt;a href="http://httpd.apache.org/download.cgi"&gt;The Apache HTTP  Server Project&lt;/a&gt;. I prefer the zip over the Windows Installer. You are free to choose the Windows Installer if you wish, but modify the service instructions below accordingly.&lt;br /&gt;&lt;br /&gt;2. &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;Apache Tomcat 5.5.20&lt;/span&gt; from &lt;a href="http://tomcat.apache.org/download-55.cgi"&gt;Apache Tomcat downloads&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;3. &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;Mod JK Tomcat connector &lt;/span&gt;from &lt;a href="http://tomcat.apache.org/download-connectors.cgi"&gt;here&lt;/a&gt;. Please note: You want to download the binary- click on JK 1.2 Binary Releases --&gt; win32 --&gt; jk-1.2.21 --&gt; mod_jk-apache-2.2.4.so&lt;br /&gt;&lt;br /&gt;Now let's start by installing Tomcat first.&lt;br /&gt;&lt;br /&gt;1. Extract the Tomcat zip. Hereafter, the directory you extracted to will be referred to as &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;2. Test Tomcat to see that it works. Go to &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;/span&gt;\bin and run startup.bat&lt;br /&gt;You may need to add an environment variable called &lt;span style="font-weight: bold; font-style: italic;"&gt;CATALINA_HOME&lt;/span&gt; which is set to &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;/span&gt; in case Tomcat fails to start.&lt;br /&gt;&lt;br /&gt;3. Open up your browser and access http://localhost:8080/&lt;br /&gt;If you see the default page, then Tomcat Instance 1 is working fine. Shut down Tomcat.&lt;br /&gt;&lt;br /&gt;4. Now set this up as a service. Go to your command prompt, change directory to &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;/span&gt;\bin and set an environment variable called &lt;span style="font-weight: bold; font-style: italic;"&gt;CATALINA_BASE&lt;/span&gt;. The value of this variable should again, be &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME. &lt;/span&gt;For example:&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;SET CATALINA_BASE=C:\Tomcat-5.5.20&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Then, execute the following: &lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;service install Tomcat5&lt;/span&gt;&lt;br /&gt;This will set up the Windows service for Tomcat.&lt;br /&gt;&lt;br /&gt;5.  Go to your Services and see that Tomcat 5 is listed. Start the service, and then verify again that http://localhost:8080 is up.&lt;br /&gt;That's all for the first Tomcat instance. Now for the second.&lt;br /&gt;&lt;br /&gt;1. Make a directory called SecondInstance in &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;2. Copy the conf, logs, shared, temp, webapps and work directories from the &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;/span&gt; directory into the SecondInstance directory.&lt;br /&gt;&lt;br /&gt;3. Open up SecondInstance\conf\server.xml in a text editor. We've got to change the port numbers so that they don't conflict with the first instance.&lt;br /&gt;I just incremented by 10 and changed them as follows, but you could use other port numbers:&lt;br /&gt;&lt;span style="color: rgb(255, 102, 0);font-family:courier new;" &gt;&lt;code&gt;&lt;br /&gt;&amp;lt;Server port="8005" shutdown="SHUTDOWN"&amp;gt; &lt;span style="color: rgb(0, 0, 0);"&gt;to&lt;/span&gt; &lt;span style="color: rgb(0, 0, 153);"&gt;&amp;lt;Server port="8015" shutdown="SHUTDOWN"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Connector port="8080" maxHttpHeaderSize="8192"... &lt;span style="color: rgb(0, 0, 0);"&gt;to&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 153);"&gt;&amp;lt;Connector port="8090" maxHttpHeaderSize="8192"...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Connector port="8009" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" /&amp;gt; &lt;span style="color: rgb(0, 0, 0);"&gt;to&lt;/span&gt; &lt;span style="color: rgb(0, 0, 153);"&gt;&amp;lt;Connector port="8019" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="color: rgb(0, 0, 0);font-family:georgia;" &gt;Change the SSL port if you need it as well.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;4. Now set up the second instance to run as a service. Go to the command prompt, change to the&lt;span style="font-weight: bold; font-style: italic;"&gt; TOMCAT_HOME&lt;/span&gt;\bin directory. Set the &lt;span style="font-weight: bold; font-style: italic;"&gt;CATALINA_BASE&lt;/span&gt; environment variable to &lt;span style="font-weight: bold; font-style: italic;"&gt;TOMCAT_HOME&lt;/span&gt;\SecondInstance. For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    SET CATALINA_BASE=C:\Tomcat5.5.20\SecondInstance&lt;/span&gt;&lt;br /&gt;Then, type:&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    service install SecondTomcat&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Go to Services and start the SecondTomcat service. Test it out by pointing your browser to http://localhost:8090/&lt;br /&gt;Works ok? Great! Your second tomcat instance is now ready to be used.&lt;br /&gt;&lt;br /&gt;Next, let's set up the Apache HTTP Server. It's pretty simple...&lt;br /&gt;&lt;br /&gt;1. Run the installer you downloaded. The standard install will do.&lt;br /&gt;&lt;br /&gt;2. Open the Apache Server Monitor and start the web server if it's not already running.&lt;br /&gt;&lt;br /&gt;3. Point your browser to http://localhost/ to verify that Apache is running on port 80.&lt;br /&gt;&lt;br /&gt;4. Stop Apache.&lt;br /&gt;&lt;br /&gt;Finally, we reach mod JK. Let's set it up first just to delegate requests to the two Tomcat instances, and we'll load balance it a bit later.&lt;br /&gt;&lt;br /&gt;1. Copy the mod_jk-apache-2.2.4.so to the modules directory in your Apache installation.&lt;br /&gt;&lt;br /&gt;2. Rename it to mod_jk.so&lt;br /&gt;&lt;br /&gt;3. Open up httpd.conf in the conf directory of your Apache installation in a text edit, and add the following line at the end of the set of LoadModule statements:&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;LoadModule jk_module modules/mod_jk.so&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;4. Create a file called workers.properies in the conf directory. Add these lines to it:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    workers.tomcat_home=C:/tomcat-5.5.20&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    workers.java_home=C:/jdk1.5.0_03&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.list=worker1,worker2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;    worker.worker1.port=8009&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker1.host=localhost&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;br /&gt;worker.worker1.type=ajp13&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker2.port=8019&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;br /&gt;worker.worker2.host=localhost&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;&lt;br /&gt;worker.worker2.type=ajp13&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This file defines which workers Apache can delegate to. We've listed worker1 and worker 2 to correspond to our two tomcat instances. Remember to set tomcat_home and java_home as well.&lt;br /&gt;&lt;br /&gt;5. Specify the worker properties in httpd.conf:&lt;br /&gt;&lt;br /&gt;Add these lines just after the LoadModule definitions-&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# Path to workers.properties&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkWorkersFile c:/apache2.2/conf/workers.properties&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# Path to jk logs&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkLogFile c:/apache2.2/mod_jk.log&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# Jk log level [debug/error/info]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkLogLevel info&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# Jk log format&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# JkOptions for forwarding&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;# JkRequestLogFormat set the request format&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkRequestLogFormat "%w %V %T"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /jsp-examples worker1&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /jsp-examples/* worker1&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /tomcat-docs worker2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /tomcat-docs/* worker2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Defining these tells Apache where to look for definitions of its workers and tells it that any requests for the jsp-examples context should be handed off to the Tomcat instance represented by worker 1, and any requests for tomcat-docs context should be handed off to Tomcat Instance 2, represented by worker 2.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;5.5 [Added on April 11 2007]&lt;/span&gt;&lt;br /&gt;Edit the server.xml for Tomcat and Tomcat's SecondInstance and add a jvmRoute attribute to the Engine element:&lt;br /&gt;&lt;span style="color: rgb(255, 102, 0);"&gt;&amp;lt;Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1"&amp;gt;&lt;/span&gt;&lt;br /&gt;for the first instance and&lt;br /&gt;&lt;span style="color: rgb(255, 102, 0);"&gt;&amp;lt;Engine name="Catalina" defaultHost="localhost" jvmRoute="worker2"&amp;gt;&lt;/span&gt;&lt;br /&gt;for the second.&lt;br /&gt;&lt;br /&gt;6. Start Tomcat Instance 1 and 2. Start up the Apache webserver. Point your browser to http://localhost/jsp-examples/ and then to http://localhost/tomcat-docs. You should see the respective pages load. To distinguish which Tomcat is serving you the page, the easiest thing to do is edit the index page in the tomcat-docs and jsp-examples of Tomcat 2 and change the title for example. Then you can verify that tomcat-docs is being served only by the second instance.&lt;br /&gt;&lt;br /&gt;Thats it!! Apache is now delegating requests to both Tomcats.&lt;br /&gt;Now for our last task- we will load balance it so that Apache distributes load for jsp-examples between both instances of Tomcat. It also serves as a failover mechanism. If Tomcat 1 is down for whatever reason, Apache will automatically keep delegating to Tomcat 2 so your application remains accessible.&lt;br /&gt;&lt;br /&gt;Load balancing is a simple configuration. First shut down your Tomcat instances and Apache as well.&lt;br /&gt;&lt;br /&gt;1. Open workers.properties in a text editor.&lt;br /&gt;&lt;br /&gt;2. Edit it so it looks like this (changed lines in bold)-&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;workers.tomcat_home=C:/tomcat-5.5.20&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;workers.java_home=C:/jdk1.5.0_03&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;#worker.list=worker1,worker2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.list=balancer&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker1.port=8009&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker1.host=localhost&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker1.type=ajp13&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.worker1.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker2.port=8019&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker2.host=localhost&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;worker.worker2.type=ajp13&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.worker2.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.balancer.type=lb&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.balancer.balance_workers=worker1,worker2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;font-family:courier new;" &gt;worker.balancer.method=B&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;We've changed the worker list to a single worker called balancer, and specified that the worker type of balancer is 'lb' or load balancer. The workers it manages are worker1 and worker2 (these do not need to appear in the workers list). And finally, we set the balance method to 'B' or balance by busy factor. Apache will delegate the next request to the Tomcat instance which is least busy. Please note that there are a couple of options for method- consult the Apache/Tomcat documentation which lists out options for workers properties to help you decide the best method for your type of application.&lt;br /&gt;&lt;br /&gt;3. Open httpd.conf and comment out the previous JkMount directives. Replace them with these:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /jsp-examples balancer&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;JkMount /jsp-examples/* balancer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Very simple- we've just pointed Apache to a single worker- the balancer.&lt;br /&gt;&lt;br /&gt;4. Start up both Tomcats and Apache. Access http://localhost/jsp-examples&lt;br /&gt;You will either be served by Tomcat 1 or Tomcat 2. To prove that both are capable of serving, shut down the first instance and refresh your browser. You should be served by instance two.&lt;br /&gt;&lt;br /&gt;Congratulations! You've successfully set up Apache load balancing multiple tomcat instances!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-582598632150746999?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Eps2K6UuDdeTXwWgcVxWF5JZYWU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Eps2K6UuDdeTXwWgcVxWF5JZYWU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Eps2K6UuDdeTXwWgcVxWF5JZYWU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Eps2K6UuDdeTXwWgcVxWF5JZYWU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/WW6yyoc8Q4I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/582598632150746999/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=582598632150746999" title="72 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/582598632150746999?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/582598632150746999?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/WW6yyoc8Q4I/how-to-load-balance-tomcat-55-with.html" title="How to load balance Tomcat 5.5 with Apache on Windows" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>72</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/03/how-to-load-balance-tomcat-55-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4BSXs8eSp7ImA9WBFQEkg.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-5121149006175526982</id><published>2007-03-07T14:07:00.000+05:30</published><updated>2007-03-07T14:29:18.571+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-07T14:29:18.571+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="no src" /><category scheme="http://www.blogger.com/atom/ns#" term="jsp" /><category scheme="http://www.blogger.com/atom/ns#" term="page reloads" /><category scheme="http://www.blogger.com/atom/ns#" term="page loads twice" /><category scheme="http://www.blogger.com/atom/ns#" term="img" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Help! My page loads twice...</title><content type="html">I spent all morning looking at a jsp which was taking too long to load. It executed a query and then displayed results.&lt;br /&gt;First, I assumed it was the query. So I timed it but found that it took 1/4th of the entire page load time.&lt;br /&gt;Then, I put in timers in the jsp around certain blocks of code and watched my Tomcat console. To my surprise, I saw the timers printed twice on the console- one set, then the next.&lt;br /&gt;So apparently, my page was reloading. I checked all pages that linked to this... put in alerts and everything possible to see which was trying to load the page a second time (this page is in an iframe...so the possibility does exist)- but all pages seemed clean.&lt;br /&gt;&lt;br /&gt;Then, I decided to eliminate all jsp code and js as well. It still loaded twice. Finally, I had no option but to remove html bit by bit till I find the section forcing the reload. Believe me, that was a painful process.&lt;br /&gt;&lt;br /&gt;It came down to a cell in a table. The contents of the cell were an anchor with content as an image. Remove the image...and voila! the page loaded only once.&lt;br /&gt;Now why would an image cause a page to reload?&lt;br /&gt;&lt;br /&gt;Here is where I demonstrate my stupidity:&lt;br /&gt;&lt;br /&gt;We basically have a whole lot of thumbnail images displayed on that page. So we have image tags like &lt;pre style="color: rgb(51, 51, 255);"&gt;&lt;code&gt;&amp;lt;img id="theId" src="dummyImg.jpg" /&amp;gt;&lt;/code&gt;&lt;/pre&gt; etc.&lt;br /&gt;Now, I am dynamically assigning the src via JavaScript. So I thought, why let all the dummyImg.jpg's load if I'm going to be replacing them anyway. I removed the src... yes I actually did this-&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);"&gt;&lt;code&gt;&amp;lt;img id="theId" src="" /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And that was my folly. When I looked at the Page Info in my browser, the media list contained this image, with address http://www.xyz.com/theBadPage.jsp&lt;br /&gt;It just used a relative path and appended nothing because the src was empty. And obviously, it tried to fetch the image, which in this case was the page itself, and hence the reload.&lt;br /&gt;&lt;br /&gt;That is why it took so long... re-executed the query, did whatever calculations and assigments all over again.... just because of the empty src.&lt;br /&gt;Now I have set it to a 1 pixel transparent gif... and have learnt a jolly good lesson...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-5121149006175526982?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3EpLRzEh3Ujab4L8yRzLRlP7JSg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3EpLRzEh3Ujab4L8yRzLRlP7JSg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3EpLRzEh3Ujab4L8yRzLRlP7JSg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3EpLRzEh3Ujab4L8yRzLRlP7JSg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/jHHmFi0iQrA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/5121149006175526982/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=5121149006175526982" title="25 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/5121149006175526982?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/5121149006175526982?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/jHHmFi0iQrA/help-my-page-loads-twice.html" title="Help! My page loads twice..." /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>25</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/03/help-my-page-loads-twice.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQCRno6fSp7ImA9WBFRF0g.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-1754200506555246760</id><published>2007-03-01T17:00:00.000+05:30</published><updated>2007-03-01T17:29:27.415+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-01T17:29:27.415+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="intern" /><category scheme="http://www.blogger.com/atom/ns#" term="performance tuning" /><category scheme="http://www.blogger.com/atom/ns#" term="strings" /><category scheme="http://www.blogger.com/atom/ns#" term="optimization" /><category scheme="http://www.blogger.com/atom/ns#" term="equals" /><category scheme="http://www.blogger.com/atom/ns#" term="stringbuffer" /><title>Java String performance</title><content type="html">&lt;span style="font-family:georgia;"&gt;We all know that misuse of Strings degrade performance. But more often than not, we go back to look at our String code only when we are asked to optimize performance. This is a short blog on the performance aspect of Strings which would be good to keep in mind when coding.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;So, the first thing to remember is that Strings are immutable- once you create them, you can't change them. Oh yes, you might &lt;span style="font-style: italic;"&gt;think&lt;/span&gt; you're modifying them, but in reality, a new String is generated. Warning bells should be ringing in your head by now :-)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;If you are concatenating Strings over and over, lets say in a loop, then you know that because they are immutable, new Strings keep getting generated. The javac compiler internally uses a StringBuffer to do this- so for example, you have&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;pre&gt; String itemList = "";&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;  &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt; itemList=itemList + items[i].description;&lt;/pre&gt;&lt;/span&gt;in a loop.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;What happens is, within the loop, two objects are generated. One is a StringBuffer- &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;itemList=new StringBuffer().append(itemList).&lt;br /&gt;          append(items[i].description).toString();&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;The other is the String that gets assigned to itemList via the toString().&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;A much better way out would be to create a StringBuffer outside the loop, and just append to it within the loop. More efficient.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Also beware of certain String operations like substring, trim or replace that actually work by creating new Strings. Consider using equivalent StringBuffer methods instead.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Another thing we do not think about is comparing Strings.&lt;br /&gt;Comparing a String via equals() can be fairly expensive. It basically involves a character-by-character comparison, though every effort is made to avoid it. For example, if the lengths do not match, the character by character comparison is not done. But there are many cases where lengths are same and strings are long... in these cases, equals() can be time consuming.&lt;br /&gt;Now we know that comparing Strings with == will not solve our problem because == compares the pointer references, and since both Strings are different instances, you will get a false, even if characters match.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Fortunately, there is a way out, if you know about the intern() method. According to the JavaDoc, intern() returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;What this means is that if you have two identical Strings and intern them, only one instance is maintained. So then you can safely use == and have it compare the references and hence return a true.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Now the compiler automatically interns String constants for you. But you could explicitly intern() other Strings that will be compared extensively and repetitively, for example.&lt;br /&gt;&lt;br /&gt;As with everything else in life, make sure that if you are interning, do it &lt;span style="font-weight: bold;"&gt;responsibly&lt;/span&gt;. If you intern every String in sight, you are in deep trouble. A pool of Strings will have maintenance costs and you cannot rely on interned Strings getting garbage collected. Hence, if you use it rashly, your performance will actually degrade and you will possibly run into memory issues.&lt;br /&gt;It is worth knowing about intern though- after tuning other areas of your code, you could consider intern especially if you know for a fact that a particular operation will be more efficient by interning the String in question. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-1754200506555246760?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oP598oMR0ZYc9655I3yi77amP3E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oP598oMR0ZYc9655I3yi77amP3E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oP598oMR0ZYc9655I3yi77amP3E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oP598oMR0ZYc9655I3yi77amP3E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/L21QCucitTg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/1754200506555246760/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=1754200506555246760" title="15 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1754200506555246760?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/1754200506555246760?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/L21QCucitTg/java-string-performance.html" title="Java String performance" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>15</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/03/java-string-performance.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AGQXo5eyp7ImA9WBFRF08.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-4131018040587128904</id><published>2007-02-28T15:26:00.000+05:30</published><updated>2007-03-01T11:45:20.423+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-01T11:45:20.423+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="zimoz postcard web2.0" /><title>Zimoz.com</title><content type="html">(i should state upfront that Luanne is part of the zimoz product team)&lt;br /&gt;&lt;br /&gt;I've been hearing a lot about this new site &lt;a href="http://www.zimoz.com/"&gt;http://www.zimoz.com/&lt;/a&gt; (reasons - above ;) ) Zimoz.com is a way to create and communicate your feelings, thoughts, pictures or video with a postcard. It fits neatly into the &lt;a href="http://en.wikipedia.org/wiki/Web_2"&gt;Web 2.0&lt;/a&gt; buzz that you hear of nowadays. The user interface is very easy to use without the clutter of options that you would rarely use. I've seen it evolve over the last few months and it seems to have somewhat stabilized in its current state. The zimoz team has been very responsive to user feedback which shows in its latest version. It's still in beta though. I'm looking forward to when it goes fully live. I won't go into another review here (here's a &lt;a href="http://www.webyantra.net/2007/02/11/zimozblogging-on-postcards/"&gt;review you can read&lt;/a&gt; though). What really gets me excited about zimoz is the amount of technology that has gone into the product. They use ajax a lot and you can tell that a lot of effort has gone into the UI for creating postcards. Speaking to Luanne I hear that there are a number of new features planned and they all sound neat. It could really change the way you look at the web today. With this movement towards web 2.0, where the community drives the content and more control is with the user, zimoz plays its part and plays it well. I can see a myriad sites that could do with the 'zimoz way' and I'm sure the community will come up with creative ways to exploit all this wonderful technology. I'm impressed. Way to go, guys!!&lt;br /&gt;&lt;br /&gt;Check my own postcard at &lt;a href="http://www.zimoz.com/zimo/user/aldrin/1172602091492.postcard"&gt;http://www.zimoz.com/zimo/user/aldrin/1172602091492.postcard&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;Aldrin&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-4131018040587128904?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LeiWdhEIuj58jNsuPwcPbaKbgUM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LeiWdhEIuj58jNsuPwcPbaKbgUM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LeiWdhEIuj58jNsuPwcPbaKbgUM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LeiWdhEIuj58jNsuPwcPbaKbgUM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/_3NMnzA3rI4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/4131018040587128904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=4131018040587128904" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4131018040587128904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/4131018040587128904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/_3NMnzA3rI4/zimozcom.html" title="Zimoz.com" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/zimozcom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8EQXw-cCp7ImA9WBFRFUg.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-7243021691772780093</id><published>2007-02-27T09:49:00.000+05:30</published><updated>2007-02-27T10:03:20.258+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-27T10:03:20.258+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox" /><category scheme="http://www.blogger.com/atom/ns#" term="scrollLeft" /><category scheme="http://www.blogger.com/atom/ns#" term="ie" /><category scheme="http://www.blogger.com/atom/ns#" term="scroll position" /><category scheme="http://www.blogger.com/atom/ns#" term="scrollTop" /><category scheme="http://www.blogger.com/atom/ns#" term="pageXOffset" /><category scheme="http://www.blogger.com/atom/ns#" term="pageYOffset" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox internet explorer browser firebug DOM CSS HTML inspector" /><category scheme="http://www.blogger.com/atom/ns#" term="browser" /><title>IE and Firefox- Scroll Offsets</title><content type="html">Many times, one needs to know scroll positions- how much the user has scrolled in a web page. These are particularly useful to display a dialog for example, in the center of the visible space of the browser.&lt;br /&gt;As usual, there are different ways to get this figure in IE and Firefox.&lt;br /&gt;&lt;br /&gt;In Firefox, you would use the window.pageYOffset or window.pageXOffset to get these positions. In IE, you would use document.documentElement.scrollTop or document.documentElement.scrollLeft.&lt;br /&gt;&lt;br /&gt;So, to handle both browsers, a simple function to do this would be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;function getYOffset() {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    var pageY;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    if(typeof(window.pageYOffset)=='number') {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;       pageY=window.pageYOffset;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    else {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;       pageY=document.documentElement.scrollTop;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;    return pageY;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-7243021691772780093?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ed6-5egL_J1-YNMrY6oUAffm9-E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ed6-5egL_J1-YNMrY6oUAffm9-E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ed6-5egL_J1-YNMrY6oUAffm9-E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ed6-5egL_J1-YNMrY6oUAffm9-E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/47ajQOxoIaM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/7243021691772780093/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=7243021691772780093" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/7243021691772780093?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/7243021691772780093?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/47ajQOxoIaM/ie-and-firefox-scroll-offsets.html" title="IE and Firefox- Scroll Offsets" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/ie-and-firefox-scroll-offsets.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ANQnY_fyp7ImA9WBFRFUk.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-8057192754820270980</id><published>2007-02-27T09:43:00.000+05:30</published><updated>2007-02-27T09:46:33.847+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-27T09:46:33.847+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="services" /><category scheme="http://www.blogger.com/atom/ns#" term="ooad" /><category scheme="http://www.blogger.com/atom/ns#" term="service oriented analysis and design" /><category scheme="http://www.blogger.com/atom/ns#" term="object oriented analysis and design" /><category scheme="http://www.blogger.com/atom/ns#" term="soad" /><title>The SOA hype</title><content type="html">&lt;span style="font-family:georgia;"&gt;We were rather surprised at the response we received for the SOAD workshop.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Most of the participants came in awe of SOAD, hoping to hear the hype and the promise that SOAD would turn their projects into raging successes overnight.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; Instead, they heard that services are nothing new- they've been around for ages. And that good designers have already been practising it implicitly.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; Using services does not mean that all your project problems will be solved instantly- everything boils down to good analysis and design skills. Everybody wants to hear that this is some great new technology and that OOAD is old fashioned and should be shelved. Many were not willing to accept that you need good OOAD skills first. Only after this will you be able to grasp and apply correctly service oriented analysis and design to produce more flexible software.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Which just goes to show- how many people understand concepts and basic principles- and how many want a quick fix solution and an excuse to use the latest buzzwords...&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-8057192754820270980?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/spMNYjFn3_WGoCNOkEX17AszNos/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/spMNYjFn3_WGoCNOkEX17AszNos/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/spMNYjFn3_WGoCNOkEX17AszNos/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/spMNYjFn3_WGoCNOkEX17AszNos/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/RukLtGfDRm0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/8057192754820270980/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=8057192754820270980" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8057192754820270980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/8057192754820270980?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/RukLtGfDRm0/soa-hype.html" title="The SOA hype" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/soa-hype.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ICSXo7cSp7ImA9WBFRFEs.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-3740622374142834748</id><published>2007-02-26T09:10:00.000+05:30</published><updated>2007-02-26T09:16:08.409+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-26T09:16:08.409+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="experience commerce" /><category scheme="http://www.blogger.com/atom/ns#" term="service oriented analysis and design" /><category scheme="http://www.blogger.com/atom/ns#" term="soad" /><title>Service oriented analysis and design workshop</title><content type="html">&lt;span style="font-family: georgia;"&gt;Unfortunately, I haven't been able to post anything for the past couple of days. I was part of a workshop on Service Oriented Analysis and Design conducted by &lt;/span&gt;&lt;a style="font-family: georgia;" href="http://www.experiencecommerce.com"&gt;Experience Commerce&lt;/a&gt;&lt;span style="font-family: georgia;"&gt; in Mumbai.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;More on this and others later... keep reading!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-3740622374142834748?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/slIo4_dnbjWMi9yrRWqEhGoYOq8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/slIo4_dnbjWMi9yrRWqEhGoYOq8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/slIo4_dnbjWMi9yrRWqEhGoYOq8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/slIo4_dnbjWMi9yrRWqEhGoYOq8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/DdtWDS-hNGk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/3740622374142834748/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=3740622374142834748" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/3740622374142834748?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/3740622374142834748?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/DdtWDS-hNGk/service-oriented-analysis-and-design.html" title="Service oriented analysis and design workshop" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/service-oriented-analysis-and-design.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EHQXw7cSp7ImA9WB9bEkw.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-2378177846343535971</id><published>2007-02-21T13:27:00.000+05:30</published><updated>2007-12-21T11:10:30.209+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-21T11:10:30.209+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox" /><category scheme="http://www.blogger.com/atom/ns#" term="onload" /><category scheme="http://www.blogger.com/atom/ns#" term="internet explorer" /><category scheme="http://www.blogger.com/atom/ns#" term="technology" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><category scheme="http://www.blogger.com/atom/ns#" term="window" /><category scheme="http://www.blogger.com/atom/ns#" term="attach events" /><category scheme="http://www.blogger.com/atom/ns#" term="browser" /><title>Attaching JavaScript functions to the Window OnLoad event</title><content type="html">In an earlier post, I had griped about IE but forgot to mention details about the actual problem. The issue was with the way we were using the html web page's onload event. We were attempting to do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;body onload="someFunk()"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;Testing the onload function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;...&amp;lt;br /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt; &amp;lt;body onload="anotherFunk()"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   You shouldn't be nesting another body tag out here !&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt; &amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yes, exactly, two body onload functions! I'll come to 'why' later. The above code doesn't work - only the outer BODY's onload event is really triggered (someFunk only is called)&lt;br /&gt;&lt;br /&gt;There is in fact a better way to attach the second function (and any subsequent functions) to the onload event. A quick utility function for this can be found at &lt;a href="http://www.dustindiaz.com/top-ten-javascript"&gt;http://www.dustindiaz.com/top-ten-javascript&lt;/a&gt; . This function simply appends your function to the existing list (meta function ?). Try this code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;function addLoadEvent(func) {&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   var oldonload = window.onload;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   if (typeof window.onload != 'function') {&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;       window.onload = func;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   else {&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;       window.onload = function() {&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;           oldonload();&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;           func();&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;       }&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;body onload="someFunk()"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;Testing the onload function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;...&amp;lt;br /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;   This is better&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt; addLoadEvent(anotherFunk);&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(51,102,255)"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Neat, elegant solution and works consistently in IE and Firefox.&lt;br /&gt;&lt;br /&gt;Now coming back to the earlier question of 'Why?'. Why did we land up with a nested body tag like that? Well we are using this framework that allows us to define a common template for a group of pages. Now some of these pages needed to trigger a javascript function on body load. This was conveniently achieved by adding a &amp;lt;body onload="..."&amp;gt; to these pages. This worked fine as long as the templates themselves did not have a &amp;lt;body onload="..."&amp;gt;! The moment a template defined a body onload event, the content page body onload, if present, was ignored. Such situations happen more often than not with templates being written by one person and other content pages being developed by various other people. There was already a way to do this in our code base but we didn't spot it immediately. It took a while to figure out and it was interesting investigating this. Well, everyday you learn something new (and my writing has been deteriorating !! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-2378177846343535971?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/832NsaPF8Rw2gU2pCiXgbhl0dko/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/832NsaPF8Rw2gU2pCiXgbhl0dko/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/832NsaPF8Rw2gU2pCiXgbhl0dko/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/832NsaPF8Rw2gU2pCiXgbhl0dko/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/1n7_NFYgNFs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/2378177846343535971/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=2378177846343535971" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2378177846343535971?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2378177846343535971?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/1n7_NFYgNFs/attaching-javascript-functions-to.html" title="Attaching JavaScript functions to the Window OnLoad event" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/attaching-javascript-functions-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAHRn4yfip7ImA9WBFSF0U.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-2534894360921343049</id><published>2007-02-18T12:57:00.000+05:30</published><updated>2007-02-18T12:58:57.096+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-18T12:58:57.096+05:30</app:edited><title>The Indian Software Factory</title><content type="html">&lt;span style="font-family: georgia;"&gt;I have been having this feeling for quite a while now, that the Great Indian Software Industry is little more than wool over our bleary eyes. At first I thought it was just me. But of late, I have been meeting people who feel the same. And finally today, to confirm my suspicions, was an article published in the Times of India entitled 'A myth called the Indian Programmer'. The very industry we claimed was THE place to be, is now a monster. To put it a bit harshly, we are no more than slaves in a sweatshop. We are no more than robots with a $ per day tag stamped onto our foreheads. We are back in the dark ages where producing more and more lines of code in the shortest possible time, earning the maximum amount of money is the very cornerstone of our lives.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;Who has time to think anymore? About how we do our work? Are we doing it the right way? Are we even thinking about doing it the right way? Of course not- the powers higher up do not pay you to think. Why would they- your thinking time has cost them money. The bottomline is- how much work can you pack into your day. And how much money can it earn. Not enough? Then work nights of course!!! Do whatever it takes. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;We have increasingly become a crazier lot. Let's present the client with this impossible estimate and impossible schedule. And then do whatever it takes to meet it. At the cost of quality and our intelligence. The clients, poor suckers, are overjoyed. Little do they know that the bright Indian Programmers are toiling day and night to fulfil their every whim and fancy and that there is a limit as to how much ones brain can take before producing complete cr*p because they are too exhausted to do anything else. They'll either scrap the project sooner or later or spend a fortune maintaining it. Yeah!!!! More work outsourced to us.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;You probably think I am a big cynic- and I don't deny it. I call it as I see it. And this is by no means a take on all the programmers out here in India. I personally know excellent ones who are simply boxed in by the industry. I know how it feels. I have been there. Some months back, I am ashamed to admit, I too stopped thinking. Completely. I rushed all over the place to complete work. Just do it. Don't think. And I knew I would regret that. I did. My failure to think was a a personal failure. A failure to my team by taking rash decisions and making poor choices, a failure to the work I loved, a failure to produce good quality software that I could be proud of. And so I quit. Till today, many are concerned about my future. Even bewildered at what I did. I had it all and threw it away. But I do not regret it. My mind is no longer enslaved. I can go back to doing the work I love and not insult it by churning out rubbish everyday.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;I frankly do not see it getting better. Most (please note, I say most- there are most certainly exceptions) companies now work on this model. A pity.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;To those who say well, this earns your bread and butter, I do not dispute it. To those to say this work enables you to have a grand lifestyle, again I do not dispute it. Everyone has different priorities. Everyone enjoys their work in different ways. But please, let us stop boasting about the great software industry. We don't do that much at all. To those excellent engineers out there- you know who you are- I know it is hard, and I know what conditions you face, but try never to give up on thinking...don't let our beloved field of work down...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;Cynically yours,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;Luanne&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;PS: Do read this very long, but interesting blog &lt;/span&gt;&lt;a style="font-family: georgia;" href="http://steve-yegge.blogspot.com/2006/09/good-agile-bad-agile_27.html"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-2534894360921343049?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UP5wf4r9gZPfkz7po83_9Xolt9c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UP5wf4r9gZPfkz7po83_9Xolt9c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UP5wf4r9gZPfkz7po83_9Xolt9c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UP5wf4r9gZPfkz7po83_9Xolt9c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/6yKjvtptCoM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/2534894360921343049/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=2534894360921343049" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2534894360921343049?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2534894360921343049?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/6yKjvtptCoM/indian-software-factory.html" title="The Indian Software Factory" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/indian-software-factory.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUACSX85fSp7ImA9WBFSFk8.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-3048997304496846374</id><published>2007-02-16T17:09:00.000+05:30</published><updated>2007-02-16T17:39:28.125+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-16T17:39:28.125+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="firefox internet explorer browser firebug DOM CSS HTML inspector" /><title>Here's to Firefox</title><content type="html">Firefox is my default browser by choice. Features that Internet Explorer (IE) has only recently have been present in Firefox for a long time. Which makes me wonder - Why do people still use IE?!! Lets take a poll here and hear your preference. Could you please take a moment to leave a comment to this post and mention the browser you prefer to use? Thanks!&lt;br /&gt;The fact that Firefox scores over IE was reinforced again today, when we were facing a confounding problem with one of our web pages. There was a menu on this page that just refused to show up. By the way, we were required to test only on IE for this particular application. When I decided to investigate this problem, by default I fired up Firefox to check it out and surprise, surprise - the menu worked just fine! That proved one thing - that the HTML being generated from the server was all right. Next possibility - some Javsascript or CSS was failing badly. This is when I began to tear my hair out (whatever little is left of it). There was simply no straightforward way to debug this in IE. Debugging was and is an extremely painful and laborious process in IE, involving scrolling through lines of HTML code picking up suspicious sections.  Contrast this with Firefox, which has these 'add-ons' where you can inspect the HTML source, see the CSS styles, debug the JavaScript, enable/disable styles and a hundred other nifty, useful thingamajigs - all designed to help web developers nail down problems. Highly recommended for debugging HTML, CSS, Javascript are the DOM Inspector, Firebug and Web Developer add-ons. It high time IE develops features like these. It's not that IE is such a bad browser (IE 7 with it's tabbed windows is pretty decent), but the thoughtful little customizable things that Firefox provides makes it a far more pleasant experience. And shouldn't the internet (and software engineering) be all about the experience ? :)&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;Al&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-3048997304496846374?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/M7TI8HSwVIxLf2lIlSQ-E3U9VaQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/M7TI8HSwVIxLf2lIlSQ-E3U9VaQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/M7TI8HSwVIxLf2lIlSQ-E3U9VaQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/M7TI8HSwVIxLf2lIlSQ-E3U9VaQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/lMDZyGC6TNY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/3048997304496846374/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=3048997304496846374" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/3048997304496846374?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/3048997304496846374?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/lMDZyGC6TNY/heres-to-firefox.html" title="Here's to Firefox" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/heres-to-firefox.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UBQnwzeCp7ImA9WBFSFU4.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-6970848429624085921</id><published>2007-02-15T16:41:00.000+05:30</published><updated>2007-02-15T17:04:13.280+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-15T17:04:13.280+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="technology" /><category scheme="http://www.blogger.com/atom/ns#" term="coding standards" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Defend thyself!</title><content type="html">&lt;span style="font-family:georgia;"&gt;I have learnt many invaluable lessons from my friend and top notch software engineer Jock Murphy. One of them was to code defensively. If there is the remote possibility that something can be null, be prepared to handle it. Although I have never forgotten that lesson, I fail to implement it many times. The past couple of days have been particularly horrific. I've had NullPointerExceptions laughing their heads off at me. And at those moments, I remember Jock and curse myself.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I also remember the yellow bit of paper on which I wrote down his programming practices as he told them to me and a colleague about a couple of years back.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;I still have that paper- and I am sure that he will not mind if I share the contents with you for the good of software-kind.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-weight: bold;"&gt;1. JavaDoc- &lt;/span&gt;Public and protected methods and properties should have JavaDoc. Things that you should put down is the purpose (what it does or what it is- not how it does it), inputs, outputs and exceptions. I have noticed that usually, JavaDoc falls into three categories- none, wrong, or excessive. I don't believe in adding JavaDoc for regular getters and setters, unless your getter or setter does more than meets the eye. In that case, one should consider why it does that in the first place. Otherwise, document it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-weight: bold;"&gt;2. Magic Numbers- &lt;/span&gt;You should never, ever have a magic number in your code. For example, &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;   &lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(51, 51, 153);"&gt; int something=somethingElse * 329;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;What the heck is 329? It should be:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(51, 51, 153);"&gt;int something=somethingElse * Constants.NUMBER_OF_VIEWS;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;You could define that constant externally in an interface, or locally in the class if it is the only class that will ever use it. Just imagine if 23 classes use 329- and then someone tells you it should be 330. Instead of abusing the guy and doing a search and replace, just go change the constant.&lt;br /&gt;&lt;br /&gt;Imagine if you did do a search and replace and class A had the line:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;   &lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(51, 51, 153);"&gt; int foo= bar + 329;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;329 here means something completely different. You have then shot yourself in the foot. Define another constant!!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-weight: bold;"&gt;3. Logging- &lt;/span&gt;Logging is your friend. Log exceptions, unexpected conditions, logic failures&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-weight: bold;"&gt;4. Exception Handling- &lt;/span&gt;Sure it's nice to define our own custom exceptions. But define and use them wisely. Don't throw exceptions all over the place- they are expensive. When you encounter an exception, log it and then handle it, or pass it on. If you don't require to have an exception thrown, don't throw one. Usually, many custom exceptions can be handled in other gentle ways.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;span style="font-weight: bold;"&gt;5. Defensive Programming-&lt;/span&gt; As mentioned above, be prepared to handle any bad data. And assume as little as possible.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;It's not rocket science- there are no buzz words or impressive rules... just plain basics...but believe me, if you follow these, you will be much happier...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Thank you Jock...I am a better engineer today :-)&lt;br /&gt;&lt;br /&gt;-Luanne&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-6970848429624085921?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5lV36VxGP0lz8mpGBt1LZ2Dk9QY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5lV36VxGP0lz8mpGBt1LZ2Dk9QY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5lV36VxGP0lz8mpGBt1LZ2Dk9QY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5lV36VxGP0lz8mpGBt1LZ2Dk9QY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/P1U8Hef03zQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/6970848429624085921/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=6970848429624085921" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/6970848429624085921?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/6970848429624085921?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/P1U8Hef03zQ/defend-thyself.html" title="Defend thyself!" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/defend-thyself.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4GQHo7fyp7ImA9WBFSFU4.&quot;"><id>tag:blogger.com,1999:blog-8978951075400478206.post-2765982810154160387</id><published>2007-02-15T15:27:00.000+05:30</published><updated>2007-02-15T16:25:21.407+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-15T16:25:21.407+05:30</app:edited><title>Welcome!</title><content type="html">&lt;span style="color: rgb(0, 0, 0); font-family: georgia;font-size:100%;" &gt;Welcome to our tech blog!&lt;br /&gt;&lt;br /&gt;Down the years [ok, we're not THAT old but makes this sound impressive ;-) ] we've formed a lot of opinions on goings on in the tech world. Experiences, learnings, mistakes, HUGE mistakes :-)&lt;br /&gt;&lt;br /&gt;For those of you who don't know us (shame on you :-D), we've both been in the software field for as long as we can remember. And this is frequently our after-hours topic of discussion. Which in effect means, we do not have 'after-hours'!!&lt;br /&gt;We both independently thought 'why not write them down for posterity'...and when we mentioned this idea, each of us said 'hey even I was thinking of doing that!'&lt;br /&gt;&lt;br /&gt;So here it is- our thoughts and feelings and passionate debates on the only thing worth talking about in our lives- technology!&lt;br /&gt;&lt;br /&gt;We hope you will like it, and read it frequently... bookmark it NOW!!! (shameless promotion)&lt;br /&gt;Please tell your friends about it (more shameless promotion), and praise us to the skies (the ultimate ;-))&lt;br /&gt;&lt;br /&gt;Do feel free to comment, disagree, argue, offer ideas and your own experience...[we can always delete the comments we don't agree with........joking ;-)]&lt;br /&gt;&lt;br /&gt;Here's to technology and our thoughts about it...cheers!!! (hic hic)&lt;br /&gt;&lt;br /&gt;PS: While we would prefer you to leave comments on the blog itself to ensure our everlasting fame, you can also email us at thought dot bytes at gmail dot com&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: georgia;font-size:100%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-family: georgia;font-size:100%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8978951075400478206-2765982810154160387?l=thought-bytes.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TJE042GkKa658L9uGF5fL5TcveA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TJE042GkKa658L9uGF5fL5TcveA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TJE042GkKa658L9uGF5fL5TcveA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TJE042GkKa658L9uGF5fL5TcveA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ThoughtBytes/~4/NnbCRFOJ2Cc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://thought-bytes.blogspot.com/feeds/2765982810154160387/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8978951075400478206&amp;postID=2765982810154160387" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2765982810154160387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8978951075400478206/posts/default/2765982810154160387?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ThoughtBytes/~3/NnbCRFOJ2Cc/welcome.html" title="Welcome!" /><author><name>Aldrin &amp;amp; Luanne Misquitta</name><uri>http://www.blogger.com/profile/08863619142582168911</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp0.blogger.com/_MAfUGsnuVtw/RdQzDsckKJI/AAAAAAAAAAM/y5ihcnTqjpI/s320/thought_bytes.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://thought-bytes.blogspot.com/2007/02/welcome.html</feedburner:origLink></entry></feed>

