<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6734864162420840501</id><updated>2012-01-19T02:10:47.548-08:00</updated><category term='unit testing'/><category term='terracotta'/><category term='ehcache'/><title type='text'>Find of the Day</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-581733746434799015</id><published>2011-11-04T04:49:00.001-07:00</published><updated>2011-11-04T04:49:49.121-07:00</updated><title type='text'>Changing data directories of mysql in Ubuntu 11.04</title><content type='html'>&lt;p&gt;This article lets you change the mysql data directory to a new directory. We might want to do this to move the data folder to a different paritition where there's enough size to hold the data.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 1 : Stop the My Sql server.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Before we do any changes to the data directory we should stop the mysql server if it is already running.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;service mysql stop&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 2: Create the new data directory&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Create the new folder where you want to migrate the data folder to..&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;mkdir -p /new_partition/mysql&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 3: Change ownership of the new data directory&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;chown -R mysql:mysql /new_partition/mysql &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 4: Change the /etc/mysql/my.cnf file&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Open the /etc/mysql/my.cnf file using root access&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;sudo vi /etc/mysql/my.cnf&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Find the attribute with name &lt;span style="font-family: terminal,monaco;"&gt;datadir&lt;/span&gt; and replace its value to the new folder that we created in step 2&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;datadir = /new_partition/mysql&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 5: Copy the required databases to the new data directory&lt;/span&gt;&lt;/p&gt;&lt;p&gt;For example we want to migrate databases of phpmyadmin, you'll find a folder inside the &lt;span style="font-family: terminal,monaco;"&gt;/var/lib/mysql/&lt;/span&gt; folder. Copy it to the new partition directory.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;cp -r -p /var/lib/mysql/phpmyadmin /new_partition/mysql/&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;-p&lt;/span&gt; option would ensure that the ownerships are preserved.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 6: Modifying the apparmour property file /etc/apparmour.d/usr.sbin.mysqld&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Edit the usr.sbin.mysqld file inside /etc/apparmour.d/ folder and add following lines.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;/new_partition/mysq&lt;/span&gt;l/ r,&lt;br /&gt;&lt;span style="font-family: terminal,monaco;"&gt;/new_partition/mysql/&lt;/span&gt;** &lt;span style="font-family: terminal,monaco;"&gt;rwk&lt;/span&gt;,&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 7:&amp;nbsp; Restart App Armour &lt;/span&gt;&lt;/p&gt;&lt;p&gt;Restart apparmour in ubuntu with following command&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;sudo /etc/init.d/apparmour restart&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: large;"&gt;Step 8: Start MySql server&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: terminal,monaco;"&gt;service mysql start&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Check the error logs of mysql to see if the server has started fine or not. If you still see errors, then its most propably due to the permission issues in the new partition.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-581733746434799015?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/581733746434799015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=581733746434799015' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/581733746434799015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/581733746434799015'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2011/11/changing-data-directories-of-mysql-in.html' title='Changing data directories of mysql in Ubuntu 11.04'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-2809714323423647019</id><published>2009-10-14T06:37:00.000-07:00</published><updated>2009-10-14T22:43:03.545-07:00</updated><title type='text'>Java API for accessing Bugzilla</title><content type='html'>It just happened one day that my manager came to me and said we should automate our build process to make our life easier. It is then we started analyzing what exactly we want to automate among the zillion steps we do as part of the build process.&lt;br /&gt;&lt;br /&gt;One of steps is that we should be able to programatically access bugzilla and do some operations with the bug. Probably search for a list of bugs and verify the comments etc.. It turns out Bugzilla only supports XML-RPC and JSON-RPC protocols, where as XML-RPC being the stable one we went ahead and picked it.&lt;br /&gt;&lt;br /&gt;Since its the first time I'm going to use XML-RPC, I did some research on net about it and found that there's one cool API framework available from apache, its called '&lt;a href="http://ws.apache.org/xmlrpc/index.html"&gt;The Apache XML-RPC client&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;Just like any other API from apache, it came with loads of documentation and Javadocs.., a big thanks to those geeks for maintaining code.&lt;br /&gt;&lt;br /&gt;Coming back to problem at hand, All I wanted to do was to access bugzilla and login and do some operations in it with a list of bugs.  Following is the code snippet that I simply copied and modified from the apache's examples for XML-RPC client.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import java.net.MalformedURLException;&lt;br /&gt;import java.net.URL;&lt;br /&gt;&lt;br /&gt;import org.apache.xmlrpc.XmlRpcException;&lt;br /&gt;import org.apache.xmlrpc.client.XmlRpcClient;&lt;br /&gt;import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class Bugzilla {&lt;br /&gt;public static void main(String[] args) throws MalformedURLException, XmlRpcException {&lt;br /&gt; XmlRpcClientConfigImpl  config = new XmlRpcClientConfigImpl();&lt;br /&gt; config.setServerURL(new URL("http://bug-tracker.yyyy.com/Bugzilla/xmlrpc.cgi"));&lt;br /&gt;&lt;br /&gt; XmlRpcClient client = new XmlRpcClient();&lt;br /&gt; client.setConfig(config);&lt;br /&gt;&lt;br /&gt; Object[] params = new Object[]{"xxx@yyy.com", "password"};&lt;br /&gt;&lt;br /&gt; Object result = client.execute("User.login", params);&lt;br /&gt; System.out.println("Result = "+result);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When i ran this, it started throwing this exception..&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Exception in thread "main" java.lang.ClassCastException: java.lang.String&lt;br /&gt;at org.apache.xmlrpc.parser.XmlRpcResponseParser.addResult(XmlRpcResponseParser.java:61)&lt;br /&gt;at org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endValueTag(RecursiveTypeParserImpl.java:78)&lt;br /&gt;at org.apache.xmlrpc.parser.XmlRpcResponseParser.endElement(XmlRpcResponseParser.java:186)&lt;br /&gt;at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:633)&lt;br /&gt;at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanEndElement(XMLNSDocumentScannerImpl.java:719)&lt;br /&gt;at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1685)&lt;br /&gt;at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:368)&lt;br /&gt;at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:834)&lt;br /&gt;at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)&lt;br /&gt;at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)&lt;br /&gt;at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1242)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:186)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:156)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:115)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:69)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:56)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:167)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:137)&lt;br /&gt;at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:126)&lt;br /&gt;at Bugzilla.main(Bugzilla.java:21)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;The error message is confusing and doesn't really point me to the root cause.&lt;br /&gt;&lt;br /&gt;After an hour of search, found the mystery with the error above. It turns out Bugzilla follows certain rules with the XML-RPC implementation.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;All the parameters that are passed to Bugzilla must be a named parameter.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;All the parameters are treated as 'struct' tag by Bugzilla, so we must pass all the parameters as keys and values in a HashMap.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Following is modified code...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import java.net.MalformedURLException;&lt;br /&gt;import java.net.URL;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;import org.apache.xmlrpc.XmlRpcException;&lt;br /&gt;import org.apache.xmlrpc.client.XmlRpcClient;&lt;br /&gt;import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class Bugzilla {&lt;br /&gt;public static void main(String[] args) throws MalformedURLException, XmlRpcException {&lt;br /&gt; XmlRpcClientConfigImpl  config = new XmlRpcClientConfigImpl();&lt;br /&gt; config.setServerURL(new URL("http://bug-tracker.yyyy.com/Bugzilla/xmlrpc.cgi"));&lt;br /&gt;&lt;br /&gt; XmlRpcClient client = new XmlRpcClient();&lt;br /&gt; client.setConfig(config);&lt;br /&gt;&lt;br /&gt; Map map = new HashMap();&lt;br /&gt; map.put("login","xxxx@yyyy.com");&lt;br /&gt; map.put("password","password");&lt;br /&gt;&lt;br /&gt; Map result = (Map) client.execute("User.login",  new Object[]{map});&lt;br /&gt; System.out.println("Result = "+result);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The response from bugzilla is again a Map object, so I had to cast it to make sure I can access elements in it.&lt;br /&gt;&lt;br /&gt;Now comes the next hurdle. Bugzilla's XML-RPC apis also assume that the client maintains the session with the server using cookies. The problem now is to figure out a way to do that with the apache XML-RPC client APIs. I'm going to write about it in my next blog post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-2809714323423647019?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/2809714323423647019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=2809714323423647019' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2809714323423647019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2809714323423647019'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/10/java-api-for-accessing-bugzilla.html' title='Java API for accessing Bugzilla'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-8104109617988131086</id><published>2009-09-04T03:26:00.000-07:00</published><updated>2009-09-04T03:49:05.799-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ehcache'/><title type='text'>The semantics of Flushing in Ehcache</title><content type='html'>When I was going through the ehcache user manual, I was a little confused about a 'flush' and a 'shutdown' of Ehcache. Of course, the names of these methods suggests their purpose in a perfectly clear way. But I never really paid any attention towards the inner workings of these methods.&lt;br /&gt;&lt;br /&gt;I always thought if I can flush each and every cache in my manager class before I shutdown its equivalent to calling a shutdown method on it. I'm talking about caches with basic functionalities ( with no bootstraps, no loaders etc.. so sending shutdown hook to all these (empty)listeners doesn't matter ). But, I was proved wrong. Here's the reason ...&lt;br /&gt;&lt;br /&gt;Following code does a very simple task. It reads all the elements from one ehcache and transfers all its element to a new cache and tries to persist the items to diskstore before termination.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import net.sf.ehcache.Element&lt;br /&gt;import net.sf.ehcache.CacheManager&lt;br /&gt;import net.sf.ehcache.Cache&lt;br /&gt;&lt;br /&gt;def cachemgr = new CacheManager("D:/mPortal/workspace_new_cvs_structure/EhCacheDemo/config/change_listener_cache.xml")&lt;br /&gt;def deltacache = cachemgr.getCache("deltaCache")&lt;br /&gt;&lt;br /&gt;def deltaclone = new Cache("deltaCacheClone", 10000,null, true,cachemgr.getDiskStorePath(), true, 120,120,true, 120,null)&lt;br /&gt;cachemgr.addCache(deltaclone)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;println "Migration about to begin"&lt;br /&gt;println "Size of the original cache : ${deltacache.getSize()}"&lt;br /&gt;println "Size of the clone : ${deltaclone.getSize()}"&lt;br /&gt;&lt;br /&gt;deltacache.getKeys().each{&lt;br /&gt;ele = deltacache.get(it)&lt;br /&gt;deltaclone.put(new Element (ele.getKey(),ele.getValue()))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;println "Size of the original cache after migration : ${deltacache.getSize()}"&lt;br /&gt;println "Size of the clone after migration : ${deltaclone.getSize()}"&lt;br /&gt;&lt;br /&gt;println "Migration successfully finished.."&lt;br /&gt;&lt;br /&gt;deltacache.flush()&lt;br /&gt;deltaclone.flush()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that I'm flushing all the caches I created/used in my program at the end.&lt;br /&gt;&lt;br /&gt;To my surprise, whenever I run this program again the 'deltaclone'  cache always initializes itself to zero. This puzzled me for quite sometime and finally forced me to revisit the source code of ehcache to understand the behavior.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 153, 0);"&gt;The Reason&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What I found is that the 'flush' operation was not a synchronous operation at all. it only signals the spool to flush it when it wakes again.  In my case, my VM didn't stop till this thread do its job.. it has killed it forcibly.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 153, 0); font-weight: bold;"&gt;How Shutdown Solves this problem ?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The shutdown method however, is very responsible and gracefully waits till the thread finishes its execution. Following is the snippet which can explain this behavior...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;//set the write index flag. Ignored if not persistent&lt;br /&gt;         flush();&lt;br /&gt;&lt;br /&gt;         //tell the spool thread to spool down. It will loop one last time if flush was caled.&lt;br /&gt;         spoolAndExpiryThreadActive = false;&lt;br /&gt;&lt;br /&gt;         //interrupt the spoolAndExpiryThread if it is waiting to run again to get it to run now&lt;br /&gt;         // Then wait for it to write&lt;br /&gt;         spoolAndExpiryThread.interrupt();&lt;br /&gt;         if (spoolAndExpiryThread != null) {&lt;br /&gt;             spoolAndExpiryThread.join();&lt;br /&gt;         }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is the snippet from the DiskStore's dispose method. Thanks to the documentation, the code is pretty much self explainable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 153, 0); font-weight: bold;"&gt;The fix&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, the proper way to fix my program is very simple.. by adding the shutdown() method call at the end.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import net.sf.ehcache.Element&lt;br /&gt;import net.sf.ehcache.CacheManager&lt;br /&gt;import net.sf.ehcache.Cache&lt;br /&gt;&lt;br /&gt;def cachemgr = new CacheManager("D:/mPortal/workspace_new_cvs_structure/EhCacheDemo/config/change_listener_cache.xml")&lt;br /&gt;def deltacache = cachemgr.getCache("deltaCache")&lt;br /&gt;&lt;br /&gt;def deltaclone = new Cache("deltaCacheClone", 10000,null, true,cachemgr.getDiskStorePath(), true, 120,120,true, 120,null)&lt;br /&gt;cachemgr.addCache(deltaclone)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;println "Migration about to begin"&lt;br /&gt;println "Size of the original cache : ${deltacache.getSize()}"&lt;br /&gt;println "Size of the clone : ${deltaclone.getSize()}"&lt;br /&gt;&lt;br /&gt;deltacache.getKeys().each{&lt;br /&gt;ele = deltacache.get(it)&lt;br /&gt;deltaclone.put(new Element (ele.getKey(),ele.getValue()))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;println "Size of the original cache after migration : ${deltacache.getSize()}"&lt;br /&gt;println "Size of the clone after migration : ${deltaclone.getSize()}"&lt;br /&gt;&lt;br /&gt;println "Migration successfully finished.."&lt;br /&gt;&lt;br /&gt;deltacache.flush() // Redundant&lt;br /&gt;deltaclone.flush() // Redundant&lt;br /&gt;&lt;br /&gt;cachemgr.shutdown()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The additional flush operations are totally redundant, the program works even if you remove those statements..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-8104109617988131086?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/8104109617988131086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=8104109617988131086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/8104109617988131086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/8104109617988131086'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/09/semantics-of-flushing-in-ehcache.html' title='The semantics of Flushing in Ehcache'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-5578266110740319156</id><published>2009-09-02T23:29:00.000-07:00</published><updated>2009-09-02T23:40:13.414-07:00</updated><title type='text'>How to download response, even if you get a HTTP 500</title><content type='html'>When we normally connect to a HTTP URL from within our java code, we tend to check only the status code and proceed based on its value. We'll be interested in handling only the HTTP SUCCESS code 200, but for other errors you'll simply want to report it as a 'Generic error'&lt;br /&gt;&lt;br /&gt;But there're times, when you want to see what exactly does the server returned for our request for diagnostics purpose. For example,  a monitoring server may not just want to know what error code the server has returned, but also want details about what exactly happened at the server side. I've written simple groovy script which uses the commons-http client and core modules from Apache to do this task for me.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;&lt;br /&gt;import org.apache.commons.httpclient.HttpClient&lt;br /&gt;import org.apache.commons.httpclient.methods.GetMethod&lt;br /&gt;&lt;br /&gt;client = new HttpClient()&lt;br /&gt;method = new GetMethod("http://10.11.12.48:8004/monitor")&lt;br /&gt;def statusCode  = client.executeMethod(method)&lt;br /&gt;&lt;br /&gt;println "Status code is : ${statusCode}"&lt;br /&gt;&lt;br /&gt;//Read the response body.&lt;br /&gt;byte[] responseBody = method.getResponseBody();&lt;br /&gt;&lt;br /&gt;// Deal with the response.&lt;br /&gt;// Use caution: ensure correct character encoding and is not binary data&lt;br /&gt;println(new String(responseBody));&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;You should keep following files in the class path to run this program successfully.&lt;br /&gt;&lt;/http&gt;&lt;ol&gt;&lt;li&gt;commons-httpclient.jar&lt;/li&gt;&lt;li&gt;commons-codec.jar&lt;/li&gt;&lt;li&gt;commons-logging.jar&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;And ofcourse, you can change the URL to which ever value you want to test out other error codes.&lt;br /&gt;&lt;http&gt;&lt;br /&gt;&lt;/http&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-5578266110740319156?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/5578266110740319156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=5578266110740319156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5578266110740319156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5578266110740319156'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/09/how-to-download-response-even-if-you.html' title='How to download response, even if you get a HTTP 500'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-5574409300898672145</id><published>2009-09-02T06:23:00.000-07:00</published><updated>2009-09-02T06:44:53.807-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ehcache'/><title type='text'>Most wanted features in Ehcache</title><content type='html'>In our company, we finally decided to make a move forward and implement ehcache as our caching provider.  The integration has provided me with great challenges, it forced me to learn quite a bit about ehcache before we took the decision.&lt;br /&gt;&lt;br /&gt;Ehcache, as an API is well tested and perfectly capable of holding up to larger loads. But what's troubling me now is to monitor the caching activity that goes under the hood in ehcache. In most of the normal cases we don't have to worry about what's happening inside Ehcache, but there're times where we want to know very specific things like...&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How far has the replication has reached ? &lt;/li&gt;&lt;li&gt;Has all the servers ( copies of ehcaches) in the cluster acknowledged the replication event successfully ?&lt;/li&gt;&lt;li&gt;How do we identify the replication failures ?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Ehcache currently doesn't support event handling at this granular level. Thanks to its extensible architecture, we can still write our own implementation classes to introduce this level of granularity. But, as you know in this world of open source every piece of code you write is worthless if some super-smart guy has already done it before.&lt;br /&gt;&lt;br /&gt;One other thing I got stuck is about maintaining the coherency of data between the database and the cache.&lt;br /&gt;&lt;br /&gt;The caching solution what we're looking at requires that the database should be 'master' of all the caches, we must make sure the database has all the latest information and at the same time the data must be available up-to-date to all the runtime components which take the hits from users in real time. &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At any given time, how do I know that the data cached in Ehcache is consistent with the database or not ?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Has anyone encountered this kind of situation before ? How were you able to handle it ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-5574409300898672145?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/5574409300898672145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=5574409300898672145' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5574409300898672145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5574409300898672145'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/09/most-wanted-features-in-ehcache.html' title='Most wanted features in Ehcache'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-2523480055241509376</id><published>2009-08-31T06:51:00.000-07:00</published><updated>2009-08-31T07:06:38.468-07:00</updated><title type='text'>Syntax highlighting of blogger entries</title><content type='html'>When I was first introduced to blogging, I came across hundreds of blogs and after getting motivation from them I started my own blog. But after all this time, the only thing that worried me was that my blog doesn't look as cool and trendy( in looks ) as many other blogs out there.  I finally found the answers...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Themes and Layouts.&lt;/li&gt;&lt;li&gt;Third party Scripts.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 102, 0); font-weight: bold;"&gt;Themes and Layouts &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Blogger allows you to customize the theme and layout of your blog using a plan ( almost ) html based template. I always wondered, it'd take me light years to come up with my own template. But luckily I don't have to put myself to such a torment after all; I found that there're thousands of templates that are available out there waiting for me to discover. I found &lt;a href="http://www.pyzam.com/bloggertemplates"&gt;this &lt;/a&gt;site very useful, it has really cool themes categorized into several categories. Now, I have limitless number of templates to choose from depending on my mood...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 102, 0);"&gt;Third party Scripts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since I can edit the template XML to my wish, I also started searching for code syntax highlighter to decorate my code snippets in my blog entries. I used to miss them alot as they certainly make a difference in presenting the code snippets. There's however, &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter"&gt;an open source solution&lt;/a&gt; available, to help us out here. Follow the guidelines in &lt;a href="http://mlawire.blogspot.com/2009/07/blogger-syntax-highlighting.html"&gt;this &lt;/a&gt;blog and you'll have your personal code highlighter in no time.&lt;br /&gt;&lt;br /&gt;These tools definitely going to help me continue blogging with more ease and elegance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-2523480055241509376?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/2523480055241509376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=2523480055241509376' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2523480055241509376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2523480055241509376'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/08/syntax-highlighting-of-blogger-entries.html' title='Syntax highlighting of blogger entries'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-6241372275548820575</id><published>2009-06-29T01:45:00.000-07:00</published><updated>2009-08-31T06:41:42.937-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='terracotta'/><title type='text'>Experimenting Terracotta</title><content type='html'>Recently, I've been looking into several caching solutions for our product.  After a little research we concluded that we use ehcache for our caching needs. But given the fact that we have a cluster of servers communicating with each others there is also a need for searching a clustering solution as well.&lt;br /&gt;&lt;br /&gt;Luckily, Ehcache also supports clustering in its own way using either&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;RMI&lt;br /&gt;&lt;/li&gt;&lt;li&gt;JMS&lt;/li&gt;&lt;li&gt;JGroups&lt;/li&gt;&lt;/ol&gt;All these methods work on the concept called replication. Ehcache keeps a copy in each of the cache node and replicates each and every mutable cache operation on every node in the cluster. Even though this solves the cluster problem to some extent, its in-efficient in a sense that I have a copy &lt;span style="font-family:georgia;"&gt;of &lt;/span&gt;cache everywhere and I've to figure out how to keep things consistent and at the same time scalable to any sizes of caches.&lt;br /&gt;&lt;br /&gt;Alternatives for the approach mentioned above were are also available.. see &lt;a href="http://gregluck.com/blog/archives/2008/08/_the_restful_eh.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;However, what I was looking for is a true clustered solution where a single copy of cache is made visible to all the nodes in the cluster as a single cache and at the same time I should be able to scale the cache to whichever size I want at runtime.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.terracotta.org/"&gt;Terracotta &lt;/a&gt;is the answer to this question.&lt;br /&gt;&lt;br /&gt;The installation worked like a breeze with absolutely no issues on windows. But I had to download the generic tar.gz file instead of a installer jar file for installing it in solaris.&lt;br /&gt;&lt;br /&gt;I've used "The definitive Guide to Terracotta" book as a guide for my quest and I'd recommend everyone to read this book for a better understanding of how terracotta works internally. You can read it online ( a limited version ofcourse ) at &lt;a href="http://books.google.com/books?id=HhvDpoLaGCoC&amp;amp;lpg=PR1&amp;amp;dq=terracotta&amp;amp;pg=PR1"&gt;google books&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The book has one HelloClusteredWorld example in it which explains the basic working of Terracotta using a simple java program. It works in the strightforward way and so I don't want to mention it here again. I want to show another experiment that I conducted my own using the ehcache integration module ( the &lt;a href="http://forge.terracotta.org/releases/projects/tim-ehcache/"&gt;ehcache TIM&lt;/a&gt; for Terracotta ) .&lt;br /&gt;&lt;br /&gt;Following is the sample groovy program that I used for testing this.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import net.sf.ehcache.Element&lt;br /&gt;import java.io.InputStreamReader&lt;br /&gt;import net.sf.ehcache.CacheManager&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;url = getClass().getResource("ehcache-config.xml");&lt;br /&gt;cacheMgr = new CacheManager(url)&lt;br /&gt;def choice = "Y"&lt;br /&gt;cache = cacheMgr.getCache("userCache");&lt;br /&gt;inreader=new InputStreamReader(System.in)&lt;br /&gt;&lt;br /&gt;println "Current cache size is : ${cache.getSize()}"&lt;br /&gt;&lt;br /&gt;while ( true ){&lt;br /&gt;print " what do you want to do ? "&lt;br /&gt;choice = new InputStreamReader(System.in).readLine()&lt;br /&gt;switch ( choice ){&lt;br /&gt;case "flush":&lt;br /&gt;  println "Flushing the cache."&lt;br /&gt;  cacheMgr.flush()&lt;br /&gt;  break;&lt;br /&gt;case "add":&lt;br /&gt;  print "Enter the key element you want to add : "&lt;br /&gt;  key = new InputStreamReader(System.in).readLine()&lt;br /&gt;  print "Enter the value element you want to add : "&lt;br /&gt;  val = new InputStreamReader(System.in).readLine()&lt;br /&gt;  cache.put(new Element(key, val))&lt;br /&gt;  break;&lt;br /&gt;case "remove":&lt;br /&gt;  print "Enter key of the element to remove : "&lt;br /&gt;  key = inreader.readLine()&lt;br /&gt;  cache.remove(key)&lt;br /&gt;case "rall":&lt;br /&gt;  print "Removing everything !"&lt;br /&gt;  cache.removeAll()&lt;br /&gt;  break;&lt;br /&gt;case "size":&lt;br /&gt;  print "Current cache size is ${cache.getSize()}"&lt;br /&gt;  break;&lt;br /&gt;default:&lt;br /&gt;  println "I don't understand what you're saying ? "&lt;br /&gt;  System.exit(0)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The purpose of this program is simple, It initializes a ehcache using its cache manager and tries to do CRUD operations in it. Without clustering this program works in a strightforward way waiting for user's input to do the corresponding action.&lt;br /&gt;&lt;br /&gt;Following is the Ehcache XML to use...&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:noNamespaceSchemaLocation="ehcache.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;defaultCache&lt;br /&gt;    maxElementsInMemory="10000"&lt;br /&gt;    eternal="false"&lt;br /&gt;    timeToIdleSeconds="120"&lt;br /&gt;    timeToLiveSeconds="120"&lt;br /&gt;    overflowToDisk="true"&lt;br /&gt;    diskSpoolBufferSizeMB="30"&lt;br /&gt;    maxElementsOnDisk="10000000"&lt;br /&gt;    diskPersistent="false"&lt;br /&gt;    diskExpiryThreadIntervalSeconds="120"&lt;br /&gt;    memoryStoreEvictionPolicy="LRU"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    /&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;cache name="userCache"&lt;br /&gt;   maxElementsInMemory="10"&lt;br /&gt;   eternal="true"&lt;br /&gt;   overflowToDisk="true"&lt;br /&gt;   diskSpoolBufferSizeMB="20"&lt;br /&gt;   timeToIdleSeconds="300"&lt;br /&gt;   timeToLiveSeconds="600"&lt;br /&gt;   diskPersistent="false"&lt;br /&gt;   memoryStoreEvictionPolicy="LFU"&amp;gt;&lt;br /&gt;&amp;lt;/cache&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/ehcache&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, I tried to convert this program into a cluster-aware program using terracotta. I used following tc-config.xml file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;&lt;br /&gt;All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;This is a Terracotta configuration file that has been pre-configured&lt;br /&gt;for use with DSO.  All classes are included for instrumentation,&lt;br /&gt;and all instrumented methods are write locked.&lt;br /&gt;&lt;br /&gt;For more information, please see the product documentation.&lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;tc:tc-config xmlns:tc="http://www.terracotta.org/config"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-4.xsd"&amp;gt;&lt;br /&gt;&amp;lt;servers&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- Tell DSO where the Terracotta server can be found. --&amp;gt;&lt;br /&gt; &amp;lt;server host="localhost"&amp;gt;&lt;br /&gt;  &amp;lt;data&amp;gt;%(user.home)/terracotta/server-data&amp;lt;/data&amp;gt;&lt;br /&gt;  &amp;lt;logs&amp;gt;%(user.home)/terracotta/server-logs&amp;lt;/logs&amp;gt;&lt;br /&gt;  &amp;lt;dso&amp;gt;&lt;br /&gt;   &amp;lt;persistence&amp;gt;&lt;br /&gt;    &amp;lt;mode&amp;gt;permanent-store&amp;lt;/mode&amp;gt;&lt;br /&gt;   &amp;lt;/persistence&amp;gt;&lt;br /&gt;  &amp;lt;/dso&amp;gt;&lt;br /&gt; &amp;lt;/server&amp;gt;&lt;br /&gt;&amp;lt;/servers&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Tell DSO where to put the generated client logs --&amp;gt;&lt;br /&gt;&amp;lt;clients&amp;gt;&lt;br /&gt; &amp;lt;logs&amp;gt;%(user.home)/terracotta/client-logs&amp;lt;/logs&amp;gt;&lt;br /&gt; &amp;lt;modules&amp;gt;&lt;br /&gt;  &amp;lt;module name="tim-ehcache-1.4.1" version="1.3.2"/&amp;gt;&lt;br /&gt; &amp;lt;/modules&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/clients&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;application&amp;gt;&lt;br /&gt; &amp;lt;dso&amp;gt;&lt;br /&gt;  &amp;lt;roots&amp;gt;&lt;br /&gt;  &lt;br /&gt;   &amp;lt;root&amp;gt;&lt;br /&gt;    &amp;lt;field-name&amp;gt;SubscriberCreator.cacheMgr&amp;lt;/field-name&amp;gt;&lt;br /&gt;   &amp;lt;/root&amp;gt;&lt;br /&gt;   &amp;lt;root&amp;gt;&lt;br /&gt;    &amp;lt;field-name&amp;gt;SubscriberCreator.cache&amp;lt;/field-name&amp;gt;&lt;br /&gt;   &amp;lt;/root&amp;gt;&lt;br /&gt;  &amp;lt;/roots&amp;gt;&lt;br /&gt;  &amp;lt;!-- Start by including just the classes you expect to get added to the shared&lt;br /&gt;      graph.  These typically include domain classes and shared data structures.&lt;br /&gt;      If you miss classes, Terracotta will throw NonPortableOjectExceptions&lt;br /&gt;      telling you more about what needs to be added. --&amp;gt;&lt;br /&gt;  &amp;lt;instrumented-classes&amp;gt;&lt;br /&gt;   &amp;lt;include&amp;gt;&lt;br /&gt;    &amp;lt;class-expression&amp;gt;SubscriberCreator&amp;lt;/class-expression&amp;gt;&lt;br /&gt;   &amp;lt;/include&amp;gt;&lt;br /&gt;  &amp;lt;/instrumented-classes&amp;gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;/dso&amp;gt;&lt;br /&gt;&amp;lt;/application&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/tc:tc-config&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;But when I ran this program, i got this error.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Starting Terracotta client...&lt;br /&gt;2009-07-01 12:23:44,758 INFO - Terracotta 3.0.1, as of 20090514-130552 (Revision 12704 by cruise@su1&lt;br /&gt;0mo5 from 3.0)&lt;br /&gt;2009-07-01 12:23:45,476 INFO - Configuration loaded from the file at 'd:\mPortal\Workspace_research\&lt;br /&gt;HelloClusteredWorld\tc-config.xml'.&lt;br /&gt;2009-07-01 12:23:45,711 INFO - Log file: 'C:\Documents and Settings\Admin\terracotta\client-logs\ter&lt;br /&gt;racotta-client.log'.&lt;br /&gt;2009-07-01 12:23:49,320 INFO - Connection successfully established to server at 127.0.0.1:9510&lt;br /&gt;2009-07-01 12:23:49,570 WARN - The root expression 'SubscriberCreator.cacheMgr' meant for the class&lt;br /&gt;'SubscriberCreator' has no effect, make sure that it is a valid expression and that it is spelled co&lt;br /&gt;rrectly.&lt;br /&gt;2009-07-01 12:23:49,570 WARN - The root expression 'SubscriberCreator.cache' meant for the class 'Su&lt;br /&gt;bscriberCreator' has no effect, make sure that it is a valid expression and that it is spelled corre&lt;br /&gt;ctly.&lt;br /&gt;com.tc.exception.TCNonPortableObjectError:&lt;br /&gt;*******************************************************************************&lt;br /&gt;Attempt to share an instance of a non-portable class by assigning it to a root. This unshareable&lt;br /&gt;class is a JVM- or host machine-specific resource. Please ensure that instances of this class&lt;br /&gt;don't enter the shared object graph.&lt;br /&gt;&lt;br /&gt;For more information on this issue, please visit our Troubleshooting Guide at:&lt;br /&gt;http://terracotta.org/kit/troubleshooting&lt;br /&gt;&lt;br /&gt;Thread                : main&lt;br /&gt;JVM ID                : VM(22)&lt;br /&gt;Non-portable root name: ALL_CACHE_MANAGERS&lt;br /&gt;Unshareable class     : java.util.concurrent.CopyOnWriteArrayList&lt;br /&gt;&lt;br /&gt;Action to take:&lt;br /&gt;&lt;br /&gt;1) Change your application code&lt;br /&gt;* Ensure that no instances or subclass instances of java.util.concurrent.CopyOnWriteArrayList&lt;br /&gt;are assigned to the DSO root: ALL_CACHE_MANAGERS&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*******************************************************************************&lt;br /&gt;&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.throwNonPortableException(ClientObjectManagerImpl.java:786)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.checkPortabilityOfRoot(ClientObjectManagerImpl.java:690)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:656)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:642)&lt;br /&gt;  at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:321)&lt;br /&gt;  at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:300)&lt;br /&gt;  at com.tc.object.bytecode.ManagerUtil.lookupOrCreateRoot(ManagerUtil.java:96)&lt;br /&gt;  at net.sf.ehcache.CacheManager.__tc_setALL_CACHE_MANAGERS(CacheManager.java)&lt;br /&gt;  at net.sf.ehcache.CacheManager.&lt;clinit&gt;(CacheManager.java:61)&lt;br /&gt;  at java.lang.Class.forName0(Native Method)&lt;br /&gt;  at java.lang.Class.forName(Class.java:164)&lt;br /&gt;  at SubscriberCreator.class$(SubscriberCreator.groovy)&lt;br /&gt;  at SubscriberCreator.$get$$class$net$sf$ehcache$CacheManager(SubscriberCreator.groovy)&lt;br /&gt;  at SubscriberCreator.run(SubscriberCreator.groovy:9)&lt;br /&gt;  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br /&gt;  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)&lt;br /&gt;  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)&lt;br /&gt;  at java.lang.reflect.Method.invoke(Method.java:585)&lt;br /&gt;  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)&lt;br /&gt;  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)&lt;br /&gt;  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1062)&lt;br /&gt;  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:893)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:744)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:727)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:383)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129)&lt;br /&gt;  at SubscriberCreator.main(SubscriberCreator.groovy)&lt;br /&gt;Exception in thread "main" com.tc.exception.TCNonPortableObjectError:&lt;br /&gt;*******************************************************************************&lt;br /&gt;Attempt to share an instance of a non-portable class by assigning it to a root. This unshareable&lt;br /&gt;class is a JVM- or host machine-specific resource. Please ensure that instances of this class&lt;br /&gt;don't enter the shared object graph.&lt;br /&gt;&lt;br /&gt;For more information on this issue, please visit our Troubleshooting Guide at:&lt;br /&gt;http://terracotta.org/kit/troubleshooting&lt;br /&gt;&lt;br /&gt;Thread                : main&lt;br /&gt;JVM ID                : VM(22)&lt;br /&gt;Non-portable root name: ALL_CACHE_MANAGERS&lt;br /&gt;Unshareable class     : java.util.concurrent.CopyOnWriteArrayList&lt;br /&gt;&lt;br /&gt;Action to take:&lt;br /&gt;&lt;br /&gt;1) Change your application code&lt;br /&gt;* Ensure that no instances or subclass instances of java.util.concurrent.CopyOnWriteArrayList&lt;br /&gt;are assigned to the DSO root: ALL_CACHE_MANAGERS&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*******************************************************************************&lt;br /&gt;&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.throwNonPortableException(ClientObjectManagerImpl.java:786)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.checkPortabilityOfRoot(ClientObjectManagerImpl.java:690)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:656)&lt;br /&gt;  at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:642)&lt;br /&gt;  at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:321)&lt;br /&gt;  at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:300)&lt;br /&gt;  at com.tc.object.bytecode.ManagerUtil.lookupOrCreateRoot(ManagerUtil.java:96)&lt;br /&gt;  at net.sf.ehcache.CacheManager.__tc_setALL_CACHE_MANAGERS(CacheManager.java)&lt;br /&gt;  at net.sf.ehcache.CacheManager.&lt;clinit&gt;(CacheManager.java:61)&lt;br /&gt;  at java.lang.Class.forName0(Native Method)&lt;br /&gt;  at java.lang.Class.forName(Class.java:164)&lt;br /&gt;  at SubscriberCreator.class$(SubscriberCreator.groovy)&lt;br /&gt;  at SubscriberCreator.$get$$class$net$sf$ehcache$CacheManager(SubscriberCreator.groovy)&lt;br /&gt;  at SubscriberCreator.run(SubscriberCreator.groovy:9)&lt;br /&gt;  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br /&gt;  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)&lt;br /&gt;  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)&lt;br /&gt;  at java.lang.reflect.Method.invoke(Method.java:585)&lt;br /&gt;  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)&lt;br /&gt;  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)&lt;br /&gt;  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1062)&lt;br /&gt;  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:893)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:744)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:727)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:383)&lt;br /&gt;  at org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)&lt;br /&gt;  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129)&lt;br /&gt;  at SubscriberCreator.main(SubscriberCreator.groovy)&lt;br /&gt;&lt;br /&gt;&lt;/clinit&gt;&lt;/clinit&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Okay, so there're two errors in the trace I pasted above. The first one is kind of a warning message from terracotta that it is unable to identify the member variables I declared in the XML file in the SubscriberCreator class file.&lt;br /&gt;&lt;br /&gt;2009-07-01 12:23:49,570 WARN - The &lt;span style="font-weight: bold;"&gt;root expression 'SubscriberCreator.cacheMgr' meant for the class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;'SubscriberCreator' has no effect&lt;/span&gt;, make sure that it is a valid expression and that it is spelled correctly.&lt;br /&gt;2009-07-01 12:23:49,570 WARN - &lt;span style="font-weight: bold;"&gt;The root expression 'SubscriberCreator.cache' meant for the class 'Su&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;bscriberCreator' has no effect&lt;/span&gt;, make sure that it is a valid expression and that it is spelled correctly.&lt;br /&gt;&lt;br /&gt;The reason for this error is because the class file I used to launch the terracotta client was generated from a groovy program. When Groovy compiler compiles the groovy file it converts the fields that we declare in the class as properties inside the class. So, whatever member variables that we declare in the groovy file is not in fact a member variable but internally its represented as a key in a HashTable.&lt;br /&gt;&lt;br /&gt;Instead of worrying about fixing this, I just converted the groovy program into a java program and this problem has vanished since then. Following is the equivalent java program...&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.net.URL;&lt;br /&gt;&lt;br /&gt;import net.sf.ehcache.Cache;&lt;br /&gt;import net.sf.ehcache.CacheManager;&lt;br /&gt;import net.sf.ehcache.Element;&lt;br /&gt;&lt;br /&gt;public class SubscriberCreator {&lt;br /&gt;&lt;br /&gt;private URL url;&lt;br /&gt;private CacheManager cacheMgr;&lt;br /&gt;private Cache cache;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public SubscriberCreator() {&lt;br /&gt; url = getClass().getResource("ehcache-config.xml");&lt;br /&gt; cacheMgr = new CacheManager(url);&lt;br /&gt; cache = cacheMgr.getCache("userCache");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public static void main(String[] args) throws IOException {&lt;br /&gt;&lt;br /&gt; SubscriberCreator creator = new SubscriberCreator();&lt;br /&gt; System.out.println("Current cache size is : "+creator.cache.getSize());&lt;br /&gt;&lt;br /&gt; do {&lt;br /&gt;  System.out.println("\nWhat do you want to do ? \n\t 1) Add \n\t 2) remove \n\t 3) flush \n\t 4) clear cache \n\t 5) get \n\t 6) size");&lt;br /&gt;  System.out.print("Enter your choice : ");&lt;br /&gt;  String choice = new BufferedReader(new InputStreamReader(System.in)).readLine();&lt;br /&gt; &lt;br /&gt;  if ( choice == null ){&lt;br /&gt;   System.out.println (" Bye Bye ");&lt;br /&gt;   System.exit(0);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  int choiceint;&lt;br /&gt;  try {&lt;br /&gt;   choiceint = Integer.parseInt(choice);&lt;br /&gt;  } catch (NumberFormatException e) {&lt;br /&gt;   System.out.println("Bye bye ");&lt;br /&gt;   break;&lt;br /&gt;  }&lt;br /&gt;  String key;&lt;br /&gt;  String val;&lt;br /&gt;  switch (choiceint){&lt;br /&gt;  case 1:&lt;br /&gt;   System.out.print ("Enter the key element you want to add : ");&lt;br /&gt;    key = new BufferedReader(new InputStreamReader(System.in)).readLine();&lt;br /&gt;    System.out.print("Enter the value element you want to add : ");&lt;br /&gt;    val = new BufferedReader(new InputStreamReader(System.in)).readLine();&lt;br /&gt;    creator.cache.put(new Element(key, val));&lt;br /&gt;    break;&lt;br /&gt;  case 2:&lt;br /&gt;   System.out.print ("Enter the key element you want to remove : ");&lt;br /&gt;    key = new BufferedReader(new InputStreamReader(System.in)).readLine();&lt;br /&gt;    creator.cache.remove(key);&lt;br /&gt;    System.out.println("key '"+key+"' removed Successfully !");&lt;br /&gt;    break;&lt;br /&gt;  case 3:&lt;br /&gt;   System.out.println("Flushing the cache now !");&lt;br /&gt;   creator.cache.flush();&lt;br /&gt;   System.out.println("Flushed the cache successfully ");&lt;br /&gt;   break;&lt;br /&gt;  case 4:&lt;br /&gt;   System.out.println("Clearning the cache !");&lt;br /&gt;   creator.cache.removeAll();&lt;br /&gt;   System.out.println("Cleared the cache successfully ");&lt;br /&gt;   break;&lt;br /&gt;  case 5:&lt;br /&gt;   System.out.print ("Enter the key element you want to retrieve : ");&lt;br /&gt;    key = new BufferedReader(new InputStreamReader(System.in)).readLine();&lt;br /&gt;    System.out.println("Element requested is : "+creator.cache.get(key));&lt;br /&gt;    break;&lt;br /&gt;  case 6:&lt;br /&gt;   System.out.println ("Cache size is : "+creator.cache.getSize());&lt;br /&gt;    break;&lt;br /&gt;   default:&lt;br /&gt;    {&lt;br /&gt;     System.out.println("I don't understand your request..");&lt;br /&gt;     System.exit(0);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt; }while ( true );&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Coming to the next half of the problem, it complains about a JDK class called &lt;span style="font-weight: bold;"&gt;java.util.concurrent.CopyOnWriteArrayList&lt;/span&gt;. It appears that terracotta 3.1 or earlier versions of it doesn't have the ability to instrument all the classes in the java.util.concurrent package.&lt;br /&gt;&lt;br /&gt;I later realized that from ehcache 1.6 beta3 they have migrated to the JDK concurrent package from the third party concurrent package. So, I had to go down the ehcache release line and re-tried the same example with ehcache 1.5 stable release. It works like a charm !&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What did I learnt from this exercise ?  Terracotta is a well tested software , but there's definitely a learning curve involved in order to understand what to share/monitor/instrument etc. Without this the whole concept looks unclear and likely to confuse you than do any better.&lt;br /&gt;&lt;br /&gt;Here're the minimum requirements for the terracotta 3.1&lt;br /&gt;&lt;br /&gt;java version : JDK 1.5 +&lt;br /&gt;ehcache TIM version : 1.4.1 or 1.3 both works fine.&lt;br /&gt;ehcache core version : ehcache 1.5.x ( 1.6 is not yet supported, hope the new version of terracotta fixes these short comings )&lt;br /&gt;Operating systems : Windows XP or higher, Solaris ( I tested only on these machines, I see no reason it doesn't work on other operating systems. )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-6241372275548820575?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/6241372275548820575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=6241372275548820575' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6241372275548820575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6241372275548820575'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2009/06/experimenting-terracotta.html' title='Experimenting Terracotta'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-6085235223449070404</id><published>2008-03-16T05:54:00.000-07:00</published><updated>2008-03-16T06:30:12.453-07:00</updated><title type='text'>3 'fantastic' static code analysis tools for eclipse</title><content type='html'>&lt;p style="font-family: trebuchet ms;"&gt;Its always a hard task to review one's code to make sure it follows some pre-defined coding standards. The reason its hard is not because its difficult to do, but its because its often boring and repetitive task to do. Adhering to 'Coding standards' while we write a piece of code is undoubtedly a very important responsibility for a programmer. Sometimes its as good as testing our functionality to check if it actually works properly or not. &lt;/p&gt;&lt;span style="font-family:trebuchet ms;"&gt;There're are many advantages that come in as a bonus for writing code as per the 'Coding standards'.&lt;/span&gt;&lt;br /&gt;&lt;ul style="font-family: trebuchet ms;"&gt;&lt;li&gt;Our code looks beautiful and easy to understand&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Its very easy to introduce new people into the projects as they can understand the code quickly.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Its easy to modify the code for further changes.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family:trebuchet ms;"&gt;Writing code as per the coding standards is like 'testing' an application. Both the tasks share the same qualities...&lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: trebuchet ms;"&gt;&lt;li&gt;They both have pre-defined set of rules ( test cases ) that we should follow every time we want to perform the task&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Both the tasks require execution of a sequence of checks/validations on the piece of code.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family:trebuchet ms;"&gt;Since we always have to execute a sequence of steps and verifications in order to finish the task successfully, this is where automation comes into picture. We have several tools available outside to automate the testing process and similarly we have tools to verify 'coding standards' in our code. These tools are normally termed as 'Static code analysis tools' outside.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;In this article i'll discuss about the static source code analysis tools that are available as plug-ins to famous 'Eclipse' IDE.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: trebuchet ms;" href="http://findbugs.sourceforge.net/"&gt;&lt;u&gt;&lt;b&gt;FindBugs:&lt;/b&gt;&lt;/u&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Findbugs is a static code analysis tool available for eclipse IDE as a plug-in. We can use this tool against a whole eclipse project or just a simple java program to find out trivial issues like 'Possible null pointer exceptions' etc. This plug-in  is available as download from the &lt;/span&gt;&lt;a style="font-family: trebuchet ms;" href="http://findbugs.cs.umd.edu/eclipse"&gt;eclipse update site&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt; itself. Its easy to install and it takes no time to test it against any java project.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://pmd.sourceforge.net/"&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;&lt;u&gt;PMD:&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;PMD is another plug-in that is available for several IDEs including eclipse. The functionality of PMD is pretty much the same as 'Findbugs' except that when we apply the tool against a project, all the code violations are integrated into the code and will be shown as errors and warnings in the code itself. It'll be very easy to use this tool as we don't need to goto any seperate eclipse 'view' to check the list of errors. They'll be shown directly in the code itself. PMD also allows us to extend or customize the validation functionality as per our requirements. If you want to extend the functionality of a validation you might need to override the API that comes along with this and plug-it into the PMD itself. Most of the times, the default set of validations that come pre-packaged with this plug-in itself would be sufficient to solve most of the commonly occurring problems. You can install the plug-in through its update site &lt;a href="http://pmd.sourceforge.net/eclipse/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://checkstyle.sourceforge.net/"&gt;&lt;span style="font-weight: bold;"&gt;&lt;u&gt;Check Style:&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check style plug-in is another static code analysis plug-in available for eclipse. This is so far the most configurable plug-in that I come across lately. It comes pre-packaged with lot of rules with it and still it supports overrides for literally every rule that it defines in its modules. You can optionally include any module you want for running check style in your project. You can also use regular expressions for refining/tuning each rule. You can download this as a standalone program from its site itself. If you want to download it as a plug-in to your eclipse you can find a nice one &lt;a href="http://eclipse-cs.sourceforge.net/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;u&gt;Conclusion :&lt;br /&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;Nobody's perfect, each plug-in listed above works very well in very specific situations and hence can't be applied in the generic sense. We can't apply the same rules in all the situation without customizing the tool for our requirement.  So, in order to get the best results suggestible to use a combination of these plug-ins in our code.&lt;br /&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/6734864162420840501-6085235223449070404?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/6085235223449070404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=6085235223449070404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6085235223449070404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6085235223449070404'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2008/03/3-fantastic-static-code-analysis-tools.html' title='3 &apos;fantastic&apos; static code analysis tools for eclipse'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-2060204533242061024</id><published>2008-01-16T13:21:00.001-08:00</published><updated>2008-01-16T13:21:54.250-08:00</updated><title type='text'>How to Mock an object ?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;In today's article, we'll see how to build Mock objects from a normal object and what are the rules that we should follow while creating objects so that they can be mocked.&lt;br/&gt;&lt;br/&gt;Mock objects are meant for replacing the actual domain object or an object collaborator with an 'expected' functionality. Basically here are the things we can do with a mock object. &lt;br/&gt;&lt;ul&gt;&lt;li&gt;We can set expectations about the object's behavior.&lt;/li&gt;&lt;li&gt;We can simulate error conditions that might occur in real life situations. &lt;/li&gt;&lt;li&gt;We can eliminate the dependency on the domain object so that we don't have&lt;br/&gt;to worry about setting up a separate environment for testing our small&lt;br/&gt;piece of code.&lt;/li&gt;&lt;/ul&gt;With that said, lets also see things we aren't supposed to do with mock object. Mock object's behavior should be restricted to its expectations. The number of objects we mock for testing a given piece of code should not be more than a small value like 2 to 3. If we have to mock too many objects to make our code work then we need to seriously consider re-factoring our code into small pieces so that we can test them using less number of mock objects.&lt;br/&gt;&lt;br/&gt;There're again two cases you should consider while writing a mock object they are.. &lt;br/&gt;&lt;ul&gt;&lt;li&gt;Mocking an Interface.&lt;/li&gt;&lt;li&gt;Mocking a Class&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;Mocking an Interface&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;:&lt;br/&gt;&lt;br/&gt;Creating a mock object out of a interface is very simple and straight forward. Your mock object can simply implement the interface and behave the way exactly as you expected. Lets look at an example on how to do it with a sample Interface. &lt;br/&gt;&lt;br/&gt;Public interface Request&lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;public String getParameter(String paramName); &lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;Now, lets try to mock this interface&lt;br/&gt;&lt;br/&gt;public class MockRequest implements Request&lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;String _expectedValue = null;&lt;br/&gt;&lt;br/&gt;public void setExpectedResult(String pVal)&lt;br/&gt;{&lt;br/&gt;this._expectedValue = pVal;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;public String getParameter(String pName)&lt;br/&gt;{&lt;br/&gt;return _expectedValue; &lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;At the first glance, you will know that my mock object has nothing to do with how the actual implementation of the Request interface gets its values from. It can get it from a simple hashmap or get it using a complex logic like going to DB, we don't care ! All we care about is what is the result that we expect from this object. This is exactly what we're doing by adding a method 'setExpectedResult()'. We just describe what we need from the mock object and nothing more. &lt;br/&gt;&lt;br/&gt;Now in our test class we can simply write the code like this .. &lt;br/&gt;&lt;br/&gt;public class SomeTest extends TestCase&lt;br/&gt;{&lt;br/&gt;public void testOneMethod()&lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;MockRequest req = new MockRequest(); &lt;br/&gt;req.setExpectedResult("PURCHASE");&lt;br/&gt;&lt;br/&gt;DomainObjectToTest test = new DomainObjectToTest(req); &lt;br/&gt;test.callMethodTotest(); &lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;Lets assume that 'callMethodToTest()' method invokes getParameter() of the request object that is passed as a parameter to the constructor. With the mock object, we have control over what values that our code receives when it eventually calls the 'getParameter()' method on the request object. &lt;br/&gt;&lt;br/&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;Mocking a Class:&lt;/b&gt;&lt;/u&gt;&lt;/i&gt; &lt;br/&gt;&lt;br/&gt;Mocking a class is done in pretty much the same manner as interfaces. The mock object is created by extending from the actual domain object instead of implementing an interface. The pattern to wrap a behavior around a given method remains the same as described above. &lt;br/&gt;&lt;br/&gt;There're some rules we should follow while creating the actual domain object before we start mocking it. &lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;li&gt;The Domain object should be extensible. It can't be a final class. &lt;/li&gt;&lt;li&gt;The Domain object's default constructor should be visible atleast to its sub classes. So, the allowable access modifier to a default constructor is 'protected'. &lt;/li&gt;&lt;li&gt;We should not mock the very object we're trying to test in the first place. &lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;The first two points are intuitive but I wanted to stress more on the third point here. You can check my previous article "&lt;a href='http://whatdidilearn2day.blogspot.com/2008/01/testing-using-mock-objects-using-junit.html'&gt;Testing using Mock Objects using Junit&lt;/a&gt;", in the article I have mentioned two methods for abstracting away the singleton invocations from a given class. In one of the methods I've said that we can move the singleton invocations to a separate methods so that we can override them by returning our mock objects instead of actual singletons. This method is clearly not suggestible according to the third point I specified above. I mentioned that approach there because its easy to start off as a beginner, but the ideal way to handle that situation is always by using 'Dependency Ingestion'. &lt;br/&gt;&lt;br/&gt;There're many other things that we can achieve and verify using the mock objects, but all those implementations are too tedious to implement manually, so we leave that to mock object generators. Mock object generators are tools to create mock objects out of real time objects, they come particularly handy while mocking interfaces. We'll discuss more about these tools in my coming articles. &lt;br/&gt;&lt;br/&gt;Going further we'll also discuss about some famous design principles which could help us write de-coupled code while implementing a functionality. Till then, keep glued to my blog for updates !! &lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p class='poweredbyperformancing'&gt;Powered by &lt;a href='http://scribefire.com/'&gt;ScribeFire&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-2060204533242061024?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/2060204533242061024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=2060204533242061024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2060204533242061024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/2060204533242061024'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2008/01/how-to-mock-object.html' title='How to Mock an object ?'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-6251683020805920982</id><published>2008-01-15T20:35:00.001-08:00</published><updated>2008-01-15T20:35:55.184-08:00</updated><title type='text'>Testing using Mock objects using Junit</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;In today's article,we'll talk about how to test our code using Mock objects using a small example. &lt;br/&gt;&lt;br/&gt;Lets assume a class which uses lot of singleton classes for implementing the functionality. Singleton classes if used unwisely can clutter our program with too many static invocations and make our code hard to test. For this reason we should always de-couple these singleton instances to other objects/functions. For Example consider this class... &lt;br/&gt;&lt;br/&gt;Public class AuthorizeAdapterImpl&lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;    LoggerManager _logMgr = null;&lt;br/&gt;    DataManager _dataMgr = null;&lt;br/&gt;    PlanManager _planMgr = null;&lt;br/&gt;&lt;br/&gt;    public AuthorizeAdapterImpl()&lt;br/&gt;    { // constructor. &lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;public boolean authorizeEverything()&lt;br/&gt;{&lt;br/&gt;    _logMgr = LoggerManager.getInstance();&lt;br/&gt;    _dataMgr = DataManager.getInstance();&lt;br/&gt;    _planMgr = PlanManager.getInstance(); &lt;br/&gt;&lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   ....   // code that extensively uses these variables. &lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;Now, if you look closely at this class it is directly dependent on three Manager classes. So in order to run/test this class we need to make sure the other Manager classes which it depends on are initialized properly, which is totally unnecessary as we wanted to test logic in only this class.&lt;br/&gt;&lt;br/&gt;We can address this in two possible ways.. &lt;br/&gt;&lt;ul&gt;&lt;li&gt;Replace static invocations with simple getXXXInstance methods. &lt;/li&gt;&lt;li&gt;Dependency ingestion.&lt;/li&gt;&lt;/ul&gt;Lets look at the first alternative...&lt;br/&gt;&lt;br/&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;Replace static invocations with simple getXXXInstance methods :&lt;/b&gt;&lt;/u&gt;&lt;/i&gt; &lt;br/&gt;&lt;br/&gt;The idea behind this is to move the singleton invocations into a separate private methods so that our function doesn't directly depend on those static methods directly. Look at the code below.. &lt;br/&gt;&lt;br/&gt;Public class AuthorizeAdapterImpl&lt;br/&gt;&lt;br/&gt;{&lt;br/&gt;    LoggerManager _logMgr = null;&lt;br/&gt;    DataManager _dataMgr = null;&lt;br/&gt;    PlanManager _planMgr = null;&lt;br/&gt;&lt;br/&gt;    public AuthorizeAdapterImpl()&lt;br/&gt;&lt;br/&gt;    { // constructor. &lt;br/&gt;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;public boolean authorizeEverything()&lt;br/&gt;{&lt;br/&gt;    _logMgr = getLoggerManagerInstance();&lt;br/&gt;    _dataMgr = getDataManagerInstance();&lt;br/&gt;    _planMgr = getPlanManagerInstance(); &lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   ....   // code that extensively uses these variables. &lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;protected LoggerManager getLoggerManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return LoggerManager.getInstance();&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;protected DataManager getDataManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return DataManager.getInstance();&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;protected PlanManager getPlanManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return PlanManager.getInstance();&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;Now, our 'authorizeEverything()' method doesn't depend on any of the singleton classes. This class now becomes testable because we can extend this class and override the getXXXInstance() methods to return our 'Mock' objects instead of actual collaborating objects like DataManager, LoggerManager etc.. &lt;br/&gt;&lt;br/&gt;public class MockAuthorizeAdapterImpl extends AuthorizeAdapterImpl&lt;br/&gt;{&lt;br/&gt;protected LoggerManager getLoggerManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return new MockLoggerManager();&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;protected DataManager getDataManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return new MockDataManager();&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;protected PlanManager getPlanManagerInstance()&lt;br/&gt;{&lt;br/&gt;    return new MockPlanManager();&lt;br/&gt;}   &lt;br/&gt;}&lt;br/&gt; &lt;br/&gt;Now that we have replaced the collaborating objects with our mock objects we can use this class for testing the method &lt;br/&gt;'authorizeEverything()'. This works because when we call this method we're actually invoking the method in the super class which is AuthorizeAdapterImpl in this case.&lt;br/&gt;&lt;br/&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;Dependency Ingestion :&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;Dependency ingestion is a refactoring technique that allows to do the things in a more nicer and efficient way. The basic way how this differs from the above given approach is that instead of abstracting away the singleton invocations into a seperate methods in the same class, we provide the instances of these classes as 'parameters' to this method/class. The choice is again left to the developer but in this case since all the singleton objects are class level variables it makes sense to inject them at the class level instead of passing them to each method. &lt;br/&gt;&lt;br/&gt;Public class AuthorizeAdapterImpl&lt;br/&gt;{&lt;br/&gt;    LoggerManager _logMgr = null;&lt;br/&gt;    DataManager _dataMgr = null;&lt;br/&gt;    PlanManager _planMgr = null;&lt;br/&gt;&lt;br/&gt;    public AuthorizeAdapterImpl(LoggerManager logger, DataManager dMgr , PlanManager pMgr)&lt;br/&gt;&lt;br/&gt;    { // constructor. &lt;br/&gt;       this._logMgr = logger; &lt;br/&gt;this._dataMgr = dMgr; &lt;br/&gt;this._planMgr = pMgr; &lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;public boolean authorizeEverything()&lt;br/&gt;{&lt;font color='#ff0000'&gt;&lt;br/&gt;    //_logMgr = LoggerManager.getInstance(); We don't need this !! &lt;br/&gt;    //_dataMgr = DataManager.getInstance();&lt;br/&gt;    //_planMgr = PlanManager.getInstance(); &lt;/font&gt;&lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   .... &lt;br/&gt;   ....   // code that extensively uses these variables. &lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;With this change, the code has to be changed all the invocation points where we create the object for AuthorizeAdapterImpl class to send the required objects to this class. &lt;br/&gt;&lt;br/&gt;This makes our test class very easy to write.. &lt;br/&gt;&lt;br/&gt;public class AuthorizeAdapterImplTest&lt;br/&gt;{&lt;br/&gt;   public void testAuthorizeEverything()&lt;br/&gt;  {&lt;br/&gt;      AuthorizeAdapterImpl impl = new AuthorizeAdapterImpl(new MockLogger(), new MockdataMgr(), new MockPlanMgr()); &lt;br/&gt;      impl.authorizeEverything(); &lt;br/&gt;       // assertion code to verify our test case. &lt;br/&gt;  }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;There's one disadvantage with this approach... &lt;br/&gt;&lt;br/&gt;if our AuthorizeAdapterImpl class has to use a new singleton object, then we've to change the constructor to inject that object too which may not be feasible all the times. What we can do in this case is that we'll move all these singleton objects into a container and pass the reference to the container to this class. Lets call the container DLMSubSystem. The AuthorizeAdapterImpl class becomes like this. &lt;br/&gt;&lt;br/&gt;public class AuthorizeAdapterImpl &lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;   DLMSubSystem _dlmSubSystem = null;&lt;br/&gt;&lt;br/&gt;public AuthorizeAdapterImpl(DLMSubSystem subSystem)&lt;br/&gt;{&lt;br/&gt; this._dlmSubSystem = subSystem;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;public boolean authorizeEverything()&lt;br/&gt;{&lt;br/&gt;  LoggerManager logger = _dlmSubSystem.getLogger(); &lt;br/&gt; DataManager dataMgr = _dlmSubSystem.getDataManager();&lt;br/&gt;....&lt;br/&gt;...&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;Well, i hope you got the basic idea behind how to use refactoring and mock objects for unit testing code. In my next article i'll tell you more about what constitutes a Mock object and how to define behavior of mock object as per our requirement. &lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p class='poweredbyperformancing'&gt;Powered by &lt;a href='http://scribefire.com/'&gt;ScribeFire&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-6251683020805920982?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/6251683020805920982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=6251683020805920982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6251683020805920982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6251683020805920982'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2008/01/testing-using-mock-objects-using-junit.html' title='Testing using Mock objects using Junit'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-6836531513509108288</id><published>2008-01-11T08:12:00.000-08:00</published><updated>2008-01-15T11:11:15.231-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><title type='text'>Policies and AntiPatterns in Junit</title><content type='html'>&lt;div style="font-family: trebuchet ms;" xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;span style="font-size:100%;"&gt;Now that you took the first step towards the automation testing, its time to know the rules and play by them… Today, I’ll try to list down the policies that we should follow and what are the antipatterns available in Junit. &lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;b style=""&gt;&lt;u&gt;Policies:&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;1) Write Unit tests only for the code which is visible to other classes. You can just write tests for only the complex methods in a class, but there’s no rule of thumb for determining whether the given method is a complex method to test or not. But we can get a viable answer from the &lt;a href="http://www.junitfactory.com/articles/crap4j/"&gt;C.R.A.P formula&lt;/a&gt; used in Crap4J plug-in. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;2) The purpose of the unit test is only to test a particular piece of code, it doesn’t make sense to implement anything more than that in a junit test case so, it should not involve complex logic like connecting to Database or setting up property files etc.&lt;span style=""&gt;  &lt;/span&gt;You can make use of Mock objects to avoid the situations mentioned above. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;3) Your unit testing code should clean you actual functionality with effective refactoring techniques, but in any case you actual code should not be changed just to make work with your Unit testing code. We should always try to make it more testable in nature, but not directly rely up on the unit testing code. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;   &lt;/span&gt;For example : You can not have logic something like this in the core part of our code.. &lt;pre&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;                        &lt;/span&gt;If (isTestingMode)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;                                    &lt;/span&gt;//do following…&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;                        &lt;/span&gt;Else &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;                                    &lt;/span&gt;// do following… &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;4) Mock object should be only used as a substitute of an existing object, it SHOULD NOT contain any application specific code inside it. ( Is this what we’re trying to simulate using this object ? )&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size:100%;"&gt;For example : Lets say we've an object in the actual code that we use to fetch various property values from a property file. The method you wanted to test is written something like this...&lt;br /&gt;&lt;br /&gt;public void methodToTest()&lt;br /&gt;{&lt;br /&gt;// Some application specific code&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;PropertyManager mgr = PropertyManager.getInstance();&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;   String propertyName = "SomePropertyName";&lt;br /&gt;String propValue = mgr.getPropertyWithName(propertyName);&lt;br /&gt;// manipulating the property value here.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;For unit testing this method, you don't need to have MyBundle.properties in the classpath, you can pull out the code which reads the property from the property file and instead pass it as an argument like this.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;public void methodToTest(PropertyManager propMgr)&lt;br /&gt;{&lt;br /&gt;// Some application specific code&lt;br /&gt;String propertyName = "SomePropertyName";&lt;br /&gt;String propValue = &lt;/span&gt;&lt;span style="font-size:100%;"&gt;propMgr&lt;/span&gt;&lt;span style="font-size:100%;"&gt;.getPropertyWithName(propertyName);&lt;br /&gt;// manipulating the property value here.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Now, our code is ready for unit testing and we can mock the Propertymanager by asking it to emulate the call to 'getPropertyWithName(...)' method by returning our required values ( or behavior ). So, our mock object should look like this.&lt;br /&gt;&lt;br /&gt;MockPropertyManager extends PropertyManager&lt;br /&gt;{&lt;br /&gt;public String getPropertyWithName(propertyName)&lt;br /&gt;{&lt;br /&gt;if(propertyName == "SomePropertyName") return "correspondingValue";&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;At this point, we've removed the dependency of a property file from our code. Now,we can test this code without worrying about setting up the whole environment around it.&lt;br /&gt;&lt;br /&gt;I'll elaborate more about using mock objects in my coming articles...&lt;br /&gt;&lt;/span&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;b style=""&gt;&lt;u&gt;Anti patterns : &lt;o:p&gt;&lt;/o:p&gt;&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;Anti patterns are things we &lt;u&gt;shouldn’t do or against the standard&lt;/u&gt; while writing any piece of code/work. We’ve antipatterns for Junit as well, and internet is filled with numerous number of articles discussing about these. As you can see, this topic is pretty dynamic in nature and new patterns are kept on adding every day.. ( well, don’t know where exactly they add, but they mention all these new items in blogs and there’re ppl who’d like to archive all these things and keep them at one single place)… &lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;When I started looking for these things, I stumbled across one interesting article which talks especially about “&lt;a href="http://www.exubero.com/junit/antipatterns.html"&gt;Junit antipatterns&lt;/a&gt;”. You can just go through it and you’ll know what I’m talking about.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-6836531513509108288?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/6836531513509108288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=6836531513509108288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6836531513509108288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/6836531513509108288'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2008/01/2-things-you-must-know-about-junit.html' title='Policies and AntiPatterns in Junit'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-1108096961691188181</id><published>2007-11-30T06:56:00.001-08:00</published><updated>2007-11-30T06:56:39.110-08:00</updated><title type='text'>Remote Desktop access using dynammic IP address</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Every one knows that if we've to access our machine remotely from a different location we need to have a static IP address for the system we'd like to connect. But its not always that we get one static address for 'Free' of cost. I've figured out way to achieve the same using dynammic addresses that your ISP assigns to your computer when ever u log in to use internet. &lt;br/&gt;&lt;br/&gt;The basic idea behind these softwares is that they try to remove the  'dynammic' nature of your IP address using a client software that you have to install on your system. The client software basically informs their server when ever your IP address changes to a different value and all this happens seamlessly without the user's notice ( all the techies can find out abt this easily by looking at the console, but for ordinary users its of no concern). &lt;br/&gt;&lt;br/&gt;I have found two choices for this approach &lt;br/&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://www.no-ip.com/'&gt;NO-IP.com&lt;/a&gt; : This is freely available service, where you can create a account and map your desktop computer to a domain name. After configuring this we can use the XP's built in 'Remote Desktop Connection' utility to access your computer remotely from anywhere in the world. &lt;/li&gt;&lt;/ul&gt;         The major problem with this service is that you need to make sure your ISP is not blocking 'Remote access' port for&lt;br/&gt;       accessing your system. You can check that at &lt;a target='_blank' href='http://www.canyouseeme.org/' onclick='return top.js.OpenExtLink(window,event,this)'&gt;http://www.canyouseeme.org/&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='https://secure.logmein.com/home.asp'&gt;LogMeIn&lt;/a&gt; : This is another alternative, which is far more superior than the first choice.  Using this, you can access your computer from your favorite web browser like Internet explorer or Firefox. Its very easy to install and very easy to configure. But all this convenience  comes with a cost ;-) , you can still use the basic remote access after evaluating the pro version of the software. &lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p class='poweredbyperformancing'&gt;Powered by &lt;a href='http://scribefire.com/'&gt;ScribeFire&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-1108096961691188181?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/1108096961691188181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=1108096961691188181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/1108096961691188181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/1108096961691188181'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2007/11/remote-desktop-access-using-dynammic-ip.html' title='Remote Desktop access using dynammic IP address'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6734864162420840501.post-5365789361996297665</id><published>2007-11-22T01:54:00.000-08:00</published><updated>2007-11-22T02:03:19.807-08:00</updated><title type='text'>Oh ! who needs another blog !</title><content type='html'>Well, many of the folks actually think like that .. with millions of blogs that exist today why do we need another blog like this..&lt;br /&gt;&lt;br /&gt;People say , 'Growth stops, the moment you stop learning' whether its related to job or life, we always learn. Thats what we're made for. In addition to this,  if we can't remember what we've learned on each day, all our effort may prove to be useless.&lt;br /&gt;&lt;br /&gt;This blog is meant to be a chronicle of 'What I've learned today', a short description about the new things I learnt today at my work.  I'd prefer discussing only technical topics here so that it improves my skills at work too :-)&lt;br /&gt;&lt;br /&gt;Enjoy reading the blog ..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6734864162420840501-5365789361996297665?l=whatdidilearn2day.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://whatdidilearn2day.blogspot.com/feeds/5365789361996297665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6734864162420840501&amp;postID=5365789361996297665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5365789361996297665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6734864162420840501/posts/default/5365789361996297665'/><link rel='alternate' type='text/html' href='http://whatdidilearn2day.blogspot.com/2007/11/oh-who-needs-another-blog.html' title='Oh ! who needs another blog !'/><author><name>sarat</name><uri>http://www.blogger.com/profile/10445254230204209891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_kR14w9m4gP8/R4zT6UubD1I/AAAAAAAAB3Q/zPFvKRygNQc/S220/DSCN2206.JPG'/></author><thr:total>0</thr:total></entry></feed>
