<?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-3915544030735587425</id><updated>2011-08-07T15:51:05.175-07:00</updated><category term='JBoss'/><category term='packaging'/><category term='Cairnagorm'/><category term='FunFx'/><category term='Intellij'/><category term='Coding techniques'/><category term='clojure overflow'/><category term='Build'/><category term='Java'/><category term='Search'/><category term='Compilation'/><category term='Groovy'/><category term='clojure java svn'/><category term='jar'/><category term='Testing'/><category term='Jruby'/><category term='gookup'/><category term='test'/><category term='mocking'/><category term='gem'/><category term='Ruby'/><category term='Linux'/><category term='Ferret'/><category term='Ruby Gem'/><category term='Flex'/><category term='Ubuntu'/><category term='Spring'/><category term='Bash'/><category term='AMF'/><category term='Buildr'/><title type='text'>Development for the masses</title><subtitle type='html'>A blog about software development and other software related matters</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-1285325160880138636</id><published>2010-04-04T05:26:00.000-07:00</published><updated>2010-04-04T05:34:42.432-07:00</updated><title type='text'>Moving into narkisr.com</title><content type='html'>This blog has served me well for the past three years still iv decided to give it a new home that iv developed, eating my own dog food.&lt;br /&gt;&lt;br /&gt;Since Iv developed the entire thing I believe that the reading experience will be better &amp; more interesting to you all, all the old content has been migrated, ill redirect to the new one. &lt;br /&gt;&lt;br /&gt;Looking forward to meet you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-1285325160880138636?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/1285325160880138636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=1285325160880138636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1285325160880138636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1285325160880138636'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2010/04/moving-into-narkisrcom.html' title='Moving into narkisr.com'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6070163998436828898</id><published>2010-01-09T08:13:00.000-08:00</published><updated>2010-01-09T09:45:54.776-08:00</updated><title type='text'>Cool Groovy techniques</title><content type='html'>Groovy is a versatile &amp; very powerful language to code with, as a Java super set it enables a Java programmer to write its code with all the known Java idioms &amp; progress into Groovy land in small steps, in this post ill present two techniques that I find to be very powerful.&lt;br /&gt; &lt;br /&gt;The first is closure initialization, in Java land its common that when we have an object A which uses another object B with non trivial construction code (which depends on A's input) than we write all the initialization code of B inside A constructor:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class ComplexInit { // our B&lt;br /&gt;  // ... some state that need to be initialized by users of this class&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class UsesComplex {// our A&lt;br /&gt;  private ComplexInit v&lt;br /&gt;  def UsesComplex(){&lt;br /&gt;     v = new ComplexInit()&lt;br /&gt;     //..  some complex initialization logic which depends on UsesComplex &lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Another common practice is to create a factory that will encapsulate the initialization of ComplexInit class taking A as input:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class ComplexInitFactory {&lt;br /&gt;  def createComplexWith(UsesComplex u){&lt;br /&gt;    // initialization code which depends on &lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Groovy offers another way which I named "closure initialization":&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class UsesComplex{&lt;br /&gt;  private ComplexInit val = {&lt;br /&gt;     def result = new ComplexInit()&lt;br /&gt;     // more logic here&lt;br /&gt;  }()&lt;br /&gt;  &lt;br /&gt;  def UsesComplex(){&lt;br /&gt;    // ComplexInit is initialized above   &lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note that we are embedding a closure within the UsesComplex class &amp; call it immediately after it has been defined, this resembles static initializer code blocks in Java except that it not static at all, the anonymous closure has access to its surrounding scope &amp; can access other data members during its run:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class UsesComplex{&lt;br /&gt;  def today = new Date()&lt;br /&gt;&lt;br /&gt;  private ComplexInit val = {&lt;br /&gt;     def result = new ComplexInit()&lt;br /&gt;     result.a = today&lt;br /&gt;     result&lt;br /&gt;  }()&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;By separating our constructors into initialization blocks we modularize the construction of our object, making our code more readable &amp; DRY (no separation between deceleration &amp; initialization).&lt;br /&gt;Another interesting technique is dynamic method dispatch, in Groovy we can dispatch methods like so:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class Target{&lt;br /&gt;  def methodA(){ println 'hey'}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;new Target().methodA()&lt;br /&gt;new Target()."methodA"()// this works too!&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This means that we can dispatch methods according to run time logic:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class Target{&lt;br /&gt;  def calcA(){'a'}&lt;br /&gt;  def calcB(){'b'}&lt;br /&gt;  def calcC(){'c'} &lt;br /&gt;  def notCalc(){'d'}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def t = new Target()&lt;br /&gt;def calcs = t.metaClass.methods.findAll{it.name.startsWith('calc')}.collect{it.name}&lt;br /&gt;calcs.each{println t."$it"()}// will print a b c&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Its true that Java reflection has similar capabilities however the Java API is very verbose &amp; not as elegant, use this technique with care since it may result with hard to read code!&lt;br /&gt;&lt;br /&gt;Thats about it for this post, let me know if you find these techniques useful in your code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6070163998436828898?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6070163998436828898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6070163998436828898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6070163998436828898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6070163998436828898'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2010/01/cool-groovy-techniques.html' title='Cool Groovy techniques'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-1432286694230195736</id><published>2009-10-31T11:34:00.000-07:00</published><updated>2009-10-31T12:23:43.831-07:00</updated><title type='text'>Synching your enviroment around</title><content type='html'>Ubuntu 9.10 has just came out &amp; iv rushed to upgrade, upgrading my 9.04 to 9.10 via the upgrade manager is a working option but usually id rather do a clean install &amp; get a fresh system to poke around.&lt;br /&gt;The main issue that clean install brings is restoring your old environment which includes installed programs, settings files (.bashrc, .vimrc etc..), non packaged applications (usually the latest &amp; greatest versions of Clojure, Groovy etc..).&lt;br /&gt;Another issue is the need to restore these settings on multiple machines while keeping it all consistent between them, there must a better way than working it all manually!&lt;br /&gt;&lt;br /&gt;Well the solution that iv come with involve two tools, &lt;a href="http://www.getdropbox.com/"&gt;Dropbox&lt;/a&gt; &amp; &lt;a href="http://automateit.org/"&gt;AutomateIt&lt;/a&gt;, Dropbox is no more than a fancy folder to the cloud synchronizer which enables me to access all my settings file from any machine, lsym-ing my .bashrc, .vimrc &amp; any other file that id like to share across machines into the Dropbox folder is all that is required.&lt;br /&gt;&lt;br /&gt;The second part involves AutomateIt, which is a configuration management framework written in Ruby, an easy way of re-creating symlinks from my Dropbox folder onto a new system is using the following AutomateIt script:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;HOME = ENV['HOME']&lt;br /&gt;DROP = "#{HOME}/Private/Dropbox"&lt;br /&gt;&lt;br /&gt;def link(src,dst)&lt;br /&gt;   ln_s("#{DROP}/#{src}","#{HOME}/#{dst}")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# Vim&lt;br /&gt;link "vim/.vimrc",".vimrc"&lt;br /&gt;link "vim/.vim",".vim"&lt;br /&gt;link "vim/.vimclojure-2.1.2",".vimclojure"&lt;br /&gt;# Bash&lt;br /&gt;link "BashEnv/.bashrc",".bashrc"&lt;br /&gt;link "BashEnv/.inputrc",".inputrc"&lt;br /&gt;# Languages&lt;br /&gt;link "prog-langs/.clojure",".clojure"&lt;br /&gt;link "prog-langs/.groovy",".groovy"&lt;br /&gt;link "prog-langs/.jruby",".jruby"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The nice thing about it is that it hides all the nitty gritty details that id have to figure out when using plain Ruby (or any other environment for that matter), AutomateIt wraps common tasks with a bash like DSL, unlike bash this DSL is portable across multiple unix systems &amp; it hides many of the complexities that follow.&lt;br /&gt;AutomateIt performs actions only when they are required, this solves annoying cases that rise when scripts run more than once on a system (e.g. appending text to files).&lt;br /&gt;&lt;br /&gt;Another cool feature is package management, AutomateIt is capable of interacting with multiple packaging systems (yum, apt, gem etc..) in a transparent way, its easy to replicate installed packages onto multiple systems:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;# bash&lt;br /&gt;%w(terminator rlwrap).each{ |p| package_manager.install p}&lt;br /&gt;&lt;br /&gt;# programming&lt;br /&gt;%w(vim git-core).each{ |p| package_manager.install p}&lt;br /&gt;&lt;br /&gt;# communication&lt;br /&gt;%w(deluge openssh-server).each{ |p| package_manager.install p}&lt;br /&gt;&lt;br /&gt;# misc&lt;br /&gt;%w(gpodder gnome-do).each{ |p| package_manager.install p}&lt;br /&gt;&lt;br /&gt;# installing dropbox&lt;br /&gt;download_manager.download 'http://www.getdropbox.com/download?dl=packages/nautilus-dropbox_0.6.1_i386_ubuntu_9.10.deb' , :to =&gt; '/tmp/nautilus-dropbox_0.6.1_i386_ubuntu_9.10.deb'&lt;br /&gt;package_manager.install ({'nautilus-dropbox' =&gt; '/tmp/nautilus-dropbox_0.6.1_i386_ubuntu_9.10.deb'} , :with =&gt; :dpkg)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Using these tools has made configuration nirvana a bit closer to me &amp; hopefully to you :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-1432286694230195736?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/1432286694230195736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=1432286694230195736' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1432286694230195736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1432286694230195736'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/10/synching-your-enviroment-around.html' title='Synching your enviroment around'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-5875015271630388295</id><published>2009-07-25T06:50:00.000-07:00</published><updated>2009-07-25T09:41:36.728-07:00</updated><title type='text'>The easiest singleton around</title><content type='html'>Iv just finished watching &lt;a href="http://www.lispnyc.org/wiki.clp?page=past-meetings"&gt;stuart-clojure-presentation&lt;/a&gt; where the issue of singletons is mentioned (global &amp; thread local ones), a note from the audience mentions delay as a solution, REPL-ing a bit shows how this works:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;user=&gt; (defn singleton-factory []&lt;br /&gt;         (println "creating object")&lt;br /&gt;         (+ 1 2))&lt;br /&gt;#'user/singleton-factory&lt;br /&gt;user=&gt; (def singleton (delay (singleton-factory)))&lt;br /&gt;#'user/singleton&lt;br /&gt;user=&gt; (defn usage []&lt;br /&gt;         (force singleton))&lt;br /&gt;#'user/usage&lt;br /&gt;user=&gt; (usage)&lt;br /&gt;creating object&lt;br /&gt;3&lt;br /&gt;user=&gt; (usage)&lt;br /&gt;3&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Stuart does mention &lt;a href="http://code.google.com/p/clojure-contrib/wiki/SingletonApiDoc"&gt;contrib singleton&lt;/a&gt; which has also per-thread-singleton.&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;user=&gt; (use 'clojure.contrib.singleton)&lt;br /&gt;nil&lt;br /&gt;user=&gt; (def t-singleton (per-thread-singleton singleton-factory)) &lt;br /&gt;#'user/t-singleton&lt;br /&gt;user=&gt; (defn use-twice [] (+ 1 (t-singleton)) (+ 1 (t-singleton)))&lt;br /&gt;#'user/use-twice&lt;br /&gt;user=&gt; (defn use-twice-no-singleton [] (+ 1 (singleton-factory)) (+ 1 (singleton-factory)))&lt;br /&gt;#'user/use-twice-no-singleton&lt;br /&gt;user=&gt; (. (Thread. use-twice) start) ; each Clojure Fn implements Runnable&lt;br /&gt;nil&lt;br /&gt;user=&gt; creating object ; REPL prints on the wrong line&lt;br /&gt;&lt;br /&gt;user=&gt; (. (Thread. use-twice-no-singleton) start)&lt;br /&gt;user=&gt; creating object ; same thing&lt;br /&gt;creating object&lt;br /&gt;&lt;br /&gt;user=&gt; &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This should come useful when working with all those Java mutable objects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-5875015271630388295?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/5875015271630388295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=5875015271630388295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5875015271630388295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5875015271630388295'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/07/easiest-singleton-around.html' title='The easiest singleton around'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-8871420951859863603</id><published>2009-07-23T15:57:00.000-07:00</published><updated>2009-07-25T06:49:26.694-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clojure overflow'/><title type='text'>Dont overflow yourself!</title><content type='html'>Clojure has many nice less highlighted features, one of these is overflow protection, this can be a true life saver:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;user=&gt; (unchecked-add 1 2); not safe but might be faster&lt;br /&gt;3&lt;br /&gt;user=&gt; (unchecked-add (. Integer MAX_VALUE) 2); oops&lt;br /&gt;-2147483647&lt;br /&gt;user=&gt; (+ (. Integer MAX_VALUE) 2) ; using safe arithmetic again&lt;br /&gt;2147483649&lt;br /&gt;user=&gt; (+ (. Integer MAX_VALUE) 23)&lt;br /&gt;2147483670&lt;br /&gt;user=&gt; (class (+ (. Integer MAX_VALUE) 23)); Clojure does the right thing for us&lt;br /&gt;java.lang.Long&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It does pack more than just concurrency up its sleeve.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-8871420951859863603?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/8871420951859863603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=8871420951859863603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8871420951859863603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8871420951859863603'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/07/dont-overflow-yourself.html' title='Dont overflow yourself!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-2938055409941179112</id><published>2009-06-29T14:26:00.000-07:00</published><updated>2009-06-29T15:25:45.340-07:00</updated><title type='text'>Genericsfaction, getting some generics satisfaction</title><content type='html'>Java generics have a lot of short shortcoming, most of which are the result of the religious backward compatibility that Java is known for. &lt;br /&gt;One of the most annoying "features" of generics is type erasure in which the compiler removes (&lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Class.html#getGenericSuperclass()"&gt;almost&lt;/a&gt;) any trace of generic types meta data.&lt;br /&gt;&lt;br /&gt;Iv been pondering about this issue &amp; had a simple idea, what if we could add back in the meta data that the erasing process removed?&lt;br /&gt;So, iv decided to create a proof of concept in order to show how this might work and named it &lt;a href="http://github.com/narkisr/genericsfaction/tree/master"&gt;genericsfaction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Using genericsfaction requires an additional code manipulation stage in which the source code is scanned &amp; gets its AST manipulated (meta data is introduced), each manipulated source file is dumped into a separate folder (named gen), all that is left is to compile the files under gen (instead of the original src).&lt;br /&gt;&lt;br /&gt;At the moment there are only two enrichments implemented, the first is method input parameters annotation enrichment:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public void twoTypeParamsMet(@GenMeta(stringRep = "((Object ()) (Object ()))", classes = { Object.class, Object.class }) Map &amp;lt;Object, Object&amp;gt; map) {&lt;br /&gt;   // method code&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The second is variable initialization enrichment:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public static void main(String [] args) {&lt;br /&gt;   List&amp;lt;Integer&amp;gt; list = (List &amp;lt;Integer&amp;gt;)MetaProxy.newInstance(new ArrayList&amp;lt;Integer&amp;gt;(),"(Integer ())",new Class []{Integer.class});&lt;br /&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The reason that annotations aren't used in this case is due to this &lt;a href="http://forums.sun.com/thread.jspa?threadID=664018"&gt;limitation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There is no release to play with yet, however the source is up on github (mostly Clojure), I am planing on making a release as soon as ill finish to implement a validation module that uses this meta data in runtime.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-2938055409941179112?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/2938055409941179112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=2938055409941179112' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2938055409941179112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2938055409941179112'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/06/genericsfaction-getting-some-generics.html' title='Genericsfaction, getting some generics satisfaction'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-7964072952206948839</id><published>2009-05-23T13:21:00.000-07:00</published><updated>2009-05-25T12:05:36.759-07:00</updated><title type='text'>Newify your Object</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Update&lt;/span&gt; a generous Anonymous has left a comment that the following special macro form does the same as the newify function that i present later on:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;(def nested-object (-&gt; GrandFather. Father. GrandSon.)) &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Feel free to skip this entry (unless your interested in an alternative implementation).&lt;br /&gt;&lt;br /&gt;Instantiating large nested object graphs can be tedious in any language Clojure included:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;(def nested-object &lt;br /&gt;  (new Grandson &lt;br /&gt;    (new Father &lt;br /&gt;      (new Grandfather)))) &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;All those new methods call get old pretty quickly and are not DRY, to remedy this will take advantage on a cool property of Clojure &lt;a href="http://en.wikipedia.org/wiki/Homoiconicity"&gt;Homoiconicity&lt;/a&gt;.&lt;br /&gt;Homoiconicity basically means that the code is represented by a basic data structure of the language itself (lists in the case of Clojure), this means that manipulating the AST is easy as pie!&lt;br /&gt;It would be nice if we could write something like the following:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;(def nested-object &lt;br /&gt;  (def nested-object (newify '(Grandson (Father (Grandfather))))) &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The newify function takes a nested list of objects &amp; adds new before each object, post that the function evaluates the resulting list:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;(defn newify [e] (eval (newify-imp e)))&lt;br /&gt;; required since used before defined &lt;br /&gt;(defn- newify-rest [e] )&lt;br /&gt;&lt;br /&gt;(defn- newify-imp [e]&lt;br /&gt;  (let [add-new (partial cons 'new) add-rest (partial cons (first e))]&lt;br /&gt;    (if (not (empty? e))&lt;br /&gt;      (-&gt; (newify-rest e) add-rest add-new) e)))&lt;br /&gt;&lt;br /&gt;(defn- newify-rest [e]&lt;br /&gt;  (map #(if (list? %) (newify-impl %) %) (rest e)))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The newify-imp &amp; newify-rest functions are mutually recursive, newify-imp adds the new symbol &amp; the first list element to the result of the newify-rest function result, the newify-rest maps each list in the rest of the list to its newified value.&lt;br /&gt;&lt;br /&gt;This implementation could be transformed into a recursive macro that will spare us from the list escaping:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="clojure"&gt;&lt;br /&gt;  (def nested-object (newify '(Grandson (Father (Grandfather))))) &lt;br /&gt;  ; no escaping here&lt;br /&gt;  (def nested-object (newify (Grandson (Father (Grandfather))))) &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ill have to dig that option later on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-7964072952206948839?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/7964072952206948839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=7964072952206948839' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7964072952206948839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7964072952206948839'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/05/newify-your-object.html' title='Newify your Object'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4967482019043022834</id><published>2009-04-30T15:56:00.000-07:00</published><updated>2009-05-01T10:27:41.501-07:00</updated><title type='text'>NILFS on  Jaunty</title><content type='html'>The latest release of Ubuntu includes the long awaited Ext4 FS (works flawlessly on my system).&lt;br /&gt;Ext4 is faster &amp; more secure but still lacks the ability to manage FS snapshots (ZFS excels in that, but runs only in &lt;a href="http://www.wizy.org/wiki/ZFS_on_FUSE"&gt;FUSE&lt;/a&gt; on linux).&lt;br /&gt;An interesting alternative is &lt;a href="http://www.nilfs.org/en/"&gt;NILFS&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;NILFS is a log-structured file system supporting versioning of the entire file system and continuous snapshotting which allows users to even restore files mistakenly overwritten or destroyed just a few seconds ago. &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;NILFS maintains a repo for Hardy, the Jaunty repos contain only the user land tools which won't do us much good since we need the kernel module as well, this leaves us only with the option of installing it from source (still quite easy).&lt;br /&gt;&lt;br /&gt;&lt;div class="gray"&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;# a perquisite&lt;br /&gt;$ sudo aptitude install uuid-dev  &lt;br /&gt;# installing kernel module, result module resides in /lib/modules/2.6.28-11-generic/kernel/fs/nilfs2/nilfs2.ko&lt;br /&gt;$ wget http://www.nilfs.org/download/nilfs-2.0.12.tar.bz2&lt;br /&gt;$ tar jxf nilfs-2.0.12.tar.bz2&lt;br /&gt;$ cd nilfs-2.0.12&lt;br /&gt;$ make&lt;br /&gt;$ sudo make install&lt;br /&gt;# installing user land tools&lt;br /&gt;$ wget http://www.nilfs.org/download/nilfs-utils-2.0.11.tar.bz2&lt;br /&gt;$ tar jxf nilfs-utils-2.0.11.tar.bz2&lt;br /&gt;$ cd nilfs-utils-2.0.11&lt;br /&gt;$ ./configure&lt;br /&gt;$ make &lt;br /&gt;$ sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Creating a file system on a file (ideal for playing around):&lt;br /&gt;&lt;div class="gray"&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;$ dd if=/dev/zero of=mynilfs bs=512M count=1&lt;br /&gt;$ mkfs.nilfs2 mynilfs&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The FS is only a mount away:&lt;br /&gt;&lt;div class="gray"&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;# mounting the file as a loop device&lt;br /&gt;$ sudo losetup /dev/loop0 mynilfs&lt;br /&gt;$ sudo mkdir /media/nilfs&lt;br /&gt;$ sudo mount -t nilfs2 /dev/loop0 /media/nilfs/&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now lets create a couple of files:&lt;br /&gt;&lt;div class="gray"&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;$ cd /media/nilfs&lt;br /&gt;$ touch 1 2 3 &lt;br /&gt;# listing all checkpoints &amp; snapshots, on your system list should vary &lt;br /&gt;$ lscp&lt;br /&gt;                  CNO        DATE     TIME  MODE  FLG   NBLKINC       ICNT&lt;br /&gt;                   7  2009-05-01 01:08:09   ss    -         12          6&lt;br /&gt;                  13  2009-05-01 19:05:34   cp    i          8          3&lt;br /&gt;                  14  2009-05-01 19:05:59   cp    i          8          3&lt;br /&gt;                  15  2009-05-01 19:07:09   cp    -         12          6&lt;br /&gt;# creating a snapshot&lt;br /&gt;$ sudo mkcp -s&lt;br /&gt;# 15 is the new snapshot (mode is ss)&lt;br /&gt;$ lscp &lt;br /&gt;                 CNO        DATE     TIME  MODE  FLG   NBLKINC       ICNT&lt;br /&gt;                   7  2009-05-01 01:08:09   ss    -         12          6&lt;br /&gt;                  13  2009-05-01 19:05:34   cp    i          8          3&lt;br /&gt;                  14  2009-05-01 19:05:59   cp    i          8          3&lt;br /&gt;                  15  2009-05-01 19:07:09   ss    -         12          6&lt;br /&gt;                  16  2009-05-01 19:08:59   cp    i          8          6&lt;br /&gt;&lt;br /&gt;# our post snapshot file&lt;br /&gt;$ touch 4&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now lets go back in time into our snapshot, NILFS enables us to mount old snapshots as read only FS (while the original FS is still mounted):&lt;br /&gt;&lt;div class="gray"&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;$ sudo mkdir /media/nilfs-snapshot&lt;br /&gt;$ sudo mount.nilfs2  -r  /dev/loop0 /media/nilfs-snapshot/ -o cp=15 # only snapshots works!&lt;br /&gt;$ cd /media/nilfs-snapshot&lt;br /&gt;# as we might expect&lt;br /&gt;$ ls &lt;br /&gt; 1 2 3 &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;NILFS has some interesting features, its not production ready yet however it sure worth looking after its development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4967482019043022834?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4967482019043022834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4967482019043022834' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4967482019043022834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4967482019043022834'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/04/nilfs-on-jaunty.html' title='NILFS on  Jaunty'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6534405333058201794</id><published>2009-03-06T07:30:00.000-08:00</published><updated>2009-03-06T08:14:43.944-08:00</updated><title type='text'>MetaClasses can bite!</title><content type='html'>Groovy has MOP classes built in like the MetaClass class, this class enables (among other things) objects introspection, we could for example use its getProperties() method in order to get the list of all the meta properties of an object and copy their values into another object:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class ParentModel {&lt;br /&gt;    def String parentProp&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Copying the current object properties into the other object&lt;br /&gt;     */&lt;br /&gt;    def copyInto(other){&lt;br /&gt;        this.metaClass.getProperties().findAll{it.getSetter()!=null}.each{metaProp-&gt;&lt;br /&gt;            if(metaProp.getProperty(this)!=null){&lt;br /&gt;                metaProp.setProperty(other,metaProp.getProperty(this))&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        other&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The usage is quite simple:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt; def parent = new ParentModel(parentProp:"parent")&lt;br /&gt; def copiedParent = parent.copyInto(new ParentModel())&lt;br /&gt; assert copiedParent.parentProp.equals(parent.parentProp)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;While this code runs perfectly fine with object that have identical classes it has some unexpected side effects when one of the classes derives from another:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class DerivingModel extends ParentModel{&lt;br /&gt;    def derivedProp&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def parent = new ParentModel(parentProp:"parent")&lt;br /&gt;def derived = new DerivingModel(derivedProp:"derived")&lt;br /&gt;def copiedDerived = parent.copyInto(derived)&lt;br /&gt;assert copiedDerived.parentProp.equals(parent.parentProp)&lt;br /&gt;assert copiedDerived.derivedProp.equals("derived")// throws groovy.lang.MissingPropertyException:&lt;br /&gt;                                                  // No such property: derived&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;How can this be? the DerivingModel class has the derivedProp but after the copyInto invocation its missing!&lt;br /&gt;Lets see what the getProperties method actually returns:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;def parent = new ParentModel(parentProp:"parent")&lt;br /&gt;parent.metaClass.getProperties().each{println it.name}// prints: class, parentProp, metaClass&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;It seems that we don't only get the parentProp that we defined but also the metaClass and class properties, this means that in the derived case the copyInto method has set the metaClass and class values of ParentModel into the DerivedModel instance (causing it to lose access to its derivedProp).&lt;br /&gt;The fix is quite simple:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class ParentModel {&lt;br /&gt;    def String parentProp&lt;br /&gt;    def excludes = ['metaClass']&lt;br /&gt;    def copyInto(other){&lt;br /&gt;        this.metaClass.getProperties().findAll{it.getSetter()!=null}.each{metaProp-&gt;&lt;br /&gt;            // we must not set the metaClass of the current object into the other&lt;br /&gt;            if(metaProp.getProperty(this)!=null &amp;&amp; !excludes.contains(metaProp.name)){&lt;br /&gt;                metaProp.setProperty(other,metaProp.getProperty(this))&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        other&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;There is no need to exclude the class property since it keeps the original even if set.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6534405333058201794?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6534405333058201794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6534405333058201794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6534405333058201794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6534405333058201794'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/03/metaclasses-can-bite.html' title='MetaClasses can bite!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3394723648911558089</id><published>2009-03-01T14:41:00.000-08:00</published><updated>2009-03-01T14:43:35.803-08:00</updated><title type='text'>Clojure on youtube</title><content type='html'>Iv really enjoyed watching the Intro to Clojure series:&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Aoeav_T1ARU&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Aoeav_T1ARU&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;If your interested what the fuss is about check it out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3394723648911558089?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3394723648911558089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3394723648911558089' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3394723648911558089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3394723648911558089'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/03/clojure-on-youtube.html' title='Clojure on youtube'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4670422564275710773</id><published>2009-02-28T11:24:00.000-08:00</published><updated>2009-02-28T13:29:26.829-08:00</updated><title type='text'>GroovyShell bindings validation</title><content type='html'>Groovy 1.6 got released not long a go with a &lt;a href='http://www.infoq.com/articles/groovy-1-6'&gt;load of new features&lt;/a&gt;, one of these is AST transformations which basically lets developers manipulate/access Groovy's AST before it gets loaded into the JVM.&lt;br /&gt;This feature enables some really cool MOP options to mind however iv decided to try it in solving a non MOP-ish issue.&lt;br /&gt;  &lt;br /&gt;The &lt;a href='http://groovy.codehaus.org/api/groovy/lang/GroovyShell.html'&gt;GroovyShell&lt;/a&gt; is a very versatile and useful tool that enables us to evaluate any Groovy script file at runtime:&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;def bindings = [lastDay:2]&lt;br /&gt;def script = """&lt;br /&gt;   import java.util.Calendar&lt;br /&gt;   Calendar cal = Calendar.instance&lt;br /&gt;   cal.set(2009,Calendar.FEBRUARY,2)&lt;br /&gt;   def ghday = cal.time&lt;br /&gt;   cal.set(2009,Calendar.MARCH,lastDay)&lt;br /&gt;   def spring = cal.time&lt;br /&gt;   def days = (ghday..spring).size()&lt;br /&gt;   println days&lt;br /&gt;  """&lt;br /&gt;def shell = new GroovyShell(new Binding(bindings))&lt;br /&gt;shell.evaluate(script)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The script get its input parameters from the bindings hash, forgeting to pass an input variable (lastDay in this case) will cause a groovy.lang.MissingPropertyException to be thrown.&lt;br /&gt;&lt;br /&gt;This is quite reasonable during development time but not in other scenarios in which the script is written in one machine &amp; evaluated on a remote machine.&lt;br /&gt;The exception gets thrown only post its evaluation which might be too late (deep in the execution flow), wouldn't it be nice if it was possible to validate this at will on the client side?&lt;br /&gt;&lt;br /&gt;We could scan the script for suspect variables that might not have been initialised, such scanning might be possible by inspecting the script AST, looking after variables that weren't declared in the current script, Groovy code visitors to the rescue! &lt;br /&gt;&lt;br /&gt;The following implementation matches the bill perfectly:&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm.script.valid&lt;br /&gt;import org.codehaus.groovy.ast.ClassCodeVisitorSupport&lt;br /&gt;import org.codehaus.groovy.ast.expr.MethodCallExpression&lt;br /&gt;import org.codehaus.groovy.control.SourceUnit&lt;br /&gt;import org.codehaus.groovy.ast.expr.VariableExpression&lt;br /&gt;import org.codehaus.groovy.ast.expr.DeclarationExpression&lt;br /&gt;&lt;br /&gt;class ClassCodeVisitorSupportImp extends ClassCodeVisitorSupport {&lt;br /&gt;&lt;br /&gt;    def declared = []&lt;br /&gt;&lt;br /&gt;    def existsByDefault=['context','args']&lt;br /&gt;&lt;br /&gt;    def bindings&lt;br /&gt;&lt;br /&gt;    def notInBindings = {name -&gt; bindings?.keySet().find{it.equals(name)} == null}&lt;br /&gt;&lt;br /&gt;    def notDeclared = {name -&gt; declared?.find{it.text.equals(name)} == null &amp;&amp; !existsByDefault.contains(name)}&lt;br /&gt;&lt;br /&gt;    def notValid = {notDeclared(it.text) &amp;&amp; !it.hasInitialExpression() &amp;&amp; notInBindings(it.text)}&lt;br /&gt;&lt;br /&gt;    def suspectVariables = []&lt;br /&gt;&lt;br /&gt;    public void visitMethodCallExpression(MethodCallExpression methodCall) {&lt;br /&gt;        def variables=methodCall.arguments.expressions.findAll{(it instanceof VariableExpression)}&lt;br /&gt;        suspectVariables &lt;&lt; variables.findAll{notValid(it)}&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void visitDeclarationExpression(final DeclarationExpression decleration){&lt;br /&gt;        declared &lt;&lt; decleration.variableExpression&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected SourceUnit getSourceUnit() {&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This visitor keeps a suspects list of all the variables that are either not in the declared variables or in the bindings hash.&lt;br /&gt;The following class encapsulates the visitor usage:&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm.script.valid&lt;br /&gt;import org.codehaus.groovy.ast.ClassCodeVisitorSupport&lt;br /&gt;import org.codehaus.groovy.ast.ModuleNode&lt;br /&gt;import org.codehaus.groovy.control.SourceUnit&lt;br /&gt;import org.codehaus.groovy.control.CompilationUnit&lt;br /&gt;import org.codehaus.groovy.ast.ClassNode&lt;br /&gt;import org.codehaus.groovy.control.Phases;&lt;br /&gt;&lt;br /&gt;class GroovyScriptValidator {&lt;br /&gt;&lt;br /&gt;    def validate(script,bindings){&lt;br /&gt;        def ast=getAST(script)&lt;br /&gt;        def impl=new ClassCodeVisitorSupportImp()&lt;br /&gt;        impl.bindings=bindings&lt;br /&gt;        impl.visitClass((ClassNode)ast.getClasses().get(0));&lt;br /&gt;        impl.suspectVariables.flatten()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def ModuleNode getAST(String source) {&lt;br /&gt;        SourceUnit unit = SourceUnit.create("Test",source);&lt;br /&gt;        CompilationUnit compUnit = new CompilationUnit();&lt;br /&gt;        compUnit.addSource(unit);&lt;br /&gt;        compUnit.compile(Phases.SEMANTIC_ANALYSIS);&lt;br /&gt;        return unit.getAST();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Validating the script is now simple:&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;package com.jdftm.script.valid&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; *&lt;br /&gt; * @author ronen&lt;br /&gt; */&lt;br /&gt;class InParamValidationTest {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        def bindings = [lastDay:2]&lt;br /&gt;        def script = """&lt;br /&gt;           import java.util.Calendar&lt;br /&gt;&lt;br /&gt;           Calendar cal = Calendar.instance&lt;br /&gt;           cal.set(2009,Calendar.FEBRUARY,2)&lt;br /&gt;           def ghday = cal.time&lt;br /&gt;           cal.set(2009,Calendar.MARCH,lastDay)&lt;br /&gt;           def spring = cal.time&lt;br /&gt;           def days = (ghday..spring).size()&lt;br /&gt;           println days&lt;br /&gt;        """&lt;br /&gt;        def validator = new GroovyScriptValidator()&lt;br /&gt;        def suspects = validator.validate(script,bindings)&lt;br /&gt;        suspects.each{println it.text}&lt;br /&gt;        if(suspects.size()==0){&lt;br /&gt;            def shell = new GroovyShell(new Binding(bindings))&lt;br /&gt;            shell.evaluate(script)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;AST introspection is one cool feature to have!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4670422564275710773?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4670422564275710773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4670422564275710773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4670422564275710773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4670422564275710773'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/02/groovyshell-bindings-validation.html' title='GroovyShell bindings validation'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-8582042940149135640</id><published>2009-01-19T14:16:00.000-08:00</published><updated>2009-01-19T14:46:53.937-08:00</updated><title type='text'>Injecting Closures with Groovy BeanBuilder</title><content type='html'>Programmatic Spring configuration has always appealed to me (can't wait for Spring JavaConfig to come out), the clarity and ability to cut down repetitive configuration meta data is the way to go.&lt;br /&gt;&lt;br /&gt;Groovy eco system has got a lot of builders to configure any thing from build to you'v guessed it right Spring beans.&lt;br /&gt;The BeanBuilder is a Groovy builder (google the pattern) class that enables us to define Spring beans in pure Groovy code, for example:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class AnyPojo {&lt;br /&gt;    def c&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def builder=new BeanBuilder()&lt;br /&gt;def value="yummy"&lt;br /&gt;builder.anyPojo(AnyPojo){&lt;br /&gt;     c=value&lt;br /&gt;}&lt;br /&gt;def context = builder.createApplicationContext()&lt;br /&gt;assert context.getBean("anyPojo").c.equals("yummy")&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note that an external value is injected into the bean (its not a spring bean), this might useful in cases that we want to pass behavior into our Spring beans like so:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;def builder=new BeanBuilder()&lt;br /&gt;def value={"yummy"}// returns "yummy"&lt;br /&gt;builder.anyPojo(AnyPojo){&lt;br /&gt;  c=value&lt;br /&gt;}&lt;br /&gt;def context = builder.createApplicationContext()&lt;br /&gt;assert context.getBean("anyPojo").c.call().equals("yummy")&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This should work!, however upon running this code we get this exception:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;.. Error creating bean with name '(inner bean)': Instantiation of bean failed; nested exception is java.lang.IllegalStateException: No bean class specified on bean definition&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The builder thinks that we are trying to created a nested inner bean:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;builder.anyPojo(AnyPojo){&lt;br /&gt;  c={ SomePojo p-&gt;&lt;br /&gt;     //..&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;No matter what as soon as the builder gets a closure as value for a property it fails.&lt;br /&gt;The best solution that iv found (without altering the BeanBuilder code) is to wrap the closure in a delegating class like so:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class ClosureDelegate {&lt;br /&gt; def c&lt;br /&gt;&lt;br /&gt;    ClosureDelegate(c){&lt;br /&gt;        this.c=c&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def call(){&lt;br /&gt;        c.call()&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def builder=new BeanBuilder()&lt;br /&gt;def value=new ClosureDelegate({"yummy"})// the diff&lt;br /&gt;builder.anyPojo(AnyPojo){&lt;br /&gt;   c=value&lt;br /&gt;}&lt;br /&gt;def context = builder.createApplicationContext()&lt;br /&gt;assert context.getBean("anyPojo").c.call().equals("yummy")// this passes as well&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This way we avoid the call to inner bean builder method (=(Closure c)).&lt;br /&gt;This solution is partial (sometimes closures are applied without a call the the call method), but than again it should do it for most cases (oh and BTW you can get BeanBuilder without Grails from &lt;a href="http://dist.codehaus.org/grails/"&gt;spring spring jar&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-8582042940149135640?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/8582042940149135640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=8582042940149135640' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8582042940149135640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8582042940149135640'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/01/injecting-closures-with-groovy.html' title='Injecting Closures with Groovy BeanBuilder'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3342994813256842539</id><published>2009-01-17T09:52:00.000-08:00</published><updated>2009-01-17T13:00:07.263-08:00</updated><title type='text'>Demystifying Spring wiring process</title><content type='html'>Many Java applications these days make use of Spring IoC, taking the initialization management from the hand of the developer has many benefits but also has a couple of down sides like the lose of some control on the wiring process itself.&lt;br /&gt;&lt;br /&gt;Most of the time its a none issue however there are times in which Spring fails to resolve a dependency and all that the developer is left with is a cryptic stack trace to follow.&lt;br /&gt;&lt;br /&gt;Iv been thinking on how to make it possible to track down Spring weaving process and see at each stage what has been wired up, basically there are three approaches that iv considered:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;The first is to hook into the injection process by some public API, iv decided to drop it since i didn't find any API which notifies me upon beans creation and wiring.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;The second was to wire some Aspect into Spring injection process, iv started to read Spring source code and saw that pin point all the spots in code in which the wiring takes place is very tedious and error prone to start with.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;The third option was to think on Spring as an isolated container that has to interact with the JVM in order to create and inject objects into each other, tracing this interaction sholud give us the log of the injection process itself!&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;A little more digging (see org.springframework.beans.BeanUtils) revealed that Spring uses Java reflection API  (java.lang.reflect.Constructor.newInstance, java.lang.reflect.Field.set) in order to build/wire beans, armed with this knowledge we are only left to devise a method for tracing the calls to these methods.&lt;br /&gt;&lt;br /&gt;A possible option is Btrace, Btrace is a Java agent modeled after DTrace which is capable of instrumenting running Java classes, using the following Btrace script would activate the tracing of the wiring process on all the classes under the com.jdftm package: &lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package jdftm;&lt;br /&gt;&lt;br /&gt;import com.sun.btrace.annotations.*;&lt;br /&gt;import com.sun.btrace.AnyType;&lt;br /&gt;import static com.sun.btrace.BTraceUtils.*;&lt;br /&gt;import java.lang.reflect.Constructor;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.lang.reflect.Field;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;@BTrace public class ReflecTracer {&lt;br /&gt;    @OnMethod(&lt;br /&gt;        clazz="/java.lang.reflect.Constructor/",&lt;br /&gt;        method="/newInstance/"&lt;br /&gt;    )&lt;br /&gt;    public static void anyNewInstance(Constructor con,Object[] args) {&lt;br /&gt;        if(con!=null &amp;&amp; matches("public\\scom\\.jdftm(\\.|\\w*)*\\(\\)",str(con))){&lt;br /&gt;         println(strcat(strcat("Object ",str(con))," got constructed"));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   @OnMethod(&lt;br /&gt;        clazz="/java.lang.reflect.Field/",&lt;br /&gt;        method="/set/"&lt;br /&gt;    )&lt;br /&gt;    public static void anyFieldSet(Field field,Object obj,Object value) {&lt;br /&gt;         println(strcat("Set invoked on ",str(field)));&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Using the script with Btrace involve two steps, compilation:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="bash"&gt;btracec ReflecTracer.java&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Agent attaching (attach before context creation, debugging is an option):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="bash"&gt;btrace &amp;lt;process id, use jps&amp;gt; jdftm/ReflecTracer.class&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The following beans wiring:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class BeanA {&lt;br /&gt;    @Autowired&lt;br /&gt;    private BeanB b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class BeanB {&lt;br /&gt;    @Autowired&lt;br /&gt;    private BeanA a;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt; &lt;br /&gt;&lt;br /&gt;Produces the following traces:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;Object public com.jdftm.spring.context.BeanA() got constructed&lt;br /&gt;Object public com.jdftm.spring.context.BeanB() got constructed&lt;br /&gt;Set invoked on private com.jdftm.spring.context.BeanA com.jdftm.spring.context.BeanB.a&lt;br /&gt;Set invoked on private com.jdftm.spring.context.BeanB com.jdftm.spring.context.BeanA.b&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;br /&gt;An interesting idea that i had is to create a graph out of these traces and give the developer even better visualization on the process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3342994813256842539?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3342994813256842539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3342994813256842539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3342994813256842539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3342994813256842539'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/01/demystifying-spring-wiring-processta.html' title='Demystifying Spring wiring process'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3694637936001299074</id><published>2009-01-10T13:19:00.000-08:00</published><updated>2009-01-10T13:25:19.940-08:00</updated><title type='text'>Learning some Haskell</title><content type='html'>Well iv been studying a little Haskell lately, mainly by reading &lt;a href="http://learnyouahaskell.com/chapters"&gt;Learn You a Haskell for Great Good!&lt;/a&gt;, I can only recommend any one to follow this book, my next read will be &lt;a href="http://book.realworldhaskell.org/read/"&gt;Real world Haskell&lt;/a&gt;.&lt;br /&gt;Functional programing rulz!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3694637936001299074?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3694637936001299074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3694637936001299074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3694637936001299074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3694637936001299074'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2009/01/learning-some-haskell.html' title='Learning some Haskell'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4421559656072331256</id><published>2008-12-25T14:08:00.000-08:00</published><updated>2008-12-25T14:15:03.473-08:00</updated><title type='text'>Pure Java entertainment</title><content type='html'>Iv really enjoyed this &lt;a href="http://www.youtube.com/watch?v=wDN_EYUvUq0"&gt;presentation&lt;/a&gt; about Java puzzlers.&lt;br /&gt;The main moral of this presentation in my mind is that we should relay more on static tools in order to avoid such corner cases (there is no way to remember them all).&lt;br /&gt;Take a look im sure that youl enjoy it as I did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4421559656072331256?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4421559656072331256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4421559656072331256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4421559656072331256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4421559656072331256'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/12/pure-java-entertainment.html' title='Pure Java entertainment'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-169674624870285444</id><published>2008-12-18T12:46:00.000-08:00</published><updated>2008-12-18T13:12:00.610-08:00</updated><title type='text'>VMware recovery methods</title><content type='html'>Iv been using VMware server and player for a time now and usually the hosted OS is XP, it happens to be that iv had the "luck" to witness the crash/corruption of such images and have devised two nifty tricks/methods of data recovery that i think worth sharing.&lt;br /&gt;The first is for data recovery for an unbootable image, it matches cases in which you don't seem to be able to boot XP up but the image itself is readable &amp; loaded by VMware (you see the black screen loading), the basic idea is to change the first boot device of the image to a Linux live cd (Ubuntu works perfectly), after booting up all you need to do is to mount the NTFS folder and copy it out (by scp, thumb drive, etc..).&lt;br /&gt;The second one is more complex and comes to handle a case in which the image dose not load at all (vmware complains about a corrupted vmx file), in order to recover from this state there are a couple of prequisits:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;VMware server installed.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You have another working XP image with a vmx file.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The corrupted image has a snapshot of a working state&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The solution in this case is to copy the working vmx file into the folder of the corrupted image, load this image in VMware server and replace all the hard drive entries with the corrupted machine images, now all that is done is to revert to the last saved snapshot and see how the system is restored!&lt;br /&gt;I hope that these two little methods help you as much as they helped me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-169674624870285444?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/169674624870285444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=169674624870285444' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/169674624870285444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/169674624870285444'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/12/vmware-recovery-methods.html' title='VMware recovery methods'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3275673969337735455</id><published>2008-12-16T13:32:00.000-08:00</published><updated>2008-12-16T14:08:15.378-08:00</updated><title type='text'>Java statefull callbacks</title><content type='html'>Any programmer comes to know callbacks at some point or another, in Java it looks something like this:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public interface Callback {&lt;br /&gt;    void doCall();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class CallbackCosumer {&lt;br /&gt;    public void execute(final Callback callback){&lt;br /&gt;          callback.doCall();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// usage&lt;br /&gt;public class Main {&lt;br /&gt;  public static void main(String[] args) {&lt;br /&gt;    final CallbackConsumer consumer = new CallbackConsumer();&lt;br /&gt;    consumer.execute(new Callback() {&lt;br /&gt;        public void doCall() {&lt;br /&gt;           System.out.println("doing my callback thingy");&lt;br /&gt;        }&lt;br /&gt;     });&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The biggest downside is that its hard to pass calling context state into the rigid callback interface, we could try something like:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class CustomCallback &amp;lt;T&amp;gt; implements Callback {&lt;br /&gt;&lt;br /&gt;    private &amp;lt;T&amp;gt; state;&lt;br /&gt;&lt;br /&gt;    public void doCall() {&lt;br /&gt;        System.out.println(state);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setState(&amp;lt;T&amp;gt; state) {&lt;br /&gt;        this.state = state;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note that this implementation is limiting, the doCall method has to work for any type T, custom behavior will require sub classing (not reasonable expectation from the callback provider). &lt;br /&gt;A somewhat better (the most elegant that iv found to date) solution is to take advantage of another interface:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public interface StatefullCallback&amp;lt;T&amp;gt; extends Callback{&lt;br /&gt;       void addState(T state);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Now we have a custom state object&lt;br /&gt;public static class CustomState {&lt;br /&gt;     // fields .. &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// And usage with a type matching logic&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;   final CallbackConsumer consumer = new CallbackConsumer();&lt;br /&gt;   final StatefullCallback&amp;lt;CustomState&amp;gt; callback=new StatefullCallback&amp;lt;CustomState&amp;gt;() {&lt;br /&gt;       private CustomState state;&lt;br /&gt;&lt;br /&gt;       public void addState(final CustomState state) {&lt;br /&gt;             this.state = state;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       public void doCall() {&lt;br /&gt;         // some custom logic that uses the custom state object&lt;br /&gt;       }&lt;br /&gt;   };&lt;br /&gt;   callback.addState(new CustomState());     &lt;br /&gt;   consumer.execute(callback);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Its quite easy to see how its possible to pass multiple types of state objects into the callback execution context and do it with relative ease, closure-blessed languages require no such hacking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3275673969337735455?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3275673969337735455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3275673969337735455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3275673969337735455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3275673969337735455'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/12/java-statefull-callbacks.html' title='Java statefull callbacks'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-1651239716474770845</id><published>2008-11-21T13:39:00.000-08:00</published><updated>2008-11-21T14:45:22.585-08:00</updated><title type='text'>Keeping your Zen with Linux</title><content type='html'>Creative mp3 players seemed to be a reasonable choice in the early IPod mania days, the single main problem that iv had for years with my trusty Nomad Zen Xtra is the fact that there was no Linux interoperability what so ever, the only (somewhat shaky) solution was to wait for  &lt;a href='http://gnomad2.sourceforge.net/'&gt;Gnomad&lt;/a&gt; to mature.&lt;br /&gt;Things has changed and the Zen access has worked with Gnomad, but two major issues remained:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;No automation possible (like latest podcast copying with a matching playlist generated).&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Ugly and limiting UI to deal with.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;After a bit digging iv found &lt;a href='http://www.adebenham.com/mtpfs/'&gt;mtpfs&lt;/a&gt; which is a FUSE file system that can mount MTP devices, installation and usage are simple as:&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;$ sudo aptitude install mtpfs&lt;br /&gt;$ sudo mkdir /media/zen&lt;br /&gt;$ sudo mtpfs -o allow_other /media/zen/ # allowing other enables non root access to zen folders&lt;br /&gt;$ ls /media/zen&lt;br /&gt;  Music  My Playlists  Playlists  WMPInfo.xml&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;The Music folder holds all the mp3 files in a flat structure and the Playlists folder hold m3u files in the following format (the player root is /):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;/Music/Outlaws64.mp3&lt;br /&gt;/Music/uupc_s01e18_high.mp3&lt;br /&gt;/Music/JavaPosse217.mp3&lt;br /&gt;/Music/seradio-episode117-branSelicOnUML.mp3&lt;br /&gt;/Music/CyberSpeak_98_Nov_16_2008.mp3&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;Its quite easy to see how to automate the podcast download and copying combined with &lt;a href='http://podget.sourceforge.net/'&gt;podget&lt;/a&gt; utility, my Zen has been restored :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-1651239716474770845?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/1651239716474770845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=1651239716474770845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1651239716474770845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1651239716474770845'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/11/keeping-your-zen-with-linux.html' title='Keeping your Zen with Linux'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4143706931249328016</id><published>2008-11-13T11:02:00.000-08:00</published><updated>2008-11-13T12:03:34.760-08:00</updated><title type='text'>Objectifying conditionals</title><content type='html'>Im sure that any programmer has come across a code snippet which included a long list of nested conditionals, like follows:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class NaiveImpl {&lt;br /&gt; public void process(final String option) {// mapping a type code to behaviour&lt;br /&gt;        if (option.equals("first")) {&lt;br /&gt;            // first option .. &lt;br /&gt;        } else if (option.equals("second")) {&lt;br /&gt;            // second option code ..&lt;br /&gt;        }//.. a ton load of other conditionals&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Basically conditionals map between state (option) and behavior (a legacy which is carried from the procedural programming days), multiple conditionals are problematic:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;They include multiple navigation paths in single condensed code sections.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;They have a large number of inter dependencies between them (makes changes hard).&lt;/li&gt;&lt;br /&gt; &lt;li&gt;They are not objects (statements in Java, we cant access them in runtime, they are not "first class citizens").&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;One of my favorite ways of handling type code to behavior mapping without the resort to conditionals is binding Enum values to behavior:&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;   public class CleanImpl {&lt;br /&gt;&lt;br /&gt;    private interface Handler {&lt;br /&gt;        void handle();&lt;br /&gt;    }&lt;br /&gt;    private static Handler firstOptionHandler = new Handler() {&lt;br /&gt;        public void handle() {&lt;br /&gt;            // first option code&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;    private static Handler secondOptionHandler = new Handler() {&lt;br /&gt;        public void handle() {&lt;br /&gt;            // first option code&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    private enum Option {&lt;br /&gt;&lt;br /&gt;        First("first", firstOptionHandler),&lt;br /&gt;        Second("second", secondOptionHandler);// more options to come ..&lt;br /&gt;        private final String name;&lt;br /&gt;        private final Handler handler;&lt;br /&gt;&lt;br /&gt;        private Option(final String name, final Handler handler) {&lt;br /&gt;            this.name = name;&lt;br /&gt;            this.handler = handler;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static Option fromString(final String optionString) {&lt;br /&gt;            for (Option option : values()) {&lt;br /&gt;                if (option.name.equals(optionString)) {&lt;br /&gt;                    return option;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            throw new RuntimeException("no matching option found");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void process(final String option){&lt;br /&gt;        Option.fromString(option).handler.handle();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This code seem to be more verbose at first glance but its more than reasonable to split the handler interface and implementations into separate files (all in one file enables minimal visibility of members and getter-less code), its easy to see how all the above downsides are answered:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;No multiple navigation paths in single condensed code section (each handler is seperated).&lt;/li&gt;&lt;br /&gt; &lt;li&gt;No inter dependencies between different options handling.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;All round objects.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Hopefully will see more usage of similar patterns and enjoy an if-less world!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4143706931249328016?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4143706931249328016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4143706931249328016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4143706931249328016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4143706931249328016'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/11/objectifying-conditionals.html' title='Objectifying conditionals'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3463981353651245483</id><published>2008-10-24T07:05:00.000-07:00</published><updated>2008-11-01T11:52:01.912-07:00</updated><title type='text'>The spreading Java and Ubunut love</title><content type='html'>These days it seems that the Java community is more and more Ubuntu friendly, the integration of Java and Linux (Ubuntu in particular) has been steadily improving making it easy to install (with a bit &lt;a href="http://java.randgestalten.de/?p=31"&gt;tinkering&lt;/a&gt;) Java 6 update 10, Netbeans and other Java goodies.&lt;br /&gt;The Linux and Java open spirit are starting to merge, these are good times to be a Java developer on Linux systems.&lt;br /&gt;&lt;br /&gt;Note:&lt;br /&gt;It seems as if in Ubuntu 8.10 running sudo apt-get install sun-java6-jdk installs 6 update 10 by default.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3463981353651245483?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3463981353651245483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3463981353651245483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3463981353651245483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3463981353651245483'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/10/spreading-java-and-ubunut-love.html' title='The spreading Java and Ubunut love'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-5758329775328255952</id><published>2008-10-20T06:23:00.000-07:00</published><updated>2008-10-20T07:10:48.623-07:00</updated><title type='text'>Oracle Cursor and SimpleJdbcCall</title><content type='html'>The title does sound innocent enough, calling a store procedure by using Spring SimpleJdbcCall should be simple and well &lt;a href="http://static.springframework.org/spring/docs/2.5.x/reference/jdbc.html#jdbc-simple-jdbc-call-1"&gt;documented&lt;/a&gt;, in usual circumstances this is the case however when Oracle Cursor is involved all hell brakes loose.&lt;br /&gt;&lt;br /&gt;An example for such a procedure:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;CREATE PROCEDURE GET_COUNTRIES_BY_INDEPENDECE (cursor OUT  types.ref_cursor , date NUMBER) AS &lt;br /&gt;BEGIN     &lt;br /&gt;  OPEN cursor FOR select * from COUNRTY where INDEPENDENCE &gt;= date;&lt;br /&gt;END;&lt;br /&gt;&lt;br /&gt;-- note that the ref_cursor type has to be declared in a package&lt;br /&gt;&lt;br /&gt;CREATE OR REPLACE PACKAGE types&lt;br /&gt;AS&lt;br /&gt;   TYPE ref_cursor IS REF CURSOR;&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The first problem starts with the fact that the Oracle driver doesn't provide the metadata that Spring requires, this means that the programmer has to define all the in and out parameters by himself and that the metadata depended functionality of Spring has to be disabled (failing to do so make Spring ignore in/out parameter decelerations, verified by Spring source code debugging).&lt;br /&gt;&lt;br /&gt;The second problem is how to make Spring work with the result set that the procedure provides via the cursor, i didn't find any mentioning of this on the web (besides some &lt;a href="http://forum.springframework.org/showthread.php?t=59328"&gt;forum entries&lt;/a&gt; that didn't show a clear solution path), one tutorial that did help was &lt;a href="http://www.enterprisedt.com/publications/oracle/result_set.html"&gt;jdbc&lt;/a&gt; related.&lt;br /&gt;&lt;br /&gt;After a couple of attempts and Spring source code reading iv managed to find a winning solution: &lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;  ParameterizedRowMapper&amp;lt;Map&amp;gt; mapper = new ParameterizedRowMapper&amp;lt;Map&amp;gt;() {&lt;br /&gt;    @Override&lt;br /&gt;    public Map mapRow(ResultSet rs, int rowNum) throws SQLException {&lt;br /&gt;      BasicRowProcessor processor = new BasicRowProcessor();// commons dbutils &lt;br /&gt;      return processor.toMap(rs);&lt;br /&gt;    }&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; final Map in = new HashMap();&lt;br /&gt; in.put(inParam, value);&lt;br /&gt; JdbcTemplate template = new JdbcTemplate(dataSource);&lt;br /&gt; SimpleJdbcCall jdbcCall = new SimpleJdbcCall(template).withProcedureName("GET_COUNTRIES_BY_INDEPENDECE").withCatalogName("CATALOG");&lt;br /&gt;&lt;br /&gt; // taking care of the cursor result set with a custom mapper&lt;br /&gt; jdbcCall.returningResultSet("cursor", mapper);&lt;br /&gt;&lt;br /&gt; // disabling metadata so that Spring won't reject parameter declaration&lt;br /&gt; // this is due to the lacking oracle jdbc driver &lt;br /&gt; jdbcCall.withoutProcedureColumnMetaDataAccess();&lt;br /&gt;&lt;br /&gt; // order matters! spring uses them according to the position in the collection  &lt;br /&gt; jdbcCall.addDeclaredParameter(new SqlOutParameter("cursor",OracleTypes.CURSOR));&lt;br /&gt; jdbcCall.addDeclaredParameter(new SqlParameter(someDateInMili,OracleTypes.NUMERIC));&lt;br /&gt;&lt;br /&gt; List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; result = (List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;) jdbcCall.execute(in).get("cursor");// getting back the result set that was provided by the cursor&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;There are a couple of weird things in this code, first we must declare not only that the call returns a result set but also an out parameter for the cursor, second the order of the deceleration matters! (which makes sense since Spring can't guess the placement of the parameter without metadata).&lt;br /&gt;Thats about it, hopefully iv saved you some time ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-5758329775328255952?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/5758329775328255952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=5758329775328255952' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5758329775328255952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5758329775328255952'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/10/oracle-cursor-and-simplejdbccall.html' title='Oracle Cursor and SimpleJdbcCall'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3901343912849017854</id><published>2008-10-17T08:31:00.000-07:00</published><updated>2008-10-17T08:39:09.120-07:00</updated><title type='text'>Gookup 0.0.3 is out</title><content type='html'>For those of you who don't know Gookup is a backup utility for three Google online main services (Gmail Blogger and Reader), the basic idea is taking back control on your data and back it up.&lt;br /&gt;Its true that Google has some strong back up procedures however even they can't protect you 100%.&lt;br /&gt;&lt;br /&gt;Iv been using it now for a while to back up all my online content on Google servers and its been quite a useful tool, taking back the control on your own data is a liberating experience. &lt;br /&gt;&lt;br /&gt;See the release notes and download link &lt;a href="http://code.google.com/p/gookup/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3901343912849017854?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3901343912849017854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3901343912849017854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3901343912849017854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3901343912849017854'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/10/gookup-003-is-out.html' title='Gookup 0.0.3 is out'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4651941251695608829</id><published>2008-10-03T09:52:00.000-07:00</published><updated>2008-10-03T11:56:22.316-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clojure java svn'/><title type='text'>Closjure it not a spelling mistac ;)</title><content type='html'>Its seems that these days any programmer has to have a triple set of languages in his tool set, the first one is the static imperative which brings on the food to table (Java or C#), the second one is the dynamic imperative one which is fun and productive to use, it saves the ceremony code (let it be Ruby Python or Groovy) and is useful in configuration code, tests and fast prototypes projects.&lt;br /&gt;As for the third type the magic keyword is &lt;span style="font-weight:bold;"&gt;functional&lt;/span&gt;, learning such a language won't make you code faster or more productive (not from day one at least) instead it will make you smarter and could improve the way in which you solve programing problems (functions all the way baby!!).&lt;br /&gt;The main question here is which one to pick from (Scala, Haskell, ML etc..), i won't go deep into which one you should choose but instead propose a surprising contender called &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; (a lisp dialect that runs on the JVM), some of the things that appealed to me from the start about Clojure were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dynamic typing&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Complete Immutability (has STM and persistent collections) no hidden side effects &lt;/li&gt;&lt;br /&gt;&lt;li&gt;REPL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Macros&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Java interop&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Iv made a bold attempt to write a small clj program which emulates svn blame functionality, the implementation is a trimmed version of an existing &lt;a href="https://wiki.svnkit.com/Annotating%20a%20file"&gt;svnkit snippet&lt;/a&gt;:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.util.Date;&lt;br /&gt;import org.tmatesoft.svn.core.SVNException;&lt;br /&gt;import org.tmatesoft.svn.core.SVNURL;&lt;br /&gt;import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;&lt;br /&gt;import org.tmatesoft.svn.core.internal.util.SVNFormatUtil;&lt;br /&gt;import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;&lt;br /&gt;import org.tmatesoft.svn.core.wc.SVNClientManager;&lt;br /&gt;import org.tmatesoft.svn.core.wc.SVNLogClient;&lt;br /&gt;import org.tmatesoft.svn.core.wc.SVNRevision;&lt;br /&gt;&lt;br /&gt;public class Annotations {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;        DAVRepositoryFactory.setup();&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            SVNURL fileURL = SVNURL.parseURIEncoded("http://gookup.googlecode.com/svn/trunk/gookup-jruby/build/artifacts.rb");&lt;br /&gt;            SVNLogClient logClient = SVNClientManager.newInstance().getLogClient();//SVNLogClient is the class with which you can perform annotations &lt;br /&gt;            boolean ignoreMimeType = false;&lt;br /&gt;            boolean includeMergedRevisions = false;&lt;br /&gt;            logClient.doAnnotate(fileURL, SVNRevision.UNDEFINED, SVNRevision.create(1), SVNRevision.HEAD,&lt;br /&gt;                    ignoreMimeType /*not ignoring mime type*/, includeMergedRevisions /*not including merged revisions */,&lt;br /&gt;                    new AnnotationHandler(), null);&lt;br /&gt;        } catch (SVNException svne) {&lt;br /&gt;            System.out.println(svne.getMessage());&lt;br /&gt;            System.exit(1);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static class AnnotationHandler implements ISVNAnnotateHandler {&lt;br /&gt;&lt;br /&gt;        /**&lt;br /&gt;         * Deprecated.&lt;br /&gt;         */&lt;br /&gt;        public void handleLine(Date date, long revision, String author, String line) throws SVNException {&lt;br /&gt;            handleLine(date, revision, author, line, null, -1, null, null, 0);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /**&lt;br /&gt;         * Formats per line information and prints it out to the console.&lt;br /&gt;         */&lt;br /&gt;        public void handleLine(Date date, long revision, String author, String line, Date mergedDate,&lt;br /&gt;                long mergedRevision, String mergedAuthor, String mergedPath, int lineNumber) throws SVNException {&lt;br /&gt;            String revStr = revision &gt;= 0 ? SVNFormatUtil.formatString(Long.toString(revision), 6, false) : "     -";&lt;br /&gt;            String authorStr = author != null ? SVNFormatUtil.formatString(author, 10, false) : "         -";&lt;br /&gt;            System.out.println(revStr + " " + authorStr + " " + line);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public boolean handleRevision(Date date, long revision, String author, File contents) throws SVNException {&lt;br /&gt;            // We do not want our file to be annotated for each revision of the range, but only for the last &lt;br /&gt;            // revision of it, so we return false  &lt;br /&gt;            return false;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void handleEOF() {&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;The Clojure implementation:&lt;br /&gt;(in-ns 'main)&lt;br /&gt;(clojure/refer 'clojure)&lt;br /&gt;(import '(org.tmatesoft.svn.core SVNException SVNURL)&lt;br /&gt;         '(org.tmatesoft.svn.core.wc ISVNAnnotateHandler SVNClientManager SVNLogClient SVNRevision)&lt;br /&gt;         '(org.tmatesoft.svn.core.internal.util SVNDate SVNFormatUtil)&lt;br /&gt;         '(org.tmatesoft.svn.core.internal.io.dav DAVRepositoryFactory))&lt;br /&gt;&lt;br /&gt;(def url "http://gookup.googlecode.com/svn/trunk/gookup-jruby/build/artifacts.rb")&lt;br /&gt;&lt;br /&gt;(def format (fn [notEmpty spacing value] (if notEmpty (SVNFormatUtil/formatString (str value) (long spacing) false) "         -")))&lt;br /&gt;&lt;br /&gt;(def handler (proxy [ISVNAnnotateHandler] []&lt;br /&gt;  (handleLine [date revision author line] ())&lt;br /&gt;  (handleLine [date revision author line mergedDate mergedRevision mergedAuthor mergedPath lineNumber] &lt;br /&gt;      (println (format (&gt;= revision 0) 6 revision)(format (not (nil? author)) 10 author) line))&lt;br /&gt;  (handleRevision [date revision author contents] false)&lt;br /&gt;  (handleEOF [] ())))&lt;br /&gt;&lt;br /&gt;(defn main [args]&lt;br /&gt;  (DAVRepositoryFactory/setup)&lt;br /&gt;  (let [fileURL (. SVNURL parseURIEncoded url)  &lt;br /&gt;        logClient (.. SVNClientManager (newInstance) (getLogClient))&lt;br /&gt;        revision (SVNRevision/create (long 1))]&lt;br /&gt;    (. logClient doAnnotate fileURL SVNRevision/UNDEFINED revision SVNRevision/HEAD false false handler nil))&lt;br /&gt;)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The Clojure implementation is less verbose and demonstrates nicely the how well Java is integrated into the language (note the proxy method that implements the ISVNAnnotateHandler interface), the ".." macro is another nice feature that makes method calls on Java object feel more natural.&lt;br /&gt;Clojure has also function objects (closures), the format closure saves yet more duplication in the handleLine method.&lt;br /&gt;The ugly thing which is common to both implementation is the huge parameters list of svnkit (what were they thinking?).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4651941251695608829?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4651941251695608829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4651941251695608829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4651941251695608829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4651941251695608829'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/10/closjure-it-not-spelling-mistac.html' title='Closjure it not a spelling mistac ;)'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3271310816155934386</id><published>2008-09-27T14:08:00.002-07:00</published><updated>2008-09-28T13:00:43.217-07:00</updated><title type='text'>Custom findbugs detectors and maven</title><content type='html'>Iv been writing a custom find bugs detector during the weekend, the bug that this detector has to detect is String.getBytes() usages, default system encoding is used when converting the char sequence into bytes which can make it work on one machine and fail on another (use String.getBytes(charsetName) instead).&lt;br /&gt;The writing of the detector was not straight forward but im not going to focus on this issue (see &lt;a href="http://www.ibm.com/developerworks/library/j-findbug2/"&gt;this&lt;/a&gt; and &lt;a href="http://dschneller.blogspot.com/2008/04/localegetdefault-findbugs-detector.html"&gt;this&lt;/a&gt;), instead id like to focus on how to create a findbugs plugin by using maven and running it with maven findbugs plugin.&lt;br /&gt;First here is the detector code:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm;&lt;br /&gt;&lt;br /&gt;import java.text.DateFormat;&lt;br /&gt;import java.util.Calendar;&lt;br /&gt;&lt;br /&gt;import org.apache.bcel.generic.ObjectType;&lt;br /&gt;&lt;br /&gt;import edu.umd.cs.findbugs.BugInstance;&lt;br /&gt;import edu.umd.cs.findbugs.BugReporter;&lt;br /&gt;import edu.umd.cs.findbugs.ba.*;&lt;br /&gt;import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;&lt;br /&gt;&lt;br /&gt;public class StringGetBytesDetector extends OpcodeStackDetector {&lt;br /&gt;&lt;br /&gt;    private BugReporter reporter;&lt;br /&gt;    private final ObjectType stringType = ObjectTypeFactory.getInstance("java.lang.String");&lt;br /&gt;    private final static String tBugType = "SGB_STRING_GET_BYTES";&lt;br /&gt;&lt;br /&gt;    public StringGetBytesDetector(BugReporter aReporter) {&lt;br /&gt;        reporter = aReporter;&lt;br /&gt;        new String("").getBytes();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void sawOpcode(int seen) {&lt;br /&gt;        if (seen != INVOKEVIRTUAL) {// we are only interested in method calls&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            ObjectType tType = ObjectTypeFactory.getInstance(getClassConstantOperand());&lt;br /&gt;            if (!tType.subclassOf(stringType) || &lt;br /&gt;                !getClassConstantOperand().equals("java/lang/String") || &lt;br /&gt;                !getNameConstantOperand().equals("getBytes")) {&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            reporter.reportBug(new BugInstance(this,tBugType, NORMAL_PRIORITY).addClassAndMethod(this).addCalledMethod(this).addSourceLine(this));&lt;br /&gt;        } catch (ClassNotFoundException e) {&lt;br /&gt;            AnalysisContext.reportMissingClass(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This class should reside in the src/main/java path of your maven module, findbugs requires another two files to be present in the plugin jar, findbugs.xml (contains bugs and detectors meta data):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;FindbugsPlugin&amp;gt;&lt;br /&gt;&amp;lt;Detector class="com.jdftm.StringGetBytesDetector" speed="fast"/&amp;gt;&lt;br /&gt;&amp;lt;BugPattern abbrev="SGB" type="SGB_STRING_GET_BYTES" category="CORRECTNESS"/&amp;gt;&lt;br /&gt;&amp;lt;/FindbugsPlugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;And messages.xml (contains bug messages and detector description):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;MessageCollection&amp;gt;&lt;br /&gt; &amp;lt;Detector class="com.jdftm.StringGetBytesDetector"&amp;gt;&lt;br /&gt;  &amp;lt;Details&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;This detector warns about String.getBytes uages.&amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;/Details&amp;gt;&lt;br /&gt; &amp;lt;/Detector&amp;gt;&lt;br /&gt; &amp;lt;BugPattern type="SGB_STRING_GET_BYTES"&amp;gt;&lt;br /&gt;   &amp;lt;ShortDescription&amp;gt;Call getBytes on String instance&amp;lt;/ShortDescription&amp;gt;&lt;br /&gt;   &amp;lt;LongDescription&amp;gt;Call getBytes on String instance&amp;lt;/LongDescription&amp;gt;&lt;br /&gt;   &amp;lt;Details&amp;gt;Using String.getBytes is bad!&amp;lt;/Details&amp;gt;&lt;br /&gt; &amp;lt;/BugPattern&amp;gt;&lt;br /&gt;&amp;lt;/MessageCollection&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Both files should reside in the src/main/resources path, the plugin also has the following dependencies:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='xml' name='code'&gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;findbugs&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;findbugs&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;1.3.5&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;org.apache&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&gt;bcel&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&gt;5.2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;asm&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;asm&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;3.1&amp;gt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&gt;asm&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&gt;asm-tree&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;3.&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The easiest way of getting them is by downloading findbugs distribution and deploying them from the lib folder into your favorite maven proxy (artifactory in my case).&lt;br /&gt;All that is left is to deploy the plugin and to add it to your maven findbugs plugin configuration:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='xml' name='code'&gt;&lt;br /&gt;&amp;lt;reporting&amp;gt;&lt;br /&gt; &amp;lt;plugins&amp;gt;&lt;br /&gt;  &amp;lt;plugin&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;findbugs-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.0&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;configuration&amp;gt;&lt;br /&gt;      &amp;lt;effort&amp;gt;Max&amp;lt;/effort&amp;gt;&lt;br /&gt;      &amp;lt;threshold&amp;gt;Low&amp;lt;/threshold&amp;gt;&lt;br /&gt;      &amp;lt;xmlOutput&amp;gt;true&amp;lt;/xmlOutput&amp;gt;&lt;br /&gt;      &amp;lt;debug&amp;gt;true&amp;lt;/debug&amp;gt;&lt;br /&gt;      &amp;lt;pluginList&amp;gt;{artifact_path}/findstringtobyte-1.0.jar&amp;lt;/pluginList&amp;gt;&lt;br /&gt;   &amp;lt;/configuration&amp;gt;&lt;br /&gt;  &amp;lt;/plugin&amp;gt;&lt;br /&gt; &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/reporting&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Thats about all :)&lt;br /&gt;&lt;br /&gt;* A small note:&lt;br /&gt;   The findbugs maven plugin has a &lt;a href="http://jira.codehaus.org/browse/MFINDBUGS-54"&gt;bug in the 1.2.0 release&lt;/a&gt; that was fixed for the 1.2.1 &amp; 2.0 snapshot versions, it prevent the use of custom detector which means that youll need to use one of the snapshots versions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3271310816155934386?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3271310816155934386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3271310816155934386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3271310816155934386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3271310816155934386'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/09/custom-findbugs-detectors-and-maven.html' title='Custom findbugs detectors and maven'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-7590936792578499258</id><published>2008-08-30T08:11:00.000-07:00</published><updated>2008-09-13T11:14:12.131-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='AMF'/><title type='text'>AMF serialization from Java to Flex and back</title><content type='html'>There are some scenarios in which you want to pass objects to and from a Flex application to a Java back end, if your using an Adobe framework (LCDS or BlazeDS) than you get this functionality out of the box however there are some cases that you wish to escape Adobe's grip and uses some third party technology.&lt;br /&gt;Some solutions that may come to mind are JSon or XML, the problem with these solutions is that they may require a lot of bandwidth and even lots of computing power for complex objects graphs, &lt;a href="http://en.wikipedia.org/wiki/Action_Message_Format"&gt;AMF&lt;/a&gt; to the rescue.&lt;br /&gt;AMF is a binary protocol which is used natively by the flash player, with the release of BlazeDS it was made accessible to any Java client that wishes to use it, in order to use AMF we need to serialize an object into bytes and pass it as the payload of any protocol that we choose, the easiest way to do so is to encode the resulting AMF bytes into BASE64 encoding (a format that transforms byte arrays into a readable string form) and append it to the existing payload.&lt;br /&gt;Ill start with the Java side first: &lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import com.google.inject.Inject;&lt;br /&gt;import flex.messaging.endpoints.BaseHTTPEndpoint;&lt;br /&gt;import flex.messaging.io.SerializationContext;&lt;br /&gt;import flex.messaging.io.amf.Amf3Input;&lt;br /&gt;import flex.messaging.io.amf.Amf3Output;&lt;br /&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.ByteArrayOutputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import sun.misc.BASE64Decoder;&lt;br /&gt;import sun.misc.BASE64Encoder;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; *&lt;br /&gt; * @author ronen&lt;br /&gt; */&lt;br /&gt;public class AmfSerializer {&lt;br /&gt;&lt;br /&gt;    @Inject&lt;br /&gt;    private SerializationContext context;&lt;br /&gt;&lt;br /&gt;    public &amp;lt;T&amp;gt; String toAmf(final T source) throws IOException {&lt;br /&gt;        final StringBuffer buffer = new StringBuffer();&lt;br /&gt;        final ByteArrayOutputStream bout = new ByteArrayOutputStream();&lt;br /&gt;        final Amf3Output amf3Output = new Amf3Output(context);&lt;br /&gt;        amf3Output.setOutputStream(bout);&lt;br /&gt;        amf3Output.writeObject(source);&lt;br /&gt;        amf3Output.flush();&lt;br /&gt;        amf3Output.close();&lt;br /&gt;        final BASE64Encoder encoder = new BASE64Encoder();&lt;br /&gt;        return encoder.encode(bout.toByteArray());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public &amp;lt;T&amp;gt; T fromAmf(final String amf) throws ClassNotFoundException, IOException {&lt;br /&gt;        final BASE64Decoder decoder = new BASE64Decoder();&lt;br /&gt;        byte[] input = decoder.decodeBuffer(amf);&lt;br /&gt;        InputStream bIn = new ByteArrayInputStream(input);&lt;br /&gt;        Amf3Input amf3Input = new Amf3Input(context);&lt;br /&gt;        amf3Input.setInputStream(bIn);&lt;br /&gt;        return (T) amf3Input.readObject();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This code uses BlazeDS API (the messaging-core, messaging-common and messaging-remoting jars) in order to serialize an object of type T into AMF byte array the bytes are encoded to a Base64 string, encoding result of an instance of the following VO:&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm.vo;&lt;br /&gt;&lt;br /&gt;import java.util.Date;&lt;br /&gt;&lt;br /&gt;public class CurrentDayVO {&lt;br /&gt;&lt;br /&gt;    private Date now;&lt;br /&gt;&lt;br /&gt;    public CurrentDayVO() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setNow(Date now) {&lt;br /&gt;        this.now = now;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Date getNow() {&lt;br /&gt;        return now;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;might look something like ChMzY29tLmpkZnRtLnZvLkN1cnJlbnREYXlWTwdub3cIAUJrjUw54AAA.&lt;br /&gt;&lt;br /&gt;Now lets turn to the Flex side:&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm.stomp.interop {&lt;br /&gt;  import flash.utils.ByteArray;&lt;br /&gt;  import mx.utils.Base64Encoder;&lt;br /&gt;  import mx.utils.Base64Decoder;&lt;br /&gt;  &lt;br /&gt;  public class AMFSerializer {&lt;br /&gt;     public function serializeToString(value:Object):String{&lt;br /&gt;            if(value==null){&lt;br /&gt;                throw new Error("null isn't a legal serialization candidate");&lt;br /&gt;            }&lt;br /&gt;            var bytes:ByteArray = new ByteArray();&lt;br /&gt;            bytes.writeObject(value);&lt;br /&gt;            bytes.position = 0;&lt;br /&gt;            var be:Base64Encoder = new Base64Encoder();&lt;br /&gt;            be.encodeBytes(bytes);&lt;br /&gt;            var res:String = be.toString();&lt;br /&gt;            be.reset();&lt;br /&gt;            return res;&lt;br /&gt;        }&lt;br /&gt;       &lt;br /&gt;        public function readObjectFromStringBytes(value:String):Object{&lt;br /&gt;            var dec:Base64Decoder=new Base64Decoder();&lt;br /&gt;            dec.decode(value);&lt;br /&gt;            var result:ByteArray=dec.drain();&lt;br /&gt;            result.position=0;&lt;br /&gt;            return result.readObject();&lt;br /&gt;        }         &lt;br /&gt;  }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The logic is quite similar to the Java side code however when using the AMFSerializer we must register the serialized classes prior to serializing them:&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;registerClassAlias("com.jdftm.vo.CurrentDayVO", CurrentDayVO); &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Failing to so will cause the de-serialization process (on both sides) to fail since it uses the alias in order to create the resulting instance object, its also required that the serialized classes on both ends to be in the same package as implemented in the CurrentDayVO Flex class:&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.jdftm.vo{&lt;br /&gt; [Bindable]&lt;br /&gt; [RemoteClass(alias="com.jdftm.vo.CurrentDayVO")]&lt;br /&gt; public class CurrentDayVO{&lt;br /&gt;   private var _now:Date;&lt;br /&gt;  &lt;br /&gt;   public function get now():Date{&lt;br /&gt;    return _now;&lt;br /&gt;   } &lt;br /&gt;   &lt;br /&gt;   public function set now(value:Date):void{&lt;br /&gt;    _now=value;&lt;br /&gt;   }&lt;br /&gt; }  &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As youv seen AMF isn't to hard to use and may prove to be a powerful contender in the  crowded integration protocols market.&lt;br /&gt;&lt;br /&gt;Updated 2/09/08&lt;br /&gt;Here is the SerializationContext implementation which is used in the Java serialization class&lt;br /&gt;&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import com.google.inject.Provider;&lt;br /&gt;import flex.messaging.io.SerializationContext;&lt;br /&gt;&lt;br /&gt;public class SerializationContextProvider implements Provider&amp;lt;SerializationContext&amp;gt; {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public SerializationContext get() {&lt;br /&gt;        SerializationContext serializationContext = SerializationContext.getSerializationContext();// Threadlocal SerializationContent&lt;br /&gt;        serializationContext.enableSmallMessages = true;&lt;br /&gt;        serializationContext.instantiateTypes = true;&lt;br /&gt;        serializationContext.supportRemoteClass = true;// use _remoteClass field&lt;br /&gt;        serializationContext.legacyCollection = false;// false  Legacy Flex 1.5 behavior was to return a java.util.Collection for Array, New Flex 2+ behavior is to return Object[] for AS3 Array&lt;br /&gt;        serializationContext.legacyMap = false;// false Legacy flash.xml.XMLDocument Type&lt;br /&gt;        serializationContext.legacyXMLDocument = false;// true New E4X XML Type&lt;br /&gt;        serializationContext.legacyXMLNamespaces = false;// determines whether the constructed Document is name-space aware&lt;br /&gt;        serializationContext.legacyThrowable = false;&lt;br /&gt;        serializationContext.legacyBigNumbers = false;&lt;br /&gt;        serializationContext.restoreReferences = false;&lt;br /&gt;        serializationContext.logPropertyErrors = false;&lt;br /&gt;        serializationContext.ignorePropertyErrors = true;&lt;br /&gt;        return serializationContext;&lt;br /&gt;&lt;br /&gt;    /*&lt;br /&gt;    serializationContext.enableSmallMessages = serialization.getPropertyAsBoolean(ENABLE_SMALL_MESSAGES, true);&lt;br /&gt;    serializationContext.instantiateTypes = serialization.getPropertyAsBoolean(INSTANTIATE_TYPES, true);&lt;br /&gt;    serializationContext.supportRemoteClass = serialization.getPropertyAsBoolean(SUPPORT_REMOTE_CLASS, false);&lt;br /&gt;    serializationContext.legacyCollection = serialization.getPropertyAsBoolean(LEGACY_COLLECTION, false);&lt;br /&gt;    serializationContext.legacyMap = serialization.getPropertyAsBoolean(LEGACY_MAP, false);&lt;br /&gt;    serializationContext.legacyXMLDocument = serialization.getPropertyAsBoolean(LEGACY_XML, false);&lt;br /&gt;    serializationContext.legacyXMLNamespaces = serialization.getPropertyAsBoolean(LEGACY_XML_NAMESPACES, false);&lt;br /&gt;    serializationContext.legacyThrowable = serialization.getPropertyAsBoolean(LEGACY_THROWABLE, false);&lt;br /&gt;    serializationContext.legacyBigNumbers = serialization.getPropertyAsBoolean(LEGACY_BIG_NUMBERS, false);&lt;br /&gt;    boolean showStacktraces = serialization.getPropertyAsBoolean(SHOW_STACKTRACES, false);&lt;br /&gt;    if (showStacktraces &amp;&amp; Log.isWarn())&lt;br /&gt;    log.warn("The " + SHOW_STACKTRACES + " configuration option is deprecated and non-functional. Please remove this from your configuration file.");&lt;br /&gt;    serializationContext.restoreReferences = serialization.getPropertyAsBoolean(RESTORE_REFERENCES, false);&lt;br /&gt;    serializationContext.logPropertyErrors = serialization.getPropertyAsBoolean(LOG_PROPERTY_ERRORS, false);&lt;br /&gt;    serializationContext.ignorePropertyErrors = serialization.getPropertyAsBoolean(IGNORE_PROPERTY_ERRORS, true);&lt;br /&gt;     */&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is the guice provider which is used when creating such contexts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-7590936792578499258?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/7590936792578499258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=7590936792578499258' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7590936792578499258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7590936792578499258'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/08/amf-serialization-from-java-to-flex-and.html' title='AMF serialization from Java to Flex and back'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-5648216685406535074</id><published>2008-08-22T04:36:00.000-07:00</published><updated>2008-08-22T04:39:17.798-07:00</updated><title type='text'>Google collection API</title><content type='html'>If your using Java collection API you should really see the following presentation about Google collection API, this is truly a gem for any Java programmer:&lt;br /&gt;&lt;br /&gt;The first part&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ZeO_J2OcHYM&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ZeO_J2OcHYM&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The second part:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/9ni_KEkHfto&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/9ni_KEkHfto&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-5648216685406535074?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/5648216685406535074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=5648216685406535074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5648216685406535074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5648216685406535074'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/08/google-collection-api.html' title='Google collection API'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-374460981454663171</id><published>2008-08-21T13:52:00.000-07:00</published><updated>2008-08-21T14:55:47.964-07:00</updated><title type='text'>Code is data or so they say..</title><content type='html'>Iv been writing some custom checkstyle checks, the process of doing so is laborious and annoying, checkstyle uses an ANTLR visitor to allow the programmer to validate the tokens he wishes, this approach doesn't scale too well since it makes the programmer think of the "how" and not on "what", by that i mean that instead of being declarative its imperative.&lt;br /&gt;After writing a couple of those it made me realize that there must be a better tool in which i could &lt;span style="font-weight:bold;"&gt;query&lt;/span&gt; the code instead of running along side the it, as a matter of a fact we are using such a tool every day, the &lt;span style="font-weight:bold;"&gt;IDE&lt;/span&gt;.&lt;br /&gt;In the IDE we search for types, usages and other rather &lt;span style="font-weight:bold;"&gt;limited&lt;/span&gt; queries, we overcome these limitations by traversing the code wisely however there are still much more left be desired, for example the following query:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;select field from classes where class.package=com.jdftm.* and field.visibilty=protected&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;which finds all the protected fields within the com.jdftm package, this kind of queries can be usefully not only on build time but also on development and runtime!&lt;br /&gt;&lt;br /&gt;The runtime usage might sound a bit awkward but it might prove to be very powerful, imagine that we wish to write a test which validates that all the classes in com.jdftm package will not accept null parameters in any of their public methods, its possible to do so with some laborious reflection code but doing with a query tool would be much cleaner and easier to follow.&lt;br /&gt;&lt;br /&gt;It seems that im not the first one to think in this &lt;a href="http://en.wikipedia.org/wiki/SemmleCode"&gt;direction&lt;/a&gt; still i would like to find some library that can run in pure Java code (no IDE dependency).&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;After yet some more googeling iv found yet two more interesting tools &lt;a href="http://sourceforge.net/projects/javaml/"&gt;javaML&lt;/a&gt; and &lt;a href="http://browsebyquery.sourceforge.net/"&gt;bbq&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-374460981454663171?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/374460981454663171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=374460981454663171' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/374460981454663171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/374460981454663171'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/08/code-is-data-or-so-they-say.html' title='Code is data or so they say..'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3379168390829270092</id><published>2008-07-15T14:31:00.000-07:00</published><updated>2008-07-15T14:43:15.769-07:00</updated><title type='text'>snipplr CLI gem</title><content type='html'>Well being a CLI (Bash) kind of guy i really like to master my entire computer experience from within its black and white glory, one of the most frequent usages of CLI in my case is code manipulation.&lt;br /&gt;Its only natural for me that ill be able to access my Snipplr stored snippets straight from the CLI and pipe them along, im not aware for such an existing tool therefor iv decided to create one by myself.&lt;br /&gt;The utility is packaged as a gem (surprisingly named snipplr-rubygem) and should run smoothly on any platform which supports Ruby, find out more &lt;a href='http://github.com/narkisr/snipplr-ruby-gem/tree/master/README'&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3379168390829270092?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3379168390829270092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3379168390829270092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3379168390829270092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3379168390829270092'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/07/snipplr-cli-gem.html' title='snipplr CLI gem'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-2647754885089732945</id><published>2008-07-04T15:51:00.000-07:00</published><updated>2008-07-14T12:37:50.301-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='mocking'/><title type='text'>Mocking &amp; Spring tests</title><content type='html'>Spring supports unit testing quite well, still it seems that its a bit tricky to inject mocks during tests, the documentation does &lt;a href='http://static.springframework.org/spring/docs/2.5.x/reference/testing.html#unit-testing'&gt;states&lt;/a&gt; that using IOC framework can make it easier to do so but doesn't show you how.&lt;br /&gt;Lets take for example the following common scenario, we've got a service that we wish to test which requires a DAO as a part of it functionality:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public interface ListingService {&lt;br /&gt;&lt;br /&gt;    Person getPerson(String id);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public class ListingServiceImpl implements ListingService{&lt;br /&gt;&lt;br /&gt;    @Autowired&lt;br /&gt;    private PersonDAO personDAO;&lt;br /&gt;&lt;br /&gt;    @Transactional&lt;br /&gt;    @Override&lt;br /&gt;    public Person getPerson(final String id) {&lt;br /&gt;      return  personDAO.getPersonById(id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now since we don't want to test the DAO (not integration testing) we are going to need to mock it (&lt;a href='http://www.easymock.org/'&gt;EasyMock&lt;/a&gt;), not only that but we rather use Spring testing framework that can save us a lot of hard wiring since we are already using auto-wiring in our code.&lt;br /&gt;Usually mocking frameworks provides us with a static factory method that takes an interface and returns a proxy object (on which we may define behavior), this conflicts with the auto-wiring functionality since that wiring is performed according to return type of the factory method (Object) and not according to returned object itself (Spring will fail to inject the mocked DAO proxy into the service &lt;a href='http://forum.springframework.org/showthread.php?t=52375'&gt;as discussed here&lt;/a&gt;).&lt;br /&gt;This issue can be resolved by using Spring &lt;a href='http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/beans/factory/FactoryBean.html'&gt;FactoryBean&lt;/a&gt;, this interface includes the getObjectType method that is used by Spring as the return type of this factory (exactly what we need!), all that we need to do is to implement this interface and to delegate the object creation to EasyMock like follows:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='java' name='code'&gt;&lt;br /&gt;public class MocksFactory implements FactoryBean {&lt;br /&gt;&lt;br /&gt;    private Class type;// the created object type&lt;br /&gt;&lt;br /&gt;    public void setType(final Class type) {&lt;br /&gt;        this.type = type;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Object getObject() throws Exception {&lt;br /&gt;        return EasyMock.createMock(type);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Class getObjectType() {&lt;br /&gt;        return type;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public boolean isSingleton() {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now our testing context looks like:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='xml' name='code'&gt;&lt;br /&gt;&amp;lt;beans name spaces...&amp;gt;&lt;br /&gt;&amp;lt;!-- Mocks --&amp;gt;&lt;br /&gt;    &amp;lt;bean id="factory"  class="com.jdftm.springmocks.services.mocks.MocksFactory"  name="PersonDAO"&amp;gt;&lt;br /&gt;        &amp;lt;property name="type" value="com.jdftm.springmocks.dao.PersonDAO"/&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;&amp;lt;!-- The actual service--&amp;gt;&lt;br /&gt;    &amp;lt;bean id="listingService" class="com.jdftm.springmocks.services.ListingServiceImpl" autowire="autodetect"/&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;And our test:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='java' name='code'&gt;&lt;br /&gt;@RunWith(SpringJUnit4ClassRunner.class)&lt;br /&gt;@ContextConfiguration(locations = {"classpath*:spring/mocksContext.xml"})&lt;br /&gt;public class ListingServicesTest {&lt;br /&gt;&lt;br /&gt;    @Autowired&lt;br /&gt;    private ListingService service;&lt;br /&gt;    @Autowired&lt;br /&gt;    private PersonDAO personDAO;&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void setup() {&lt;br /&gt;        expect(personDAO.getPersonById("123")).andReturn(new Person("joe", "123"));&lt;br /&gt;        replay(personDAO);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void simplestTest() {&lt;br /&gt;        Person person = service.getPerson("123");&lt;br /&gt;        assertEquals(person.getId(), "123");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This approach is useful but not very maintainable since we need to specify all the auto-wired properties (mostly mocks) of each service that we wish to test, it would be much nicer if all the properties are automatically injected for us, this may be achieved by resorting to programmatic bean definition:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='java' name='code'&gt;&lt;br /&gt;public class AutoBeanDeclarer implements BeanFactoryPostProcessor {&lt;br /&gt;&lt;br /&gt;    private Class mocksHolder;&lt;br /&gt;&lt;br /&gt;    public void setMocksHolder(final Class mocksHolder) {&lt;br /&gt;        this.mocksHolder = mocksHolder;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void postProcessBeanFactory(final ConfigurableListableBeanFactory context) throws BeansException {&lt;br /&gt;        BeanDefinitionRegistry registry = ((BeanDefinitionRegistry) context);&lt;br /&gt;        for (final Field field : findAllAutoWired()) {&lt;br /&gt;            registerOn(registry, field.getType());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private List&amp;lt;Field&amp;gt; findAllAutoWired() {&lt;br /&gt;        return (List&amp;lt;Field&amp;gt;) CollectionUtils.select(Arrays.asList(mocksHolder.getDeclaredFields()), new Predicate() {&lt;br /&gt;            @Override&lt;br /&gt;            public boolean evaluate(Object field) {&lt;br /&gt;                return ((Field) field).isAnnotationPresent(Autowired.class);&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    private void registerOn(final BeanDefinitionRegistry registry,final Class type){&lt;br /&gt;        MutablePropertyValues values = new MutablePropertyValues();&lt;br /&gt;        values.addPropertyValue(new PropertyValue("type", type));&lt;br /&gt;        RootBeanDefinition definition = new RootBeanDefinition(MocksFactory.class, values);&lt;br /&gt;        registry.registerBeanDefinition("factory"+type.getSimpleName(), definition);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This class implements the BeanFactoryPostProcessor interface which enables the registration of beans as Spring loads up a context, the code scans a provided class for fields that carry the @Autowired annotation and registers for each one a matching mock.&lt;br /&gt;For any number of auto-wired fields the context will contain only a single configure line:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='xml' name='code'&gt; &amp;lt;beans name spaces.../&amp;gt;&lt;br /&gt; &amp;lt;!--Programtic configuration-- &amp;gt;&lt;br /&gt;     &amp;lt;bean id="autoConfigurer" class="com.jdftm.springmocks.services.mocks.AutoBeanDeclarer" p:mocksHolder="com.jdftm.springmocks.services.ListingServiceImpl"/&amp;gt;    &lt;br /&gt; &amp;lt;!-- The actual service--&amp;gt;&lt;br /&gt;    &amp;lt;bean id="listingService" class="com.jdftm.springmocks.services.ListingServiceImpl" autowire="autodetect"/ &amp;gt;&lt;br /&gt; &amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Fruitful mocking to us all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-2647754885089732945?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/2647754885089732945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=2647754885089732945' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2647754885089732945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2647754885089732945'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/07/mocking-spring-tests.html' title='Mocking &amp; Spring tests'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-9064389332380582254</id><published>2008-07-02T14:31:00.000-07:00</published><updated>2008-07-02T14:39:54.711-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby Gem'/><title type='text'>Polish your ruby gems</title><content type='html'>Rubygems was just released (by just i mean a week), for those of you who are no Ruby evangelist it won't ring a bell (Ruby equivalent of maven) for those who do its highly recommended to update.&lt;br /&gt;On my system (Ubuntu with rubygems 1.1) the &lt;i&gt;gem update --system&lt;/i&gt; approach didn't work so iv taken the second path and ran &lt;i&gt;gem install rubygems-update&lt;/i&gt; followed by  &lt;i&gt;update_rubygems&lt;/i&gt;.&lt;br /&gt;Now running &lt;i&gt;gem --version&lt;/i&gt; yield the desired result (1.2).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-9064389332380582254?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/9064389332380582254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=9064389332380582254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9064389332380582254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9064389332380582254'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/07/polish-your-ruby-gems.html' title='Polish your ruby gems'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-8490227820373081977</id><published>2008-06-23T12:36:00.000-07:00</published><updated>2008-07-14T12:21:38.320-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Testing those black sheep</title><content type='html'>One of the common reasonings for not writing tests is that writing tests for some code types isn't always possible nor cost effective, iv nicked them as the BDD black sheep, lets take for example command line API's, such API's are rarely tested &amp; for some good(?) reasons like:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Its so simple, why do we need to test it?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Its hard to access, how can we assert anything in such an environment?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I hate it! let me get over this and get back to the safety zone of my UI!&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;While these are all compelling (&gt;.&lt;) reasons they are only plain excuses, writing command line API's is very tricky, it requires many validations and care in order to function properly, as for the hating part id replace it with deep lovin the sooner the better, command line is the most efficient user API and is here to stay (like it or not).&lt;br /&gt;There are some technical challenges when performing assertions and mimicking user input however they can be easily overcome with two techniques, the first is mocking and its great for mimicking user input, now i know what your thinking, is he bulshitting me or what? how can a simple mock type the damn keyboard!?&lt;br /&gt;Well the simple answer is that it don't have to, lets think for a minute what do we actually need to test (its not stdin!), we don't need to test that the keyboard works and that the typed data was placed correctly into ARGV, we need test how this data is &lt;b&gt;handled&lt;/b&gt;, which means that a mocked data structure has to be created when writing tests, the reason that im using a mock (and not a fixture) is that im assuming that your using some sort of an input parsing framework (your not re inventing the wheel are you??) such as &lt;a href='http://optiflag.rubyforge.org/'&gt;optiflag&lt;/a&gt; (Ruby) or &lt;a href='http://jopt-simple.sourceforge.net/examples.html'&gt;JOpt&lt;/a&gt; (Java) and that this parser has to be mocked in order to provide some nice input into our program entry point.&lt;br /&gt;The second technique is stream redirecting (who?), well its not that complicated lets recap for a minute, the user types in data and gets feedback in the form of text which is spat onto the screen via (youv guessed it write) stdout, this means that in order to assert the functionality of our program all that we need to do is to assert what ever is printed out in different scenarios, this can be achieved by using stream redirection into some sort of buffer, in Ruby such an approach might look somthing like this:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;&lt;br /&gt;def redirect&lt;br /&gt;  orig_defout = $stdout&lt;br /&gt;  $stdout = StringIO.new&lt;br /&gt;  yield&lt;br /&gt;  $stdout.string&lt;br /&gt;ensure&lt;br /&gt;  $stdout = orig_defout&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Which can be used like so:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;&lt;br /&gt;  it "should say hello if -f flag is set" do&lt;br /&gt;    ARGV.flags.should_receive(:h).and_return(true)&lt;br /&gt;    outputStr = redirect { @bash.process }&lt;br /&gt;    outputStr.should eql('Hello!')  &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Don't forget that if there are other wanted side effects (file changes, table updates, etc..) they should be asserted like in any other code that your testing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-8490227820373081977?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/8490227820373081977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=8490227820373081977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8490227820373081977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8490227820373081977'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/06/testing-those-black-sheep.html' title='Testing those black sheep'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3236868199944066235</id><published>2008-06-14T08:57:00.000-07:00</published><updated>2008-06-14T09:10:08.797-07:00</updated><title type='text'>Effective Java Reloaded</title><content type='html'>I don't think that this book needs any introduction (Effective Java written by Josh Bloch), in this day and age in which languages go in and fade out on a daily rate, I feel that we have a still long road to go with Java (and i like it!), checkout this &lt;a href='http://sites.google.com/site/io/effective-java-reloaded'&gt;Effecive Java Reloaded&lt;/a&gt; presentation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3236868199944066235?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3236868199944066235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3236868199944066235' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3236868199944066235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3236868199944066235'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/06/effective-java-reloaded.html' title='Effective Java Reloaded'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-624277699066427006</id><published>2008-06-08T07:02:00.000-07:00</published><updated>2008-06-08T07:28:54.422-07:00</updated><title type='text'>I looooooovve Git!</title><content type='html'>After using Git for a while returning back to subversion is like a step back to stone age, im going to use it in all of my personal projects &lt;a href='http://github.com/narkisr'&gt;narkisr@github&lt;/a&gt;.&lt;br /&gt;Note: An excellent &lt;a href='http://www.gitcasts.com/'&gt;git screencasts&lt;/a&gt; web site.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-624277699066427006?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/624277699066427006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=624277699066427006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/624277699066427006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/624277699066427006'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/06/i-looooooovve-git.html' title='I looooooovve Git!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-9217702751418606672</id><published>2008-06-01T14:29:00.000-07:00</published><updated>2008-07-14T12:22:43.142-07:00</updated><title type='text'>JRuby and the pittfalls of bytes</title><content type='html'>JRuby is an amazing environment to code in, you can get clean concise and elegant Java based code by using Ruby powerful constructs, like for example:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;&lt;br /&gt; JBIStream=java.io.BufferedInputStream&lt;br /&gt;&lt;br /&gt; def read_body_as_stream(method)&lt;br /&gt;    bis = JBIStream.new( method.responseBodyAsStream())&lt;br /&gt;    res = ''&lt;br /&gt;    bytes=Java::byte[8192].new # creating new Java byte primitive array&lt;br /&gt;    count = bis.read( bytes )&lt;br /&gt;    while( count != -1)&lt;br /&gt;      res &lt;&lt; String.from_java_bytes(bytes)&lt;br /&gt;      count = bis.read(bytes);&lt;br /&gt;    end&lt;br /&gt;    bis.close()&lt;br /&gt;    res&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This code basically takes in an Apache commons http method and extracts its body by using its input stream, well almost! &lt;br /&gt;This code contains a nasty and confusing bug, the String.from_java_bytes(bytes) chews up dirty bits on each iteration from its previous one, the soultion:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;&lt;br /&gt;      res &lt;&lt; String.from_java_bytes(bytes)[0,count]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The joy of bytes!!! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-9217702751418606672?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/9217702751418606672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=9217702751418606672' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9217702751418606672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9217702751418606672'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/06/jruby-and-pittfalls-of-bytes.html' title='JRuby and the pittfalls of bytes'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3263976156824213907</id><published>2008-05-27T14:02:00.000-07:00</published><updated>2008-05-27T14:11:07.412-07:00</updated><title type='text'>Gookup second alpha is out!</title><content type='html'>In this version iv improved the Gmail backup process, its now fully resumable (download those Gig's of stored data in one shoot isn't always reasonable), faster and less resource hungry, progress info display.&lt;br /&gt;On the duller side of things iv added a couple of specs and ironed out all sorts of bugs and errors.&lt;br /&gt;Go check it &lt;a href='http://code.google.com/p/gookup/'&gt;out&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3263976156824213907?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3263976156824213907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3263976156824213907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3263976156824213907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3263976156824213907'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/05/gookup-second-alpha-is-out.html' title='Gookup second alpha is out!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6055482352994402062</id><published>2008-05-20T15:18:00.000-07:00</published><updated>2008-05-20T15:44:42.412-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Bash'/><title type='text'>From ugly to usefull</title><content type='html'>Iv encountered a troubling error in Flex remote services, those of you who are familiar with Flex remote Java services know that results of remote services are serialized into Action script objects by the Flex framework so that the RIA client may consume them.&lt;br /&gt;The problem is that due to some weird reason Java Float values are not converted properly into Numeric objects, for example a float value of 1.51 on the server side will be converted into 1.5099999904632568 Numeric value on the client side.&lt;br /&gt;This is actually the same value of new Float(1.51).doubleValue() in Java which leads me to believe that Flex takes float values and converts them into double values (a stupid floating point error).&lt;br /&gt;The only solution that iv found is to return only double values from the server.&lt;br /&gt;&lt;br /&gt;On a different note iv stumbled on &lt;a href='http://www.tenshu.net/terminator/'&gt;this&lt;/a&gt; nifty  called terminator, this tool enables the division of a single bash window into multiple ones (very useful for those multiple ssh sessions) it made me think where else such an approach could work nicely (Firefox?), anyway check it out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6055482352994402062?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6055482352994402062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6055482352994402062' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6055482352994402062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6055482352994402062'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/05/from-ugly-to-usefull.html' title='From ugly to usefull'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-7259607903542689776</id><published>2008-04-28T08:02:00.000-07:00</published><updated>2008-07-14T12:27:28.912-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Search'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Ferret'/><title type='text'>Quick and dirty code search</title><content type='html'>There are some situations in which i need to query some code folder quick and dirty on my hard drive.&lt;br /&gt;There are existing tools like desktop search applications (such as Google desktop) but it usually takes some time for them to index new folders and they are also quite resources hungry. &lt;br /&gt;Bash find utility is also an alternative how ever this tool works best only on Unix machines (NTFS &amp; cygwin's find aren't the best pair for such a use case).&lt;br /&gt;&lt;br /&gt;A nice quick and dirty solution it to use &lt;a href='http://ferret.davebalmain.com/trac/'&gt;Ferret&lt;/a&gt; which is a Ruby text indexing framework inspired by &lt;a href='http://lucene.apache.org/java/docs/index.html'&gt;Apache Lucence&lt;/a&gt; to quickly index the code &amp; search it up, all by using two small snippets of Ruby code!&lt;br /&gt;The code following code is based on this &lt;a href="http://zenmachine.wordpress.com/ferret-indexing-with-ruby/"&gt;entry&lt;/a&gt; which in turn is based on this &lt;a href='http://kasparov.skife.org/blog/src/ruby/ferret.html'&gt;one&lt;/a&gt;, first is the indexing code (index.rb):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;require 'rubygems'&lt;br /&gt;require 'ferret'&lt;br /&gt;require 'find'&lt;br /&gt;include Ferret&lt;br /&gt;&lt;br /&gt;index = Index::Index.new(:default_field =&gt; 'content', :path =&gt; '/tmp/index_folder')# creating the index&lt;br /&gt;ini = Time.now&lt;br /&gt;numFiles=0&lt;br /&gt;IndexedExts=['.java','.properties']# the list of file extensions that we wish to index&lt;br /&gt;Find.find('/code/to/index') do |path|&lt;br /&gt;&lt;br /&gt; if(IndexedExts.find {|ext| path.include?(ext)}==nil)&lt;br /&gt;   next # this file is ignored&lt;br /&gt; end &lt;br /&gt; puts "Indexing: #{path}"&lt;br /&gt; numFiles=numFiles+1&lt;br /&gt;&lt;br /&gt; if FileTest.file? path&lt;br /&gt;  File.open(path) do |file|&lt;br /&gt;   index.add_document(:file =&gt; path, :content =&gt; file.readlines)&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;elapsed = Time.now - ini&lt;br /&gt;puts "Files: #{numFiles}"&lt;br /&gt;puts "Elapsed time: #{elapsed} secs\n"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This code is quite simple, first we are creating an index folder then we use the Find module and iterate all the files which are contained within the 'code/to/search' folder, the files which don't have a matching extension are rejected the  rest have their content added to the index, next is the query code (search.rb):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='ruby' name='code'&gt;require 'rubygems'&lt;br /&gt;require 'ferret'&lt;br /&gt;require 'find'&lt;br /&gt;&lt;br /&gt;wot = ARGV[0]&lt;br /&gt;if wot.nil?&lt;br /&gt; puts "use: search.rb &lt;query&gt;"&lt;br /&gt; exit&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;index = Ferret::Index::Index.new(:default_field =&gt; 'content', :path =&gt; '/tmp/index_folder')&lt;br /&gt;ini = Time.now&lt;br /&gt;puts "Searching.."&lt;br /&gt;docs=0&lt;br /&gt;&lt;br /&gt;index.search_each(wot, options={:limit=&gt;:all}) do |doc, score|&lt;br /&gt; &lt;br /&gt; res= &lt;&lt;STRING_END&lt;br /&gt; -------------------------------------------------------&lt;br /&gt; #{File.basename(index[doc]['file'])} :&lt;br /&gt; #{index.highlight(wot, doc,:field =&gt; :content,:pre_tag =&gt; "-&gt;&gt;",:post_tag =&gt; "&lt;&lt;-")}&lt;br /&gt;STRING_END&lt;br /&gt; puts res              &lt;br /&gt; docs+=1&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;elapsed = Time.now - ini&lt;br /&gt;puts "Elapsed time: #{elapsed} secs\n"&lt;br /&gt;puts "Documents found: #{docs}"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;br /&gt;In this code we first load up the index with the default query field content, the query itself takes its value from the wot parameter, after the query execution the code block prints out the matching highlighting of the found match in the file.&lt;br /&gt;That all about there is to it, see ya.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-7259607903542689776?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/7259607903542689776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=7259607903542689776' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7259607903542689776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7259607903542689776'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/04/quick-and-dirty-code-search.html' title='Quick and dirty code search'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-2897590843847790161</id><published>2008-04-24T07:00:00.000-07:00</published><updated>2008-04-24T07:05:57.427-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Ububtu 8.04 is out!</title><content type='html'>I'm downloading it at the moment, I'm pretty excited over this (more than i was when Leopold came out) &amp; can't wait to get my hands on some of the new features, with its simplicity elegance &amp; power Ubuntu is in my humble opinion one of the best Os's out there, go ahead and give a &lt;a href='http://www.ubuntu.com/'&gt;go&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-2897590843847790161?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/2897590843847790161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=2897590843847790161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2897590843847790161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2897590843847790161'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/04/ububtu-804-is-out.html' title='Ububtu 8.04 is out!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3297182032097863926</id><published>2008-04-21T15:02:00.000-07:00</published><updated>2008-07-14T12:30:06.866-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='FunFx'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Making FunFx Flex 2 compatible</title><content type='html'>Moving to the latest and greatest software version in the enterprise takes time, Flex 3 came out not long ago and so did FunFx which a really cool tool for Flex integration testing.&lt;br /&gt;FunFx got compiled with Flex 3 SDK which means that it won't run with Flex 2 projects out of the box, the developer does states that its possible to compile it from source with Flex 2 SDK however the procedure isn't trivial and took me some trial and error that i hope to save for the rest of you out there.&lt;br /&gt;In order to get a Flex 2 compatible FunFx will need to compile the FunFxAdapter which is a swc library that any testable RIA has to depended upon, go ahead and grab its source from &lt;a href='http://rubyforge.org/frs/download.php/31988/Source-code-0.0.3.zip'&gt;here&lt;/a&gt;,  create a swc project within Flex builder called FunFxAdapter and add the source.&lt;br /&gt;Now open the project properties and add in the following dependencies to the compiler options (your paths may vary):&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='sh' name='code'&gt; &lt;br /&gt;-include-libraries "/Applications/eclipse 3.2.2/Adobe Flex Builder 3 Plug-in/sdks/2.0.1/frameworks/libs/automation.swc" "/Applications/eclipse 3.2.2/Adobe Flex Builder 3 Plug-in/sdks/2.0.1/frameworks/libs/automation_agent.swc"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The compiler options should look like:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_4IH34e52vWk/SA0Ymiqo4UI/AAAAAAAAARM/jaIMm5KY8X0/s1600-h/FunFxAdapter+compiler+options.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_4IH34e52vWk/SA0Ymiqo4UI/AAAAAAAAARM/jaIMm5KY8X0/s200/FunFxAdapter+compiler+options.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191832995847790914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately the FunFxAdapter project depends upon the automation.swc library which was not a part of the Flex 2 SDK (it was introduced in Flex 3 SDK but this version isn't binary compilable with Flex 2 SDK), if your project is a legacy Flex 2 project than its most likely that you have access to this swc.&lt;br /&gt;Compile the project and grab the compiled swc from the bin folder of the project, when adding it to the test target application you'll need to add some more dependencies in order to make it work with the compiled FunFxAdapter swc:&lt;br /&gt;&lt;div class='gray'&gt;&lt;pre class='sh' name='code'&gt; &lt;br /&gt;-include-libraries "/Users/ronen/Documents/workspace/FunFXAdapter/bin/FunFXAdapter.swc" "/Applications/eclipse 3.2.2/Adobe Flex Builder 3 Plug-in/sdks/2.0.1/frameworks/libs/automation.swc" "/Applications/eclipse 3.2.2/Adobe Flex Builder 3 Plug-in/sdks/2.0.1/frameworks/libs/automation_agent.swc" "/Applications/eclipse 3.2.2/Adobe Flex Builder 3 Plug-in/sdks/2.0.1/frameworks/locale/ja_JP/automation_agent_rb.swc"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;hopefully iv saved your valuable time.&lt;br /&gt;After publish comment:&lt;br /&gt;Iv forgot to mention that you should add the AutomationGenericEnv.xml file to the src directory of the main project module and to the application folder under tomcat (a standard FunFx requirements also in the Flex 3 version).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3297182032097863926?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3297182032097863926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3297182032097863926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3297182032097863926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3297182032097863926'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/04/making-funfx-flex-2-compatible.html' title='Making FunFx Flex 2 compatible'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_4IH34e52vWk/SA0Ymiqo4UI/AAAAAAAAARM/jaIMm5KY8X0/s72-c/FunFxAdapter+compiler+options.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6768235643838050521</id><published>2008-04-04T16:31:00.000-07:00</published><updated>2008-04-07T14:03:28.702-07:00</updated><title type='text'>The stuff that kept me busy latly</title><content type='html'>Well this post will serve as a brief summary of some interesting things that i had the chance to mess with lately.&lt;br /&gt;First but not least is Flex and actionscript, iv been pondering with the issue of testing Flex application, yeah sure there is FlexUnit still i wanted something slicker &amp; less buggy to work with.&lt;br /&gt;Iv stumbled upon &lt;a href='http://funfx.rubyforge.org/'&gt;FunFx&lt;/a&gt; which seems to answer my quest, getting it to work with Flex 2 wasn't easy (its compiled with Flex 3 sdk which isn't compatible, the documentation on the matter is lacking), it seems to be quite  capable tool which leverages &lt;a href='http://rspec.info/'&gt;rspec&lt;/a&gt; framework and other Ruby goodies.&lt;br /&gt;Another aspect which started to get my attention lately is functional programing (can you here the buzz?), iv studied Prolog during college but took the imperative way of doing things since than, i guess that my appeal to the subject right now comes from the need to find cool programing paradigms that can take advantage of Function objects in actionscript (the blog sphere is humming with similar ideas), currently im following some &lt;a href='http://www.cs.nott.ac.uk/~gmh/functional.html'&gt;slides&lt;/a&gt; that are a part of an introductory course on functional programing (Haskel as the language of choice).&lt;br /&gt;Gookup work has been delayed a bit, still there has been some progress made to the alpha 2 release. &lt;br /&gt;Thats wraps it for now, happy coding.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6768235643838050521?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6768235643838050521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6768235643838050521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6768235643838050521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6768235643838050521'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/04/stuff-that-kept-me-busy-latly.html' title='The stuff that kept me busy latly'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-654450728510530650</id><published>2008-03-23T12:43:00.001-07:00</published><updated>2008-03-31T00:46:45.526-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cairnagorm'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Entering the Flex realm (with Spring  &amp; Cairnagorm)</title><content type='html'>In this post ill present Flex development combined with the Cairngorm micro architecture &amp;amp; Spring IOC, it should provide an easy  stepping point to any Java developer who wishes to get acquainted with the above. &lt;br /&gt;Ill follow along these action items:&lt;ul&gt;&lt;li&gt;Flex server side setup &amp; Spring related configuration.&lt;/li&gt;&lt;li&gt;Client side setup including Caringorm, Caringen &amp;amp; FlexBuilder.&lt;/li&gt;&lt;li&gt;Simple demo application client side walk through.&lt;/li&gt;&lt;li&gt;Simple demo application server side walk through.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Server side setup&lt;/h4&gt;Flex applications may be deployed on any Java container that supports War deployment, in order to keep things simple will stick with &lt;a href="http://tomcat.apache.org/"&gt;Tomcat&lt;/a&gt;.&lt;br /&gt;Flex enabled War contains not only the default folders and files but also Flex configuration files &amp;amp; Jars, an easy way of getting a working skeleton of such a War is by using the &lt;a href="http://opensource.adobe.com/wiki/display/blazeds/Release+Builds"&gt;BlazeDS&lt;/a&gt; binary distribution (an OSS project which provides the connectivity between Java remote services and Flex RIAs).&lt;br /&gt;All that we need to do is to place the packaged blazeds.war that weve just downloaded into the webapps directory and start tomcat up (bin/./catalina.sh run), tomcat will unpack the War into its exploded form which will use as our base War to work with. &lt;br /&gt;Stop tomcat &amp; take a look at the webapps/blazeds/WEB-INF directory, it contains all the usual files and folders that you might expect with the following exceptions:&lt;ul&gt;&lt;li&gt;The lib folder contains flex Jars.&lt;/li&gt;&lt;li&gt;A new flex folder was added it contains flex configuration files.&lt;/li&gt;&lt;li&gt;Flex servlet &amp; session definitions were added to the web.xml file.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Delete the compressed war (we don't need it anymore), will move on to configure Spring  by getting &lt;a href="http://www.springframework.org/download"&gt;Spring Jar&lt;/a&gt; and placing it into the WEB-INF/lib folder &amp; by adding the following lines to the web.xml file (these will tell tomcat to bootstrap the spring environment):&lt;br /&gt;&lt;pre class="medium"&gt;     &lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;/WEB-INF/applicationContext.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&amp;lt;listener&amp;gt;&lt;br /&gt;  &amp;lt;listener-class&amp;gt;&lt;br /&gt;    org.springframework.web.context.ContextLoaderListener&lt;br /&gt;  &amp;lt;/listener-class&amp;gt;&lt;br /&gt;&amp;lt;/listener&amp;gt;&lt;/pre&gt;&lt;br /&gt;Create the following applicationContext.xml file under WEB-INF:&lt;pre class="small"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&amp;gt;&lt;br /&gt;&amp;lt;beans&amp;gt;&lt;br /&gt;  &amp;lt;!-- Add your spring beans here --&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now its time to integrate Spring &amp;amp; Flex:&lt;ul&gt;&lt;li&gt;Download the following  &lt;a href="http://coenraets.org/downloads/flex-spring.zip"&gt;zip file&lt;/a&gt; &amp; copy the  bin/flex folder into the WEB-INF/classes folder, this folder contains a factory class that enables Flex RIAs to access remote Spring managed beans services.&lt;/li&gt;&lt;li&gt;Add the following lines to flex/services-config.xml file (making Flex aware to the Spring factory):&lt;/li&gt;&lt;/ul&gt;&lt;pre class="small"&gt;&amp;lt;services-config&amp;gt;&lt;br /&gt;    &amp;lt;!-- Rest unchanged --&amp;gt;&lt;br /&gt;    &amp;lt;factories&amp;gt;&lt;br /&gt;      &amp;lt;factory id="spring" class="flex.samples.factories.SpringFactory"/&amp;gt;&lt;br /&gt;    &amp;lt;/factories&amp;gt;&lt;br /&gt;&amp;lt;/services-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Client side and Development environment setup&lt;/h4&gt;&lt;br /&gt;Will use &lt;a href="http://www.adobe.com/products/flex/features/flex_builder/"&gt;FlexBuilder&lt;/a&gt;  eclipse plugin in order to obtain Flex SDK and IDE support (you can use it freely for 60 days), first will create a Flex project with the presented settings:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_4IH34e52vWk/R-1WO_uuCuI/AAAAAAAAAQs/Bv6FZSIVcaQ/s1600-h/flex_porject_setup1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_4IH34e52vWk/R-1WO_uuCuI/AAAAAAAAAQs/Bv6FZSIVcaQ/s200/flex_porject_setup1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5182893561798855394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_4IH34e52vWk/R-1WO_uuCvI/AAAAAAAAAQ0/K5EgTjuG3v0/s1600-h/flex_project_setup2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_4IH34e52vWk/R-1WO_uuCvI/AAAAAAAAAQ0/K5EgTjuG3v0/s200/flex_project_setup2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5182893561798855410" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_4IH34e52vWk/R-1WPPuuCwI/AAAAAAAAAQ8/akHC_ySL69I/s1600-h/flex_project_setup3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_4IH34e52vWk/R-1WPPuuCwI/AAAAAAAAAQ8/akHC_ySL69I/s200/flex_project_setup3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5182893566093822722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Notice that in the last screen iv imported the &lt;a href="http://labs.adobe.com/wiki/index.php/Cairngorm:Cairngorm2.2.1:Download"&gt;Cairngorm.swc&lt;/a&gt; which is an external library (similar to a Jar), Cairngorm provides a structured architecture to use when developing Flex applications (basically conventions that tell what should go where), one of the best introductions to Cairngorm is available on David Tucker's &lt;a href="http://www.davidtucker.net/category/cairngorm/"&gt;blog&lt;/a&gt;.&lt;br /&gt;In order to make things less tedious will use &lt;a href=""&gt;Cairngen&lt;/a&gt; in order to generate the basic Cairngorm folder &amp; files structure (ala rails), Cairngen is ant based and only requires you to change a small number of properties in the project.properties to get going, for our project will use the following ones (remember to adjust the paths):&lt;pre class="large"&gt;################################# PROJECT PROPERTIES ##################################&lt;br /&gt;project.name        =FlexMusicArchiver&lt;br /&gt;root.dir            =/Users/ronen/Documents/workspace/FlexMusicArchiver/src&lt;br /&gt;com.dir             =com&lt;br /&gt;domain.dir          =ronen&lt;br /&gt;project.dir         =MusicArchive&lt;br /&gt;cairngorm.version   =2.2.1&lt;br /&gt;&lt;br /&gt;################################# CREATING SEQUENCES ##################################&lt;br /&gt;sequence.name       =GetAlbumList&lt;br /&gt;&lt;br /&gt;################################### CREATING VOs ######################################&lt;br /&gt;vo.name             =Album&lt;br /&gt;&lt;br /&gt;#################### ENABLE REGISTER REMOTE CLASS META-DATA IN VO #####################&lt;br /&gt;vo.remoteClass      =false&lt;br /&gt;&lt;br /&gt;############################### READ / WRITE MANAGEMENT ###############################&lt;br /&gt;overwrite.files     =false&lt;br /&gt;prompt.on.delete    =true&lt;br /&gt;&lt;br /&gt;################################## LOG MODIFICATIONS ##################################&lt;br /&gt;log.output          =true&lt;br /&gt;&lt;br /&gt;################################ PROTECTED PROPERTIES #################################&lt;br /&gt;namespace           =${com.dir}.${domain.dir}.${project.dir}&lt;br /&gt;project-uri         =${root.dir}/${com.dir}/${domain.dir}/${project.dir}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Simple demo application client side walk through&lt;/h4&gt;&lt;br /&gt;Fire up ant under Caringen folder, the basic project structure will get generated:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_4IH34e52vWk/R-4-MPuuCxI/AAAAAAAAARE/KtWThevEPuQ/s1600-h/post+Cairngen+project+structure.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_4IH34e52vWk/R-4-MPuuCxI/AAAAAAAAARE/KtWThevEPuQ/s200/post+Cairngen+project+structure.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5183148601251859218" /&gt;&lt;/a&gt;&lt;br /&gt;The FlexMusicArchiver.mxml file serves as the main entry point to the application, paste in the following code lines into it:&lt;pre class="medium"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;mx:Application&lt;br /&gt;        xmlns:mx="http://www.adobe.com/2006/mxml"&lt;br /&gt;        xmlns:control="com.ronen.MusicArchive.control.*"&lt;br /&gt;        xmlns:business="com.ronen.MusicArchive.business.*"&lt;br /&gt;        layout="absolute" xmlns:view="com.ronen.MusicArchive.view.*"&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;!-- The component that contains remote services declerations--&amp;gt;&lt;br /&gt;   &amp;lt;business:Services/&amp;gt;&lt;br /&gt;   &amp;lt;!-- The application contoler which stores events to commands mappings--&amp;gt;&lt;br /&gt;   &amp;lt;control:FlexMusicArchiverController/&amp;gt;&lt;br /&gt;   &amp;lt;!-- A simple view component--&amp;gt;&lt;br /&gt;   &amp;lt;view:AlbumsList/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/mx:Application&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now create a new Flex component named AlbumsList.mxml under the view folder and add in these code lines:&lt;pre class="large"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&amp;lt;mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" &gt;&lt;br /&gt;        &amp;lt;mx:Script&amp;gt;&lt;br /&gt;                &amp;lt;![CDATA[&lt;br /&gt;                import mx.controls.Image;&lt;br /&gt;                import com.ronen.MusicArchive.vo.Album;&lt;br /&gt;                import com.ronen.MusicArchive.events.AlbumsFetchEvent;&lt;br /&gt;                import mx.events.ListEvent;&lt;br /&gt;                import com.ronen.MusicArchive.model.ModelLocator;&lt;br /&gt;&lt;br /&gt;                private var  model:ModelLocator=ModelLocator.getInstance();&lt;br /&gt;                private var  currAlbumPath:String;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                private function fetchAlbums(e:MouseEvent){&lt;br /&gt;                        var fetchEvent:AlbumsFetchEvent=new AlbumsFetchEvent();&lt;br /&gt;                        fetchEvent.dispatch();&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                private function albumSelected(event:Event){&lt;br /&gt;                        if(event.target.selectedItem!=null){&lt;br /&gt;                          this.currAlbumPath=Album(event.target.selectedItem).coverPath ;&lt;br /&gt;                          this.albumCover.load("http://localhost:8080/blazeds/images/"+this.currAlbumPath);&lt;br /&gt;                        }&lt;br /&gt;                }&lt;br /&gt;                ]]&amp;gt;&lt;br /&gt;        &amp;lt;/mx:Script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:Panel&amp;gt;&lt;br /&gt; &amp;lt;mx:Grid width="100%" height="100%" borderStyle="solid"&amp;gt;&lt;br /&gt;  &amp;lt;mx:GridRow&amp;gt;&lt;br /&gt;    &amp;lt;mx:GridItem&amp;gt;&lt;br /&gt;      &amp;lt;mx:Text id="title" text="A list of all albums:" fontSize="12"/&amp;gt;&lt;br /&gt;    &amp;lt;/mx:GridItem&amp;gt;&lt;br /&gt;  &amp;lt;/mx:GridRow&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;mx:GridRow&amp;gt;&lt;br /&gt;    &amp;lt;mx:GridItem&amp;gt;&lt;br /&gt;      &amp;lt;mx:DataGrid id="albums" dataProvider="{model.albums}" change="albumSelected(event)"&amp;gt;&lt;br /&gt;       &amp;lt;mx:columns&amp;gt;&lt;br /&gt;         &amp;lt;mx:DataGridColumn dataField="artist" headerText="Artist"/&amp;gt;&lt;br /&gt;         &amp;lt;mx:DataGridColumn dataField="title" headerText="Album title"/&amp;gt;&lt;br /&gt;       &amp;lt;/mx:columns&amp;gt;&lt;br /&gt;      &amp;lt;/mx:DataGrid&amp;gt;&lt;br /&gt;     &amp;lt;/mx:GridItem&amp;gt;&lt;br /&gt;                &lt;br /&gt;     &amp;lt;mx:GridItem&amp;gt;&lt;br /&gt;       &amp;lt;mx:Image id="albumCover" width="200" height="200"/&amp;gt;&lt;br /&gt;     &amp;lt;/mx:GridItem&amp;gt;&lt;br /&gt;  &amp;lt;/mx:GridRow&amp;gt;&lt;br /&gt;  &amp;lt;mx:GridRow&amp;gt;&lt;br /&gt;     &amp;lt;mx:GridItem&amp;gt;&lt;br /&gt;       &amp;lt;mx:Button id="fetch" label="fetch albums" click="{fetchAlbums(event)}"/&amp;gt;&lt;br /&gt;     &amp;lt;/mx:GridItem&amp;gt;&lt;br /&gt;   &amp;lt;/mx:GridRow&amp;gt;&lt;br /&gt;  &amp;lt;/mx:Grid&amp;gt;&lt;br /&gt;&amp;lt;/mx:Panel&amp;gt;&lt;br /&gt;&amp;lt;/mx:Canvas&amp;gt;&lt;/pre&gt;&lt;br /&gt;This component makes use of a Grid layout to setup its UI components which includes: a DataGrid which is binded to the model.albums list (The Carinagorm ModelLocator idiom is used in order to get a reference to this list), an Image (its source is taken from the albumCover variable) and a fetch albums button that triggers the dispatching of the fetchEvent (the dispatching of the event in the fetchAlbums method is another Cairngorm idiom).&lt;br /&gt;Add in the albums ArrayCollection deceleration to the model/ModelLocator.as file:&lt;pre class="medium"&gt;package com.ronen.MusicArchive.model&lt;br /&gt;{&lt;br /&gt; import com.adobe.cairngorm.CairngormError;&lt;br /&gt; import com.adobe.cairngorm.CairngormMessageCodes;&lt;br /&gt; import com.adobe.cairngorm.model.IModelLocator;&lt;br /&gt; import mx.collections.ArrayCollection;&lt;br /&gt;    &lt;br /&gt;    [Bindable]&lt;br /&gt;    public final class ModelLocator implements IModelLocator{&lt;br /&gt;  public var albums:ArrayCollection;&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * Defines the Singleton instance of the Application ModelLocator&lt;br /&gt;   */&lt;br /&gt;  private static var instance:ModelLocator;&lt;br /&gt;&lt;br /&gt;         public function ModelLocator(access:Private){&lt;br /&gt;    if (access == null){&lt;br /&gt;            throw new CairngormError(CairngormMessageCodes.SINGLETON_EXCEPTION, "ModelLocator" );&lt;br /&gt;           }&lt;br /&gt;    instance = this;&lt;br /&gt;  }&lt;br /&gt;   &lt;br /&gt;  /**&lt;br /&gt;   * Returns the Singleton instance of the Application ModelLocator&lt;br /&gt;   */&lt;br /&gt;  public static function getInstance() : ModelLocator{&lt;br /&gt;   if (instance == null){&lt;br /&gt;    instance = new ModelLocator( new Private() );&lt;br /&gt;   }&lt;br /&gt;   return instance;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;/**&lt;br /&gt; * Inner class which restricts constructor access to Private&lt;br /&gt; */&lt;br /&gt;class Private {}&lt;/pre&gt;&lt;br /&gt;This class is a singleton which gives an easy access to model data as we've seen in the AlbumsView component.&lt;br /&gt;Now will head on to and create the events/AlbumsFetchEvent.as class:&lt;pre class="medium"&gt;package com.ronen.MusicArchive.events&lt;br /&gt;{&lt;br /&gt;        import com.adobe.cairngorm.control.CairngormEvent;&lt;br /&gt;&lt;br /&gt;        import flash.events.Event;&lt;br /&gt;&lt;br /&gt;        public class AlbumsFetchEvent extends CairngormEvent&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;                public static const FETCH_ALBUMS:String = "FetchAlbums";&lt;br /&gt;&lt;br /&gt;                public function AlbumsFetchEvent(){&lt;br /&gt;                        super(FETCH_ALBUMS);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                override public function clone():Event{&lt;br /&gt;                        return new AlbumsFetchEvent();&lt;br /&gt;                }&lt;br /&gt;        }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This class does nothing more than to define the event that will be fired upon the fetch button click in the view, notice that it defines a constant value that will be used in the controller to map the event to its command, lets add the mapping in the control/FlexMusicArchiverController class:&lt;pre class="medium"&gt;package com.ronen.MusicArchive.control&lt;br /&gt;{&lt;br /&gt;    import com.adobe.cairngorm.control.FrontController;&lt;br /&gt;    import com.ronen.MusicArchive.commands.*;&lt;br /&gt;    import com.ronen.MusicArchive.events.*;&lt;br /&gt;&lt;br /&gt;        public final class FlexMusicArchiverController extends FrontController{&lt;br /&gt;                public function FlexMusicArchiverController(){&lt;br /&gt;                        this.initialize();&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                private function initialize() : void{&lt;br /&gt;                   this.addCommand(AlbumsFetchEvent.FETCH_ALBUMS,AlbumsFetchCommand);&lt;br /&gt;                }&lt;br /&gt;        }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;As you can see weve added the mappings in the initialize method to a AlbumsFetchCommand class which we need also to implement, create the following commands/AlbumsFetchCommand.as class:&lt;pre class="medium"&gt;package com.ronen.MusicArchive.commands&lt;br /&gt;{&lt;br /&gt;        import com.adobe.cairngorm.commands.ICommand;&lt;br /&gt;        import com.adobe.cairngorm.control.CairngormEvent;&lt;br /&gt;        import com.ronen.MusicArchive.business.AlbumsFetchDelegate;&lt;br /&gt;        import com.ronen.MusicArchive.events.AlbumsFetchEvent;&lt;br /&gt;        import com.ronen.MusicArchive.model.ModelLocator;&lt;br /&gt;&lt;br /&gt;        import mx.collections.ArrayCollection;&lt;br /&gt;        import mx.rpc.IResponder;&lt;br /&gt;&lt;br /&gt;        public class AlbumsFetchCommand  implements ICommand, IResponder{&lt;br /&gt;                public function AlbumsFetchCommand(){&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                public function execute(event:CairngormEvent):void {&lt;br /&gt;                  var fetchEvent:AlbumsFetchEvent = event as AlbumsFetchEvent;&lt;br /&gt;                  var delegate:AlbumsFetchDelegate = new AlbumsFetchDelegate( this );&lt;br /&gt;                  delegate.fetchAlbums();&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                public function result( event:Object ):void {&lt;br /&gt;                  ModelLocator.getInstance().albums=ArrayCollection(event.result);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                public function fault( event:Object ):void {&lt;br /&gt;                  trace("CONNECTION ERROR");&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This class implement two Cairngorm interfaces, the first ICommand requires the implementation of the execute method which calls for the AlbumsFetchDelegate fetchAlbums method (the delegate acts as a bridge between the Flex application and the remote services calls, this makes it easy to swap different services implementations without changing command execution logic). &lt;br /&gt;The second one is the IResponder which requires the implementation of the result method, this method will be called upon by the delegate after the service result has been fetched (notice that a reference to the command object is passed to the delegate constructor), now will create the business/AlbumsFetchDelegate.as class:&lt;pre class="large"&gt;package com.ronen.MusicArchive.business&lt;br /&gt;{&lt;br /&gt; import mx.rpc.IResponder;&lt;br /&gt; import com.adobe.cairngorm.business.ServiceLocator;&lt;br /&gt; &lt;br /&gt; public class AlbumsFetchDelegate{&lt;br /&gt;     private var responder:IResponder;&lt;br /&gt;        private var service:Object;&lt;br /&gt;        &lt;br /&gt; public function AlbumsFetchDelegate(responder:IResponder){&lt;br /&gt;   this.responder=responder;&lt;br /&gt;   this.service = ServiceLocator.getInstance().getRemoteObject("fetchAlbums");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public function fetchAlbums(){&lt;br /&gt;          var call:Object=this.service.fetchAlbums();&lt;br /&gt;          call.addResponder(responder);&lt;br /&gt;          trace('fetch called');&lt;br /&gt;        }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This class access the ServiceLocator singleton (registers remote services) in order to get a reference to the fetch albums service, add the following declaration to the business/Services.mxml file:&lt;pre class="small"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml" &lt;br /&gt;                       xmlns:cairngorm="com.adobe.cairngorm.business.*"&amp;gt;&lt;br /&gt;                      &lt;br /&gt;    &amp;lt;mx:RemoteObject id="fetchAlbums" destination="albumsService"/&amp;gt;&lt;br /&gt;    &lt;br /&gt;&amp;lt;/cairngorm:ServiceLocator&amp;gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;One last class before we can call it off (on the client side) is the vo/Album.as:&lt;pre class="medium"&gt;&lt;br /&gt;package com.ronen.MusicArchive.vo{&lt;br /&gt;   //The com.ronen.musicarchive.AlbumVO tells Flex that Album.as maps to AlbumVO.java&lt;br /&gt;   [RemoteClass(alias="com.ronen.musicarchive.AlbumVO")]&lt;br /&gt;    public class Album{&lt;br /&gt;&lt;br /&gt;    public var artist:String;&lt;br /&gt;&lt;br /&gt;    public var title:String;&lt;br /&gt;&lt;br /&gt;    public var coverPath:String;&lt;br /&gt;&lt;br /&gt;    public function Album(){&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This class gives us a single coherent class to work with inside the Flex view classes without depending on the format which the service returns back (the conversion takes place at the command result method).&lt;br /&gt;&lt;h4&gt;Simple demo application server side walk through&lt;/h4&gt;&lt;br /&gt;Will need to expose &amp; create this service at the server side, will start by adding the following to the WEB-INF/flex/remoting-config.xml file (the file which exposes services to Flex RIAs):&lt;pre class="medium"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;service id="remoting-service"&lt;br /&gt;    class="flex.messaging.services.RemotingService"&amp;gt;&lt;br /&gt;    &amp;lt;!--rest unchanged--&amp;gt;&lt;br /&gt;    &amp;lt;destination id="albumsService"&amp;gt;&lt;br /&gt;      &amp;lt;properties&amp;gt;&lt;br /&gt;       &amp;lt;factory&amp;gt;spring&amp;lt;/factory&amp;gt;&lt;br /&gt;       &amp;lt;!--This is the spring bean id which is declared in the applicationContext.xml file--&amp;gt;&lt;br /&gt;       &amp;lt;source&amp;gt;albumsDao&amp;lt;/source&amp;gt;&lt;br /&gt;      &amp;lt;/properties&amp;gt;&lt;br /&gt;    &amp;lt;/destination&amp;gt;&lt;br /&gt;&amp;lt;/service&amp;gt;&lt;/pre&gt;&lt;br /&gt;The albumsDao is actually the Spring bean id that we are about to create:&lt;pre class="small"&gt;&lt;br /&gt;package com.ronen.musicarchive;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;&lt;br /&gt;public interface AlbumsDao {&lt;br /&gt;  Collection&lt;AlbumVO&gt; fetchAlbums();  &lt;br /&gt;}&lt;/pre&gt;Now the implementation:&lt;pre class="medium"&gt;&lt;br /&gt;package com.ronen.musicarchive;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;&lt;br /&gt;public class HardCodedAlbumsDao implements AlbumsDao {&lt;br /&gt;    public Collection&lt;AlbumVO&gt; fetchAlbums() {&lt;br /&gt;     Collection&lt;AlbumVO&gt; result = new ArrayList&lt;AlbumVO&gt;();&lt;br /&gt;     result.add(new AlbumVO("the bends", "radio head", "Radiohead.bends.albumart.jpg"));&lt;br /&gt;      result.add(new AlbumVO("MGMT", "latest fav", "MGMT_oracular_spectacular.jpg"));&lt;br /&gt;      return result;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The returned VO has to be created:&lt;pre class="large"&gt;&lt;br /&gt;package com.ronen.musicarchive;&lt;br /&gt;&lt;br /&gt;public class AlbumVO {&lt;br /&gt;&lt;br /&gt; private String title;&lt;br /&gt; &lt;br /&gt; private String artist;&lt;br /&gt; &lt;br /&gt; private String coverPath;&lt;br /&gt;&lt;br /&gt; public AlbumVO(){&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public AlbumVO(String title, String artist, String coverPath) {&lt;br /&gt;  this.title = title;&lt;br /&gt;  this.artist = artist;&lt;br /&gt;  this.coverPath = coverPath;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getTitle() {&lt;br /&gt;  return title;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setTitle(String title) {&lt;br /&gt;  this.title = title;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getArtist() {&lt;br /&gt;  return artist;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setArtist(String artist) {&lt;br /&gt;  this.artist = artist;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getCoverPath() {&lt;br /&gt;  return coverPath;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setCoverPath(String coverPath) {&lt;br /&gt;  this.coverPath = coverPath;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This simple hard coded DAO dosn't require too much elaboration, just copy the compiled interface and class into the WEB-INF/classes folder, don't forget also to declare the DAO inside the application context file:&lt;pre class="tiny"&gt;&lt;br /&gt;&amp;lt;bean id="albumsDao" class="com.ronen.musicarchive.HardCodedAlbumsDao"/&amp;gt;&lt;/pre&gt;&lt;br /&gt;If you got this far, start tomcat up and launch the FlexMusicArchiver.mxml file (inside eclipse right click Run as-&gt;Flex Application), if all went well you should see the application up and running :)&lt;br /&gt;&lt;br /&gt;Troubleshooting, make sure that:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tomcat has loaded witout any exceptions.&lt;/li&gt;&lt;li&gt;The Flex SWF compiles without errors.&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-654450728510530650?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/654450728510530650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=654450728510530650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/654450728510530650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/654450728510530650'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/03/flex-spring-cairnagorm.html' title='Entering the Flex realm (with Spring  &amp; Cairnagorm)'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_4IH34e52vWk/R-1WO_uuCuI/AAAAAAAAAQs/Bv6FZSIVcaQ/s72-c/flex_porject_setup1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-620618840369400225</id><published>2008-03-17T14:08:00.000-07:00</published><updated>2008-03-22T10:06:18.878-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jar'/><category scheme='http://www.blogger.com/atom/ns#' term='packaging'/><category scheme='http://www.blogger.com/atom/ns#' term='Jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>JRuby application packaging P-1</title><content type='html'>Any Info which regards the packaging of JRuby applications is quite scarce, in Java the options are clear and for the most part there is only one option (jar as you might have guessed already), jars aren't designed to carry Ruby code within them, they don't mix with the Ruby ecosystem too well (the interpreter cant run them directly, not without some wrapping) and they force some adjustments (like a Main Java class as an entry point).&lt;br /&gt;Luckily JRuby does support Ruby's packaging system (&lt;a href="http://www.rubygems.org/"&gt;rubygems&lt;/a&gt;) which offers some interesting options, still there are some pitfalls and issues to solve such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The creation/installation/distribution of a JRuby gem.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Jars and gems mixing (what is the correct mixture?).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Automation and build integration.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;In this post and the following one ill try to introduce some  solutions to these issues starting with the basic gem packaging procedure.&lt;br /&gt;&lt;br /&gt;A useful tool for dealing with gems is &lt;a href="http://newgem.rubyforge.org/"&gt;newgem&lt;/a&gt;, newgem is a command line utility which generates a skeleton of folders &amp; files, this approach is the easiest way to get going: &lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 55px;"&gt;&lt;br /&gt; newgem dummy # our dummy project gem  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;the resulting dummy folder will contain:&lt;pre&gt;&lt;br /&gt;History.txt   Rakefile lib setup.rb &lt;br /&gt;License.txt   log tasks   website&lt;br /&gt;Manifest.txt  config pkg test&lt;br /&gt;README.txt    doc script  tmp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The lib folder is the destination of our Ruby code, at its post creation state this folder contains an empty folder which carries the application name and a single matching ruby script:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 155px;"&gt;&lt;br /&gt;$:.unshift File.dirname(__FILE__)&lt;br /&gt;&lt;br /&gt;module AppName&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;  &lt;br /&gt;This script is the gateway to your application (it includes the first lines of code that will be executed upon gem requiring), in its naked form it only adds the code under the lib/app_name path to the interpreter's load path variable (LOAD_PATH aka $: which is an array), this will enable access to the the rest of the code:&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 155px;"&gt;&lt;br /&gt;# this loads up the gem&lt;br /&gt;gem 'dummy'&lt;br /&gt;# this will load up lib/dummy.rb and add /lib/dummy to $:&lt;br /&gt;require 'dummy'&lt;br /&gt;# now we may require any other piece of code under dummy&lt;br /&gt;require 'dummy/bla'&lt;/pre&gt;Any to be packaged file &amp; folder should have its name appended to the Manifest.txt file.&lt;br /&gt;&lt;br /&gt;All that is left in order to package our code into a gem is to invoke:&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 105px;"&gt;&lt;br /&gt;rake package # The resulting gem will be placed under the pkg folder.&lt;br /&gt;jruby -S gem pkg/app_name_version.gem # this will install it into the JRuby environment &lt;br /&gt;&lt;/pre&gt;Another nice feature that newgem offers is the ability to create a binary command (like rake, rails) which is integrated into the Ruby environment along side the gem installation:&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 55px;"&gt;ruby script/generate executable dummy # run this under the generated folder path&lt;/pre&gt; &lt;br /&gt;This will generate a bin folder which contains a single file, all that is left is to append the desired functionality at the bottom of this file and add it to the Manifest.txt.&lt;br /&gt; &lt;br /&gt;Summary:&lt;br /&gt;In this post wev'e taken a look on basic gem creation, on the next one ill explain how to inject jar's into our gem and take a look on some automated newgem manipulation with buildr &amp; rake.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-620618840369400225?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/620618840369400225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=620618840369400225' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/620618840369400225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/620618840369400225'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/03/jruby-application-packaging-p-1.html' title='JRuby application packaging P-1'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-9206909795430614359</id><published>2008-03-11T01:29:00.000-07:00</published><updated>2008-03-11T05:32:51.744-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gookup'/><title type='text'>First gookup version released to the wild!</title><content type='html'>Iv uploaded the first version of &lt;a href="http://code.google.com/p/gookup/"&gt;gookup&lt;/a&gt; &amp; im quite happy with it, there's still more work to be done (as always) how ever im happy to say that from inception to realization this is all mine :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-9206909795430614359?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/9206909795430614359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=9206909795430614359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9206909795430614359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9206909795430614359'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/03/first-gookup-released.html' title='First gookup version released to the wild!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-1869470540674885106</id><published>2008-03-05T00:56:00.000-08:00</published><updated>2008-03-06T05:00:03.415-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gookup'/><category scheme='http://www.blogger.com/atom/ns#' term='Jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Getting ahead with the program</title><content type='html'>Well it's been a week since my last post (time moves fast isn't it?) and had the need to write about some new idea's/solutions/stuff that iv found, so without further ado:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the gookup front iv made some progress with the packging scheme of the application, the problem is that Ruby/JRuby programs need to have at least a parser installed in order to work (well almost true since for Ruby you may use somthing like &lt;a href='http://www.erikveen.dds.nl/rubyscript2exe/'&gt;RubyScript2Exe&lt;/a&gt;), still i don't want to make my users have to install JRuby (the only requirement that im willing to live with is the need to have a working &gt;1.5 JRE).&lt;br /&gt;After goggling quite a bit iv found two main approaches, the &lt;a href='http://wiki.netbeans.org/SwingJRubyPackaging'&gt;first&lt;/a&gt; is to use a main Java class as an entry point to your JRuby main code and package the whole application in a Jar, the down side with this approach is that it doesn't seem to answer how to package ruby gems that your application requires in a clean manner (a possible answer might be to use something like &lt;a href='http://www.carbonfive.com/community/archives/2008/01/jrubygems_relea_1.html'&gt;JRubyGems&lt;/a&gt;   ).&lt;br /&gt;The &lt;a href='http://blog.nicksieger.com/articles/2007/01/12/self-cloning-jruby-and-rubygems-in-a-jar'&gt;second&lt;/a&gt; approach is to use jruby-complete.jar and create a working JRuby environment as a part of your install process with something like this:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 400px; height: 50px;"&gt;&lt;br /&gt; java -Xmx512m -jar jruby-complete.jar --command gem install gem-name&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will create a gem library under .jruby (or any custom library with the -Djruby.home=/custom/path flag) onto required gems will be installed.&lt;br /&gt;In order to run your JRuby main code all you need to do is to issue:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 400px; height: 50px;"&gt;&lt;br /&gt; java -Xmx512m -jar jruby-complete.jar --command main.rb&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Iv not decided which one of them ill eventually use (if any), the nice things about these kind of projects is how they evolve and grow.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Another two related tidbits:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Since this application will be command line base iv decided to look for a Ruby library that will save me the trouble of parsing commands from the user, &lt;a href='http://cmdparse.rubyforge.org/'&gt;cmdparse&lt;/a&gt; seems to meet my expectations, not only does it have an nice design but also a default help and version commands by default.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Another issue which bothered me along the development process was the lack of a debugger in my IDE, im used to the Intellij debbuger but it doesn't seem to support JRuby code yet (Netbeans does), &lt;a href='http://www.datanoise.com/ruby-debug/'&gt;ruby-debug&lt;/a&gt; seems to be have ported to JRuby (haven't tested it yet) and from &lt;a href='http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/'&gt;this&lt;/a&gt; screen cast it looks pretty awesome! &lt;br /&gt;&lt;/ul&gt;    &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In the Flex front iv been taking baby steps in trying to figure out how things are related to each other, iv noticed is that Adobe has a tendency to &lt;a href='http://weblogs.macromedia.com/flexteam/archives/2007/03/flex_data_servi.cfm'&gt;rename&lt;/a&gt; things quite a lot (marketing takes it tall i guess), so that Flex Data Services is now called LiveCycle Data services, LiveCycle consists of a couple of parts of functionality out of which im only interested (at the moment) in Flex remoting services and the way that they interact with Java backends, this small fraction of functionality is distributed in a OSS distribution named &lt;a href='http://opensource.adobe.com/wiki/display/blazeds/BlazeDS'&gt;BlazeDS&lt;/a&gt; project. &lt;br /&gt;&lt;S&gt;One frustrating thing that iv noticed is that Flex 2 compiled SWF's aren't compilable with latest BlazeDS, iv learned this the hard way following this simplistic &lt;a href='http://www.adobe.com/devnet/livecycle/articles/blazeds_gettingstarted.html'&gt;getting started guide&lt;/a&gt;,&lt;/S&gt; (My bad it seems as if i haven't passed mxmlc flags during compilation) &lt;br /&gt;iv learned that Flex RIA has couple of remote call options, one of which is RPC-type services which basically enable Flex RIA's to call remote Pojo methods and cosume the return values that they produce, its also &lt;a href='http://coenraets.org/flex-spring/'&gt;possible&lt;/a&gt; to call managed Spring beans methods by using a custom factory.&lt;/p&gt;&lt;br /&gt;Im planing to develope some toy project that will incorperate Flex, Spring and Hibernate, ill share my experience here so stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-1869470540674885106?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/1869470540674885106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=1869470540674885106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1869470540674885106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1869470540674885106'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/03/getting-ahead-with-program.html' title='Getting ahead with the program'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-4721960288911497886</id><published>2008-02-27T02:10:00.000-08:00</published><updated>2008-02-28T01:55:12.129-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gookup'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Yet another informational post (yaip)</title><content type='html'>After not writing for some time in this blog iv decided that i should post more regularly and share cool ideas/technologies that i encounter on daily/weekly bases, my agenda these days revolves around some of the following:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href='http://code.google.com/p/gookup/'&gt;gookup&lt;/a&gt; - a Google services backup utility which takes your valuable online data and stores it localy on your hard drive for safe keeping.&lt;br /&gt;Iv been working on it for the past couple of months, the nice thing about it (besides its usefulness i hope) is the fact that its fully JRuby based &amp; uses Buildr as its build tool.&lt;br /&gt;This matching allows some intresting combination like 'auto' Jar requiring in our JRuby code via the usage of the artifacts that we define in our build (ill elaborate on this on some other post).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Another subject that will keep me busy in the couple of following weeks is &lt;a href='http://www.adobe.com/products/flex/'&gt;Flex&lt;/a&gt;, this nifty piece of technology will be a main part of projects that ill take part in the near future.&lt;br /&gt;My plan is to study the following subjects:Flex Basics, Flex &amp; Java/Tomcat integration, &lt;a href='http://en.wikipedia.org/wiki/Cairngorm_(Flex_framework)'&gt;Cairngorm&lt;/a&gt;.&lt;br /&gt;So far iv taken a look on Flex Builder (current idea support should get &lt;a href='http://blogs.jetbrains.com/idea/2008/02/creating-flex-applications-with-intellij-idea/'&gt;better &lt;/a&gt; on 7.0.3) and some online resources such as &lt;a href='http://www.adobe.com/devnet/flex/articles/java_testdrive.html'&gt;thirty-minute Flex test drive &lt;/a&gt;.&lt;br /&gt;Still the best way to study a new technology is by getting your hands dirty and actually building something with it (ill figure something up).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Last but not least is Adobe AIR and JavaFX, im considering using one of the two for gookup front end (AIR dosn't support linux yet), still i might just use swing and profligacy instead if the integration with JRuby will prove to be impossible.&lt;br /&gt;&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-4721960288911497886?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/4721960288911497886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=4721960288911497886' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4721960288911497886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/4721960288911497886'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2008/02/yet-another-informational-post-yaip.html' title='Yet another informational post (yaip)'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-9222197187661557594</id><published>2007-12-18T00:56:00.000-08:00</published><updated>2007-12-27T08:55:11.292-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Buildr'/><category scheme='http://www.blogger.com/atom/ns#' term='Build'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Buildr and groovyc</title><content type='html'>Buildr is a build tool that iv mentioned in previous posts, its really flexible and easy to mold custom functionality into it due to its Ruby heritage and its &lt;a href="http://antwrap.rubyforge.org/"&gt;AntWrap&lt;/a&gt; utilization.&lt;br /&gt;In this post im going to demonstrate how to use the &lt;a href="http://groovy.codehaus.org/The+groovyc+Ant+Task"&gt;groovyc ant task&lt;/a&gt; in order to intruduce groovy compilation into your build (which is a bit tricky).&lt;br /&gt;Lets dive head first into the code:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 250px;"&gt;&lt;br /&gt;SP=File::SEPARATOR&lt;br /&gt;&lt;br /&gt;desc "Dummy project"&lt;br /&gt;define "Dummy" do&lt;br /&gt; #..&lt;br /&gt; def&lt;br /&gt;  hashToPath(hash)hash[:group].gsub('.',SP)+SP+hash[:id]+SP+hash[:version]+SP+hash[:id]+'-'+hash[:version]+'.jar'&lt;br /&gt; end &lt;br /&gt;&lt;br /&gt; def reslove_artifacts_paths(array)&lt;br /&gt;    array.flatten.inject([]){|result,arti|  result &lt;&lt; repositories.local+'/'+hashToPath(artifact(arti).to_hash)}.join(File::PATH_SEPARATOR)&lt;br /&gt; end&lt;br /&gt;         &lt;br /&gt; desc 'compiling'&lt;br /&gt; compile.enhance([:groovyc])# this actully replaces the standart compile with the groovyc ant task&lt;br /&gt;     &lt;br /&gt; desc 'groovyc task'&lt;br /&gt; task :groovyc do&lt;br /&gt;  classpath=reslove_artifacts_paths(RUNTIME)&lt;br /&gt;  ant('groovy') do |ant| &lt;br /&gt;    ant.taskdef :name=&gt;'groovyc',:classname=&gt;'org.codehaus.groovy.ant.Groovyc',:classpath=&gt;reslove_artifacts_paths(GROOVY)&lt;br /&gt;      ant.groovyc(:srcdir=&gt;path_to('src', 'main', 'java') , :destdir=&gt;path_to('target','classes') , :classpath=&gt;classpath){&lt;br /&gt;        ant.javac(:source=&gt;"1.5" ,:target=&gt;"1.5")&lt;br /&gt;      }&lt;br /&gt;     end&lt;br /&gt;   end&lt;br /&gt; #.. &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code above (if you havent guessed it until now) is the buildfile, lets disassemble it:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;The groovyc task uses AntWrap in order to define and use the groovyc ant task, notice that we are using joint compilation which in essence suppresses the default compilation (since there wont be anything left to compile when its turn arrives) and makes our life easier (no need to mess with the ordering of the compilation steps).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The reslove_artifacts_paths method does what its name suggests and is required in order to make ant happy (i haven't found a nicer way of doing this) or else it wont find the required classes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the GROOVY constant points to the groovy-all jar the RUNTIME points to all that is needed during compilation.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That all about there is to it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-9222197187661557594?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/9222197187661557594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=9222197187661557594' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9222197187661557594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/9222197187661557594'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/12/buildr-and-groovyc.html' title='Buildr and groovyc'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6705545659349861464</id><published>2007-12-13T03:27:00.000-08:00</published><updated>2007-12-23T09:35:56.624-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Compilation'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Compilled vs non compilled Groovy Spring beans</title><content type='html'>Spring offers great flexibility when working with dynamic languages, it enables the wiring of Groovy beans in your application with minimal effort (&lt;a href="http://static.springframework.org/spring/docs/2.5.x/reference/dynamic-language.html"&gt;see&lt;/a&gt;), one of the coolest things about it is that it enables also the re-deployment of Groovy code with no more then a simple file override (&lt;a href="http://static.springframework.org/spring/docs/2.5.x/reference/dynamic-language.html#dynamic-language-refreshable-beans"&gt;see&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;All this is fine and dandy except that it introduces quite an overhead on Spring context startup time and runtime usage, developers that use it may get the wrong impression that Groovy is Sloowww (partly true). &lt;br /&gt;The fact is (as ill demonstrate next) that Spring's magic takes its toll and that there is a simple alternative to this mechanism which is to use the compiled code and not the source code in our bean definitions.&lt;br /&gt;&lt;br /&gt;Take for example the following configurations:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;Compiled:&lt;br /&gt;&amp;lang;bean id="multiThreadedConversion" class="com.conversion.MultiThreadedConversion" scope="singleton"&amp;rang;&lt;br /&gt;  &amp;lang;property name="mapper" ref="mapper"/&amp;rang;&lt;br /&gt;&amp;lang;bean&amp;rang;&lt;br /&gt;&lt;br /&gt;&amp;lang;bean id="mapper" class="com.conversion.utils.ExtensionToAppMapper" scope="singleton"/&amp;rang;&lt;br /&gt;&lt;br /&gt;&amp;lang;bean id="scavenger" class="com.conversion.utils.ConversionDataScavenger" scope="singleton"/&amp;rang;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;Not compiled:&lt;br /&gt;&amp;lang;lang:groovy id="multiThreadedConversion" script-source="classpath:com/conversion/MultiThreadedConversionNotCompiled.groovy" scope="singleton"&amp;rang;&lt;br /&gt; &amp;lang;lang:property name="mapper" ref="mapper"/&amp;rang;&lt;br /&gt;&amp;lang;/lang:groovy&amp;rang;&lt;br /&gt;&lt;br /&gt;&amp;lang;lang:groovy id="scavenger" script-source="classpath:com/conversion/utils/ConversionDataScavenger.groovy" scope="singleton"/&amp;rang;&lt;br /&gt;&lt;br /&gt;&amp;lang;lang:groovy id="mapper" script-source="classpath:com/conversion/utils/ExtensionToAppMapper.groovy" scope="singleton"/&amp;rang;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And two simple startup time benchmarks:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt; &lt;br /&gt; public void compiled() {&lt;br /&gt;  Date before = new Date();&lt;br /&gt;  ApplicationContext compiled = new ClassPathXmlApplicationContext("application.xml");&lt;br /&gt;  System.out.println(new Date().getTime() - before.getTime());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void notCompiled() {&lt;br /&gt;  Date before = new Date();&lt;br /&gt;  ApplicationContext notCompiled = new lassPathXmlApplicationContext("not_compiled_application.xml");&lt;br /&gt;  System.out.println(new Date().getTime() - before.getTime());&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running them both resulted with the compiled version taking 0.203s to run and the the non compiled took 1.015s which is ~five times slower!&lt;br /&gt;&lt;br /&gt;Should we conclude that the compiled version is always preferable?&lt;br /&gt;Well it depends since it has its drawbacks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; We lose the easy deployment procedure when using the byte code.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;S&gt;G/Setter must be introduced in order to aid spring in identifying properties within classes (a serious draw back since in groovy we may use only the def keyword).&lt;/S&gt;&lt;br /&gt;It seems that iv got this wrong (just match the Spring  id with the Groovy property name and your set).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This leads to the answer: &lt;br /&gt;Use the source when easy redeployment (business logic is one good example) is required, use compiled when performance is critical.&lt;br /&gt;&lt;br /&gt;Keep on Grooving ..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6705545659349861464?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6705545659349861464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6705545659349861464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6705545659349861464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6705545659349861464'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/12/spring-compilled-vs-non-compilled.html' title='Compilled vs non compilled Groovy Spring beans'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-6030980906491364591</id><published>2007-12-04T01:04:00.000-08:00</published><updated>2007-12-07T15:37:37.780-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Taking back control on your tests with TestNG</title><content type='html'>I'm truly a testing fanatic, in fact i think that for each component coded tests should be an integral part the process.&lt;br /&gt;The thing is that as your code grows it gets harder to maintain the tests that you've written in addition &lt;a href="http://www.junit.org/"&gt;JUnit&lt;/a&gt; adds pain to misery due to its bad design. &lt;br /&gt;Its true that latest 4.* versions had fixed some really annoying practices like the naming convention of test methods and the need to extend a test base class but still it lacks in many other areas.&lt;br /&gt;&lt;br /&gt;One of the major problems in JUnit is the fact that the main grouping point of tests is the test class itself which isn't fined grained enough, &lt;a href="http://testng.org/doc/"&gt;TestNG&lt;/a&gt; on the other hand allows to include any test method within any group no matter in which class its defined, for example:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 250px;"&gt;&lt;br /&gt;package tests; &lt;br /&gt;&lt;br /&gt;public class SomeCases {&lt;br /&gt;&lt;br /&gt;    @BeforeMethod(groups = {"restore", "authorization"})&lt;br /&gt;    public void cleanup() {&lt;br /&gt;        // some common cleanup code&lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    @Test(groups = {"restore"})&lt;br /&gt;    public void getSingleModel() {&lt;br /&gt;     // .. &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test(groups = {"restore"})&lt;br /&gt;    public void getManyModels() {&lt;br /&gt;     // ..   &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test(groups = {"authorization"})&lt;br /&gt;    public void authorizationService() {&lt;br /&gt;     // ..   &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This class holds a bunch of test methods which are divided to two major groups restore and authorization, this fine grained division enables all sorts of new possibilities like the handling of cross cutting concerns such as the cleanup method (we could easily move it to a super class to enable it on multiple classes). &lt;br /&gt;&lt;br /&gt;Another possibility is to mix and match test suites that include test methods scattered around many classes, for example the next test method which belongs to the restore group that we've seen above:  &lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;package tests;&lt;br /&gt;&lt;br /&gt;public class MoreSomeCases {&lt;br /&gt;    @Test(groups = {"restore"})&lt;br /&gt;    public void validateModelRestore() {&lt;br /&gt;     // .. &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;is made executable (with all the other restore methods) by defining the following suite (XML):&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;&amp;lang;suite name="BASIC_FUNCTIONALITY" verbose="1"&amp;rang;&lt;br /&gt;    &amp;lang;test name="BASIC_FUNCTIONALITY"&amp;rang;&lt;br /&gt;        &amp;lang;groups&amp;rang;&lt;br /&gt;            &amp;lang;run&amp;rang;&lt;br /&gt;                &amp;lang;include name="restore"/&amp;rang;&lt;br /&gt;            &amp;lang;/run&amp;rang;&lt;br /&gt;        &amp;lang;/groups&amp;rang;&lt;br /&gt;        &amp;lang;packages&amp;rang;&lt;br /&gt;            &amp;lang;package name="tests"/&amp;rang;&lt;br /&gt;        &amp;lang;/packages&amp;rang;&lt;br /&gt;    &amp;lang;/test&amp;rang;&lt;br /&gt;&amp;lang;/suite&amp;rang;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this will enable the running of all the restore methods no matter in which class they are defined (this is an easy way to run integration tests).&lt;br /&gt;&lt;br /&gt;TestNG has a lot more to offer (only a partial list):&lt;br /&gt; - Defining input parameters of test methods and injecting them with data providers.&lt;br /&gt; - Defining dependencies among tests and groups.&lt;br /&gt; - Run tests in parallel.&lt;br /&gt;&lt;br /&gt;Head on and check it out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-6030980906491364591?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/6030980906491364591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=6030980906491364591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6030980906491364591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/6030980906491364591'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/12/taking-back-control-on-your-tests-with.html' title='Taking back control on your tests with TestNG'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-7347596079328410762</id><published>2007-11-01T06:05:00.000-07:00</published><updated>2007-12-04T01:55:32.688-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Intellij'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Intellij 7.01 on Ubuntu =&gt; Java 6 upgrade</title><content type='html'>Intellij now makes use of JDK 6 which means that one should upgrade his version (using synaptic you know the drill) and set IDEA_JDK to /usr/lib/jvm/java-6-sun at the .bashrc file.&lt;br /&gt;&lt;br /&gt;But wait! thats not all!! &lt;br /&gt;The upgrade that youv just made has changed the default Java version symlink (under /usr/bin) which is used in your bash!, this means that any bash invoked application (maven, JBoss) will use the new JDK instead the older one (a big no no if your still developing in 1.5 like me).&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 300px; height: 35px;"&gt;sudo update-alternatives --config java&lt;/pre&gt;&lt;br /&gt;Another pointer that i have found to be useful is to make sure to delete the older .IntelliJIdea70 hidden folder, that in case that you have used the M2 idea version prior to the final release.&lt;br /&gt;&lt;br /&gt;Thats all, Idea Rock on!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-7347596079328410762?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/7347596079328410762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=7347596079328410762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7347596079328410762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/7347596079328410762'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/11/intellij-701-on-ubuntu-java-6-upgrade.html' title='Intellij 7.01 on Ubuntu =&gt; Java 6 upgrade'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-8173974165976247551</id><published>2007-10-08T04:20:00.000-07:00</published><updated>2007-12-03T05:41:39.827-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Catch the bug</title><content type='html'>Well iv just spent an hour or so on this cute little bug and thought to challenge you readers to catch it by yourself (using any debuggers IDE's etc.. isn't allowed!)&lt;br /&gt;The code is in the Groovy programming language and involves two closures as follows:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;def validate(assets){&lt;br /&gt; def asset = assets.find() {a -&gt;&lt;br /&gt;  [a.floor, a.houseNr, a.street, a.zipCode].find {val -&gt; StringUtils.isEmpty(val)} !=null &lt;br /&gt; }&lt;br /&gt; asset == null ? 'all addresses are ok' : 'one address is partial'&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This little method finds an asset within an asset list that has at least one empty address value (emptiness is asserted by org.apache.commons StringUtils).&lt;br /&gt;&lt;br /&gt;The method makes use of two nested find methods (both accept two boolean closures) with this simple logic:&lt;br /&gt;We are trying to find any asset (the wrapping find call) that has at least one empty address value (the inner find), simple enough right?&lt;br /&gt;&lt;br /&gt;Well lets Write some tests:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;def asset= new Asset()&lt;br /&gt;asset.floor='1'&lt;br /&gt;asset.houseNr='1' &lt;br /&gt;asset.street='bla'&lt;br /&gt;asset.zipCode ='1234' &lt;br /&gt;assetEquals('all addresses are ok',validate([asset]))// passes&lt;br /&gt;asset.floor=''&lt;br /&gt;assetEquals('one address is partial',validate([asset]))// passes &lt;br /&gt;asset.floor=null&lt;br /&gt;assetEquals('one address is partial',validate([asset]))// bug strikes here!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well that one last test is weird, the first initial instinct of mine was to check that isEmpty handles null as empty (ill give you a hint, it does).&lt;br /&gt;Feel free to tackle it now, its not that complicated (or is it?) the following paragraph will contain the solution so stop reading now! (thats if you don't want to cheat).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The solution:&lt;br /&gt;Ok lets follow along that last test:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The validate method input includes an asset that has a nullified floor, the first find is called.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The first find calls its inner find method call.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now here is the tricky part, the inner find manages to scan only the first array value  (floor) and returns its value (which is null!), the !=null assertion returns false to its wrapping find,now since there are no more elements in the assets list the outer find returns the faulty null.&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;  &lt;br /&gt;Thats it another bug squashed!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-8173974165976247551?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/8173974165976247551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=8173974165976247551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8173974165976247551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/8173974165976247551'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/10/catch-bug.html' title='Catch the bug'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-5195395990213004497</id><published>2007-08-20T01:47:00.000-07:00</published><updated>2007-12-07T15:33:52.322-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding techniques'/><title type='text'>Generics shall risen again!</title><content type='html'>&lt;p&gt;Here is a possible solution for cases in which some libraries that you depend upon and are not under your control (Spring, Apache Commons etc..) don't use generics (usually this is due to 1.42 backward compatibility), in such cases you'd usually write lines that might resemble something like this:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 100px;"&gt;&lt;br /&gt;JdbcTemplate jdbcTemplate=new JdbcTemplate();&lt;br /&gt;List&amp;lang;String&amp;rang; result=jdbcTemplate.queryForList(/*query*/,/*params*/);&lt;/pre&gt; &lt;br /&gt;&lt;p&gt;This code will result in unchecked assignment warning during compilation however the most annoying thing about it is that the IDE will not auto complete the generics types for us(=&gt; more typing for us!).&lt;br /&gt;My solution is based upon  &lt;a href="http://www.laughingpanda.org/projects/jretrofit/"&gt; JRetrofit&lt;/a&gt;  a framework that enables us to add interfaces to classes during runtime, first will create an interface that should contain all the commonly used JdbcTemplate methods:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 100px;"&gt;&lt;br /&gt;public interface JdbcDynamicWrapper&lt;T&gt; {&lt;br /&gt;&amp;nbsp;List&lt;T&gt; queryForList(String sql,Object[] args)throws DataAccessException;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And a factory method that will be used to get jdbcTemplate instances:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;class JdbcTemplateFactory {&lt;br /&gt;&amp;nbsp;public &amp;lang;T&amp;rang; JdbcDynamicWrapper&amp;lang;T&amp;rang; getTemplateWraper(Class&amp;lang;T&amp;rang; clazz){&lt;br /&gt;&amp;nbsp;&amp;nbsp;JdbcTemplate jdbcTemplate = new JdbcTemplate();&lt;br /&gt;&amp;nbsp;&amp;nbsp;return(JdbcDynamicWrapper&amp;lang;T&amp;rang;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Retrofit.partial(jdbcTemplate,JdbcDynamicWrapper.class);&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All that is left is to use the factory method:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;JdbcTemplateFactory jdbcTemplateFactory=new JdbcTemplateFactory();&lt;br /&gt;JdbcDynamicWrapper&amp;lang;String&amp;rang;templateWraper=jdbcTemplateFactory.getTemplateWraper(String.class);&lt;br /&gt;List&amp;rang;String&amp;lang; names=templateWraper.queryForList(/*query*/,/*params*/);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now i know that this solution has its down sides (the need to add each method to the interface is one of them), but for methods which are very commonly used i think that its worth its price, don't you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-5195395990213004497?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/5195395990213004497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=5195395990213004497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5195395990213004497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5195395990213004497'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/08/generics-shall-risen-again.html' title='Generics shall risen again!'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-5371672867468635822</id><published>2007-08-03T11:15:00.000-07:00</published><updated>2007-12-03T05:35:07.508-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Build'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Building made easy..</title><content type='html'>&lt;div style="text-align: left;"&gt;&lt;br /&gt;Well this post is devoted to &lt;a href="http://buildr.rubyforge.org/"&gt;Buildr&lt;/a&gt;  a Maven like build tool intended for Java projects which aims to make the whole building process much simpler to write and maintain.&lt;br /&gt;It Actually uses similar Maven idioms &amp; concepts like:&lt;br /&gt;&lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Usage of remote Repositories.&lt;/li&gt;&lt;li&gt;Artifacts.&lt;/li&gt;&lt;li&gt;Different Life cycle stages.&lt;/li&gt;&lt;/ul&gt; Still it differs in its infer structure which is based upon &lt;a href="http://docs.rubyrake.org/"&gt;Rake&lt;/a&gt; instead of Ant (no more XML and thank god for that!).&lt;br /&gt;One of the positive things that i feel that Ruby can bring into the Java sphere is simplicity and Buildr is no exception, its really easy to start get going in a matter of hours not days!. &lt;br /&gt;With that last statement in mind iv had some troubles with the installation of Buildr under Ubuntu, which lead me to the following conclusions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;download and install gem manually (don't use synaptic).&lt;/li&gt;&lt;li&gt;sudo apt-get install ruby1.8-dev, build-essential.&lt;/li&gt;&lt;li&gt;choose ruby versions when ever gem asks you.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Now lets go ahead and create our simple build example with the following structure (looks familiar?):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_4IH34e52vWk/RrOXqCpGJ2I/AAAAAAAAAM8/N9GcEi0Afys/s1600-h/structure.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_4IH34e52vWk/RrOXqCpGJ2I/AAAAAAAAAM8/N9GcEi0Afys/s320/structure.jpg" alt="" id="BLOGGER_PHOTO_ID_5094582352005703522" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;We want our build to supply us with the following simple services:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Compile our project.&lt;/li&gt;&lt;li&gt;Create an Intellij project (with all the dependencies already defined).&lt;/li&gt;&lt;li&gt;Package our project into a jar.&lt;/li&gt;&lt;li&gt;Deploy our project into a folder ready to run.&lt;/li&gt;&lt;li&gt;To clean up our acts.&lt;/li&gt;&lt;li&gt;Run some basic tests.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Buildr requires a single file (named buildfile) to be placed at the base folder of our project, this file will contain the project's tasks.&lt;br /&gt;Our first step will be to define the artifacts that we depend upon, Buildr uses Ruby data structures (arrays, structs and even hashes!) to define them.&lt;br /&gt;Its up to us to if we want to place these definitions in a separate file or not (usually we do), here is our artifacts.rb file:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 70px;"&gt;&lt;br /&gt;#group:id:type:version&lt;br /&gt;DUMMY_ARTIFACTS=['commons-collections:commons-collections:jar:3.1'] &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now will go ahead and define our project and its repositories:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 300px;"&gt;&lt;br /&gt;require 'artifacts'&lt;br /&gt;repositories.remote &lt;&lt; "http://www.ibiblio.org/maven2/"&lt;br /&gt;repositories.local = "home/myuser/.m2/repository/"      &lt;br /&gt;desc "our dummy project" &lt;br /&gt;define "Dummy" do               &lt;br /&gt;  project.version = '1.0'           &lt;br /&gt;  project.group = "Dummy"            &lt;br /&gt;  manifest["Main-Class"] = "main.Main"# defining the jar's main class       &lt;br /&gt;   &lt;br /&gt;  desc "dummy single module"              &lt;br /&gt;   define "dummy-module" do              &lt;br /&gt;    # our tasks ..            &lt;br /&gt;   end    &lt;br /&gt;  end# the end of the dummy single module  end &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Buildr provides us with all the expected predefined tasks that you might expect:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 300px;"&gt;&lt;br /&gt; desc 'compiling'&lt;br /&gt; compile.with DUMMY_ARTIFACTS&lt;br /&gt;&lt;br /&gt; desc 'testing'&lt;br /&gt; test.with DUMMY_ARTIFACTS&lt;br /&gt;&lt;br /&gt; desc 'packing and including classpath in the manifest'&lt;br /&gt; package(:jar).with(:manifest=&gt;&lt;br /&gt; manifest.merge("Class-Path" =&gt;&lt;br /&gt; compile.classpath.collect{|dep| &lt;br /&gt; "  "+File.basename(dep.inspect)}.join("\n").strip))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Don't be alarmed by the package task code it's quite simple (remember its all Ruby code!), each and every task can be referenced by using task(:name) (compile is equivalent to task(:compile)).&lt;br /&gt;We are also referencing the manifest property which is a predefined data member of our project and setting the Class-Path property with all the artifacts that our project depends upon (the spacing is required due to &lt;a href="http://www.jroller.com/sgm/entry/manifest_class_path_too_long"&gt;weird manifest requirements&lt;/a&gt;), in order to run one of these tasks (at the project's base dir):&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 70px;"&gt;&lt;br /&gt; bla@bla-desktop:~/workspaces/Dummy$ buildr taskname&lt;br /&gt; #in order to build an Intellij project simply use the idea task.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now will head on to deploying our application into a folder in with the following structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_4IH34e52vWk/RrWcnSpGJ3I/AAAAAAAAANI/6mrXVux_mqU/s1600-h/result+app.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_4IH34e52vWk/RrWcnSpGJ3I/AAAAAAAAANI/6mrXVux_mqU/s320/result+app.jpg" alt="" id="BLOGGER_PHOTO_ID_5095150752272623474" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This is a custom task that iv cooked up:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 200px;"&gt;&lt;br /&gt; desc 'deploying the application'&lt;br /&gt; task :deploy_app =&gt; [:package,:build_app_folders,:build_bin] do      &lt;br /&gt;&amp;nbsp;&amp;nbsp;FileUtils.cp(path_to('target')+'/'+File.basename(project.packages[0].inspect),lib_path)&lt;br /&gt;&amp;nbsp;&amp;nbsp;compile.classpath.each{|dep|FileUtils.cp(dep.inspect.gsub('Buildr::Artifact:','').strip,lib_path)}&lt;br /&gt;&amp;nbsp;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This task depends upon the package, build_app_folders and build_bin tasks, it basicly copies the project jar and all the artifacts the project depends upon into the application folder. &lt;br /&gt;Take special notice to the usage of Buildr path_to method which returns the path to our module's target folder, since its a custom task will need to run it by specifying its full name:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 50px;"&gt;&lt;br /&gt;bla@bla-desktop:~/workspaces/Dummy$ &lt;br /&gt;buildr Dummy:dummy-module:deploy_app&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here are build_app_folders and build_bin tasks on which deploy_app depends upon:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 200px;"&gt;&lt;br /&gt; desc 'building the application folders'&lt;br /&gt;  task :build_app_folders do&lt;br /&gt;  unless File.exists?(app_path)&lt;br /&gt;   FileUtils.mkdir app_path ,:mode=&gt;0777&lt;br /&gt;  end&lt;br /&gt;  ...&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; desc 'building the application launcher'&lt;br /&gt; task :build_bin do&lt;br /&gt;  launch_cmd='java -Dfile.encoding=UTF-8 -jar ./lib/'+File.basename(project.packages[0].inspect)&lt;br /&gt;  unless File.exists?(bin_path+'/'+'run.sh')&lt;br /&gt;   f = File.new(bin_path+'/'+'run.sh',"w+")&lt;br /&gt;   f.puts '#!/bin/bash'&lt;br /&gt;   f.puts 'cd ..'&lt;br /&gt;   f.puts launch_cmd&lt;br /&gt;   FileUtils.chmod 0755,bin_path+'/'+'run.sh'&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now all that is left is to extend the clean task so that it will remove the application folder, in order to extend an existing buildr task will use the enhance method:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;&amp;nbsp;desc 'cleaning up our act'&lt;br /&gt;&amp;nbsp;&amp;nbsp;clean.enhance {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if File.exists?(app_path)  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;FileUtils.remove_dir app_path &lt;br /&gt;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thats all, happy building to us all :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-5371672867468635822?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/5371672867468635822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=5371672867468635822' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5371672867468635822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/5371672867468635822'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/08/building-made-easy.html' title='Building made easy..'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_4IH34e52vWk/RrOXqCpGJ2I/AAAAAAAAAM8/N9GcEi0Afys/s72-c/structure.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-2640131793318952139</id><published>2007-05-02T01:48:00.000-07:00</published><updated>2007-12-03T05:28:54.183-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding techniques'/><title type='text'>Dicsrete math &amp; Java</title><content type='html'>In my &lt;span style=""&gt;Bachelor's &lt;/span&gt;degree i had the pleasure to study discrete math, discrete math  handles &lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Group_theory"&gt;group theory&lt;/a&gt; which address well hmm... groups :).&lt;br /&gt;A group is a math entity that has a proper &lt;a href="http://en.wikipedia.org/wiki/Group_theory#Definition_of_a_group"&gt;definition&lt;/a&gt; and a collection of operations which are operable on them such as: intersection, union, disjunction, subtraction.&lt;br /&gt;&lt;br /&gt;At this point you must be thinking "well this all doesn't matter to us Java folks ..", well in fact we can think of Java collections and sets as groups (not exactly since we wont insist on a  binary operation), thinking of them this way can result in some clean code implementation.&lt;br /&gt;For example imagine that we need to find which changes were made to an arbitrary list of uniquely identifiable objects  (list which are new, removed or old), the simplistic approach will look  like:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 250px;"&gt;&lt;br /&gt;public void printChanges(List older, List newer) {&lt;br /&gt;for(Object value:older){&lt;br /&gt; if(newer.contains(value)){&lt;br /&gt;  log.info(value.toString()+" is old");&lt;br /&gt; } else {&lt;br /&gt;  log.info(value.toString()+" was removed");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;for(Object value:newer){&lt;br /&gt;  if(!older.contains(value)){&lt;br /&gt;  log.info(value.toString()+" was added");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Its not the most elegant code since it contains loops and conditionals, in simple cases this might not be so bad but in more complex cases keeping trace on this kind of code is not easy, as for run time its about o(n).&lt;br /&gt;&lt;br /&gt;Now lets see how the groups approach might work, our input consists of two object groups and we are seeking for three other groups that contain elements from these two, the most easy one to detect is the intersection of the two which match the old objects.&lt;br /&gt;Finding the removed and the new is the same symmetric problem which is to find the  objects that exists in one group but doesn't exist on the other, in groups lingo the operation that finds such objects is called subtraction.&lt;br /&gt;Now lets take a look at the group oriented implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 150px;"&gt;&lt;br /&gt;//making use of org.apache.commons.collections&lt;br /&gt;public void&lt;string,list&gt; printChanges(Collection older, Collection newer) {&lt;br /&gt; final Collection removed = CollectionUtils.subtract(older, newer);&lt;br /&gt; final Collection added = CollectionUtils.subtract(newer, older);&lt;br /&gt; final Collection old = CollectionUtils.intersection(older, newer);&lt;br /&gt; log.info("removed: "+removed);&lt;br /&gt; log.info("added: "+added);&lt;br /&gt; log.info("old: "+old);&lt;br /&gt;}&lt;br /&gt;&lt;/string,list&gt;&lt;br /&gt;&lt;/pre&gt;Its easy to see that this implementation is much more easy to follow since there are no loops or conditionals (code &lt;a href="http://www.linuxjournal.com/article/8035"&gt;complexity&lt;/a&gt; is lower), as for runtime its also o(n).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-2640131793318952139?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/2640131793318952139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=2640131793318952139' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2640131793318952139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/2640131793318952139'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/05/dicsrete-math-java.html' title='Dicsrete math &amp; Java'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-1077214558877334645</id><published>2007-04-17T15:13:00.000-07:00</published><updated>2007-12-03T05:31:02.375-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>A glass of Watir to quench your thirst</title><content type='html'>A couple of years ago (long before rails was in focus) Ruby has caught my eyes , to be exact it was &lt;a href="http://www.openqa.org/watir/"&gt;Watir&lt;/a&gt; which is a Ruby based web testing framework that took my attention , at the time i didnt know how much useful it can be.&lt;br /&gt;Watir is quite interesting since it drives the actual web browser UI (IE) during testing procedures , this makes it extremely simple to use , you don't have to sniff any http posts or use low level API , just select your DOM element and the operation that you wish the browser to perform on it:&lt;br /&gt;&lt;pre style="border: 1px solid rgb(164, 185, 127); overflow: auto; background-color: rgb(235, 235, 228); color: rgb(0, 0, 0); width: 350px; height: 100px;"&gt;&lt;br /&gt; ie = IE.new # our IE window&lt;br /&gt; ie.goto("http://mytestsite")&lt;br /&gt; ie.text_field(:name, "typeinme").clear # clearing out a text field that carries the name typeinme&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;What can you do with it?&lt;br /&gt;Well There are many applications (besides basic testing) that can utilize it such as:&lt;br /&gt;•  Web site monitors that scans web sites at certain intervals and look for errors.&lt;br /&gt;•  Web crawlers and Form data extractors.&lt;br /&gt;•  Applications that automatically recreate bugs (using saved user input data).&lt;br /&gt;&lt;br /&gt;The fact that Watir is Ruby based makes its very extensible , you can use it in conjunction with Rails to create a web based management console for your application , fetching of input data can be done easily with &lt;a href="http://rubyforge.org/projects/activerecord/"&gt;ActiveRecord&lt;/a&gt; from you favorite DB.&lt;br /&gt;&lt;br /&gt;Watir has its downsides too ,  its not very efficient since it requires an entire machine (as long your program keeps on running) , also since it works at the UI level (IE is its main resource) it takes a large amount of computing power (especially when there are a couple of them open).&lt;br /&gt;Watir largest drawback is that its only supports IE at the current moment (support for Mozilla is planned on the next release) which is quite limiting  (at least you can use this &lt;a href="http://bitcraft.ca/2006/09/12/ruby-watir-and-internet-explorer-on-linux/"&gt;hack&lt;/a&gt; for running it on Linux) , still trust me Watir is one of the most useful frameworks youl ever stumble upon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-1077214558877334645?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/1077214558877334645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=1077214558877334645' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1077214558877334645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/1077214558877334645'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/04/glass-of-watir-to-quench-your-thirst.html' title='A glass of Watir to quench your thirst'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3915544030735587425.post-3342185571623196280</id><published>2007-04-03T13:07:00.000-07:00</published><updated>2007-04-16T08:11:21.381-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>JBoss PermGen , same old error</title><content type='html'>&lt;p&gt;&lt;span style="font-family:Geneva;"&gt;A couple of weeks ago iv stumbled upon  the following &lt;/span&gt;&lt;span style="font-family:Geneva;"&gt;&lt;a href="http://my.opera.com/karmazilla/blog/2007/03/13/good-riddance-permgen-outofmemoryerror"&gt;post&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family:Geneva;"&gt; which carried the title "Good Riddance, PermGen OutOfMemoryError !", the thing is that this error happens quite alot when you are redeploying an application under JBoss for a couple of times.&lt;br /&gt;The only way to recover from it is to restart JBoss which is quite annoying (especially  when  it  takes  2min  to load it up again).&lt;br /&gt;Iv promised to myself to check the proposed post configuration and mailed the link to all my coworkers , obviously  i forgot it totally :).&lt;br /&gt;That was until one of my coworkers who read my email asked me if this thing actually works , his question had led me to perform the following test:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:Geneva;"&gt;Iv compared two configuration of /bin/run.conf and counted how many times ill be able to redeploy an application without getting the error.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Geneva;"&gt;In the first (standard) configuration iv set JAVA_OPTS to "-Xms32m -Xmx64m -XX:MaxPermSize=64m .. "  (the rest unchanged ) , this limits the memory size which is allocated to the JVM and to the perm gen memory section.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Geneva;"&gt;In the second (modified) configuration iv appended "-XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled" to JAVA_OPTS.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:Geneva;"&gt;The results were quite disappointing , no matter how iv tried to set these parameters the results were identical  , in fact the only thing that made a positive effect was setting "-XX:MaxPermSize=64m" to "-XX:MaxPermSize=128m".&lt;br /&gt;Frustrated a bit iv went back to the post and noticed that it was updated , a link to another &lt;/span&gt;&lt;span style="font-family:Geneva;"&gt;&lt;a href="http://my.opera.com/karmazilla/blog/2007/03/15/permgen-strikes-back"&gt;post&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family:Geneva;"&gt; was added , this one with the more realistic title "PremGen strikes back" :).&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3915544030735587425-3342185571623196280?l=javadevelopmentforthemasses.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javadevelopmentforthemasses.blogspot.com/feeds/3342185571623196280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3915544030735587425&amp;postID=3342185571623196280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3342185571623196280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3915544030735587425/posts/default/3342185571623196280'/><link rel='alternate' type='text/html' href='http://javadevelopmentforthemasses.blogspot.com/2007/04/my-first-post-jboss-permgen.html' title='JBoss PermGen , same old error'/><author><name>ronen</name><uri>http://www.blogger.com/profile/13360463320878175457</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
