<?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-4926719740036603542</id><updated>2012-01-05T13:55:46.132-08:00</updated><title type='text'>Martin's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-1868986895171545846</id><published>2011-05-11T09:38:00.000-07:00</published><updated>2011-10-21T08:21:15.966-07:00</updated><title type='text'>Embracing Functional Programming</title><content type='html'>Few months ago when &lt;a href="http://martinzoldano.blogspot.com/2011/02/learning-scala.html"&gt;learning&lt;/a&gt; Scala I ported few personal projects from Java, I wanted to share my experience and discoveries on a particular one, since I thought it demonstrates IMO how I embraced functional programming into my thinking process, applied to something useful. Scala was a good fit for this experiment due to its hybrid [OO+F], so I'll try to depict an implementation transitioning from imperative into functional. I found an old class (good candidate) performing statistical analysis on some collected data, so let's set the stage with summary &lt;a href="http://icp.giss.nasa.gov/education/statistics/index.html"&gt;stats&lt;/a&gt; , here's the class definition in the REPL:
&lt;pre style="color:#66FF00; background: none repeat scroll 0% 0% #000000"&gt;Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_23).
Type in expressions to have them evaluated.
Type :help for more information.
scala&amp;gt;
final class Stats( private val list: List[Double] ) {
    require( list != Nil   , "data list can't be Nil")    
    assert ( !list.isEmpty , "data list can't be empty")
                  
    lazy val data = list.sorted

    lazy val len : Int = data.length

    lazy val sum = data.sum
        
    lazy val min = data.min

    lazy val max = data.max

    lazy val range = max - min
                                                
    lazy val median = if (len%2==0) ((data((len/2)-1) + data((len/2))) /2)
                      else data(((len+1)/2)-1)
                      
    lazy val mean = sum / len
                                                                                
    lazy val variance = {
      @scala.annotation.tailrec
      def vrec(list: List[Double] , tot: Double): Double = list match {
        case head :: tail =&amp;gt; vrec( tail , tot + math.pow( head - mean , 2 ) )
        case _ =&amp;gt; tot / ( len - 1 )
      }
      vrec(data,0D)
    }

    lazy val standardDeviation = math.sqrt( variance )

    lazy val mode = histogram.maxBy(_._2)._1 

    lazy val histogram = {
       scala.collection.immutable.TreeMap[Double,Int]() ++
       data.groupBy( x =&amp;gt; x ).mapValues( _.length )
    }

    def dump { data foreach println }

    override def toString() = {
    new scala.collection.mutable.StringBuilder()
    .append("DATA     : ").append( data )
    .append("\nN        : ").append( len )
    .append("\nMIN      : ").append( min )
    .append("\nMAX      : ").append( max )
    .append("\nRANGE    : ").append( range )
    .append("\nMODE     : ").append( mode )
    .append("\nMEDIAN   : ").append( median )
    .append("\nMEAN     : ").append( mean )
    .append("\nVARIANCE : ").append( variance )
    .append("\nSTRD-DEV : ").append( standardDeviation )
    .append("\nHISTOGRAM: ").append( histogram )
    .mkString
    }             
}
defined class Stats
scala&amp;gt;
&lt;/pre&gt;let's instantiate our new class with some test data
&lt;pre style="color:#66FF00; background: none repeat scroll 0% 0% #000000"&gt;scala&amp;gt; val stats = new Stats(List[Double](60,10,20,30,20,40,20,50,90,80))
stats: Stats =
DATA     : List(10.0, 20.0, 20.0, 20.0, 30.0, 40.0, 50.0, 60.0, 80.0, 90.0)
N        : 10
MIN      : 10.0
MAX      : 90.0
RANGE    : 80.0
MODE     : 20.0
MEDIAN   : 35.0
MEAN     : 42.0
VARIANCE : 751.1111111111111
STRD-DEV : 27.406406388125955
HISTOGRAM: Map(10.0-&amp;gt;1,20.0-&amp;gt;3,30.0-&amp;gt;1,40.0-&amp;gt;1,50.0-&amp;gt;1,60.0-&amp;gt;1,80.0-&amp;gt;1,90.0-&amp;gt;1)
&lt;/pre&gt;
so let's then focus on the variance in particular:
&lt;span style="font-style: italic; color: rgb(0, 102, 0);"&gt;variance = (1/(N-1) × (the sum of (each data point - mean)&lt;/span&gt;&lt;sup style="font-style: italic; color: rgb(0, 102, 0);"&gt;2&lt;/sup&gt;&lt;span style="font-style: italic; color: rgb(0, 102, 0);"&gt;)&lt;/span&gt;

let's start with the following implementations series, we begin the imperative way with var re-assignment, not FP friendly (but ok since within method scope)
&lt;pre style="color:#2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;def variance() = {
var sum:Double = 0D
for( x &amp;lt;- data ) {
  sum += math.pow( x - mean , 2 )
}
( sum / ( len - 1 ) )
}
&lt;/pre&gt;and now with built in map + sum from List impl, this will yield O(n) for map and O(n) for the sum respective collection traversals, not too optimal but better
&lt;pre style="color:#2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;def variance = data.map( x =&amp;gt; math.pow( x - mean , 2 ) ).sum / ( len -1 )

(or use data.view.map() for O(n) traversal -&amp;gt; as explained below)
&lt;/pre&gt;we move on to a more interesting functional approach with view (could be applied to above one as well), note this time we're forcing a non-strict view on our data list, the new Seq from non-strict-view optimises performance since collection is traversed only once and accumulating the sum without a var, this important 'laziness concept' is something that Stream could achieve:
&lt;pre style="color:#2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;def variance = {
 val sum = (data.view foldLeft 0D) {
  case (sum,x) =&amp;gt; sum + math.pow( x - mean , 2 )
 }
( sum / ( len - 1 ) )
}
&lt;/pre&gt;now with inner helper function &amp;amp; pattern matching &amp;amp; recursion, calculating on head and adding via recursion, in order to be able to do this I had to define an inner helper function, (note that: recursive calls create a new stack frame and we could potentially reach at some point in time stack-overflow)
&lt;pre style="color:#2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;def variance = {
def vrec( list:List[Double] ) : Double = list match {
 case head :: tail =&amp;gt; math.pow( head - mean , 2 ) + vrec( tail )
 case _ =&amp;gt; 0D
}
vrec( data ) / ( len - 1 )
}
&lt;/pre&gt; and finally (for this particular impl, and falling back to strict since data is not large), the favourite and refined version is optimal since we added an accumulator on the recursive helper signature to sum up our total via tail-recursion (hinting with @tailrec the compiler with &lt;a href="http://www.scala-lang.org/api/current/scala/annotation/tailrec.html"&gt;optimisation&lt;/a&gt; ):
&lt;pre style="color:#2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;def variance = {
@scala.annotation.tailrec
def vrec(list: List[Double] , tot: Double): Double = list match {
 case head :: tail =&amp;gt; vrec( tail , tot + math.pow( head - mean , 2 ) )
 case _ =&amp;gt; tot / ( len - 1 )
}
vrec(data,0D)
}
&lt;/pre&gt;
Finally, when comparing the java and scala sources afterwards, it did seem a bit  dated to review the imperative way (particularly its redundant verbosity and boilerplate), I don't claim to be an expert on FP nor favour nor force you any specific path, and I'm sure there are more clever ways to do this in FP with syntactic sugar etc, my personal experience and thoughts are subjective, my goal here is to inspire you enough to give it a try yourself (with an open mind) and then you come up with your own conclusions.

What I find important to identify here is the fact that when forcing  ourselves to think differently (which applies in  general terms not just FP, and regardless of language or syntax flavour or complexity at hand) we should always strive for:

&lt;ul&gt;&lt;li&gt;Eliminate repetitive duplication: [inspired by &lt;a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt; &amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Abstraction_principle_%28programming%29"&gt;abstraction&lt;/a&gt; principles].&lt;/li&gt;&lt;li&gt;Eradicate side effects, specially on unrelated matters, foster immutable things: [inspired by the &lt;a href="http://en.wikipedia.org/wiki/Principle_of_Orthogonal_Design"&gt;orthogonal&lt;/a&gt; principle].&lt;/li&gt;&lt;li&gt;Design  implementations (with intermediate results) that are self-contained,  independent, and with a single loose coupled well-defined purpose [inspired by law  of &lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;demeter&lt;/a&gt;].&lt;/li&gt;&lt;/ul&gt;
We must admit though, the polyglot of new JVM languages is raising the bar in language design and engineering, the peril of the ones falling behind is the opportunity for the new ones to blossom, exciting to see languages evolve and improve :-)

Till next one, cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-1868986895171545846?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/1868986895171545846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=1868986895171545846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/1868986895171545846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/1868986895171545846'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2011/05/embracing-functional-programming.html' title='Embracing Functional Programming'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-5771568420582271253</id><published>2011-04-20T21:16:00.000-07:00</published><updated>2011-10-15T10:14:04.297-07:00</updated><title type='text'>CloudFoundry PaaS Test Drive</title><content type='html'>I checked out today the recently announced VMWare SpringSource &lt;a href="http://cloudfoundry.org/"&gt;PaaS&lt;/a&gt;, I'll have to admit that my first experience went pretty well, from 0 to up &amp;amp; running in the cloud in less than 15 min total (excluding download time from maven for some dependencies, your mileage may vary :), this is amazingly RAD!!. I used the vmc client instead of the STS plug-in, I needed an app to deploy so I used &lt;a href="http://www.springsource.org/roo"&gt;Roo&lt;/a&gt; (which also has a &lt;a href="http://www.springsource.org/roo/guide?w=base-cloud-foundry"&gt;plugin&lt;/a&gt;) to generate the PetClinic app from sample script file that ships with it, below are my foot-steps, follow along if you happen to be checking it out too:
&lt;pre style="color: rgb(42, 0, 255); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;# install ruby, below is the ubuntu distro way, use pkg installer accordingly
sudo apt‐get install ruby‐full
sudo apt‐get install rubygems
sudo install gem vmc
# either add to $PATH on .bashrc or just create quickly an alias as below
alias vmc='/var/lib/gems/1.8/bin/vmc'
# once installed then launch vmc then with a target cloud + login
vmc target api.&lt;span class="highlight"&gt;cloud&lt;/span&gt;foundry.com
vmc login
&amp;gt; enter email and password, you can use 'vmc passwd' to reset given temp password
&amp;gt; roo
script /samples/clinic.roo
perform package
exit
cd yourRooProjRoot/target/petclinic-0.1.0.BUILD-SNAPSHOT
vmc push
# accept all defaults and give a unique name
&lt;/pre&gt;&lt;a style="font-weight: bold;" target="_blank" href="https://petclinicroo.cloudfoundry.com/"&gt;https://petclinicroo.cloudfoundry.com&lt;/a&gt;

And below are some useful vmc app commands you can run afterwards:
&lt;ul&gt;&lt;li&gt;vmc -h&lt;/li&gt;&lt;li&gt;vmc apps&lt;/li&gt;&lt;li&gt;vmc stats petclinicroo&lt;/li&gt;&lt;li&gt;vmc logs petclinicroo&lt;/li&gt;&lt;li&gt;vmc instances petclinicroo&lt;/li&gt;&lt;li&gt;vmc logout&lt;/li&gt;&lt;/ul&gt;I found the vmc client very straightforward to use.

Though this is a very plain app test drive, what's important to identify here is (which I found better than other solutions):

&lt;li&gt;Support for some JVM languages
&lt;/li&gt;&lt;li&gt;Data storage SQL + NoSQL support [MySQL,MongoDB,Redis], more to come&lt;/li&gt;&lt;li&gt;Open paradigm, no lock in, public, private and cross infrastructure&lt;/li&gt;
PaaS is becoming the imminent sweet-spot for application developers, and VMware has stepped up the game in the future of the cloud.

Update: 08/10/2011, here's a PoC js data grid doing CRUD ops (some features not implemented) invoking RESTful service using provisioned MongoDB for persistence and Spring profiles 
&lt;br/&gt;
&lt;a style="font-weight: bold;" target="_blank" href="https://restgrid.cloudfoundry.com/"&gt;https://restgrid.cloudfoundry.com&lt;/a&gt;
&lt;span style="color: rgb(51, 102, 255);font-size:85%;" &gt;
(System.getenv("VCAP_APPLICATION") != null) ? "Cloud" : "Local" )&lt;/span&gt;
&lt;pre class="brush: java;"&gt;
public class CloudApplicationContextInitializer implements
              ApplicationContextInitializer&amp;lt;ConfigurableApplicationContext&amp;gt; {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
  CloudEnvironment env = new CloudEnvironment();
    if (env.getInstanceInfo() != null) {
      applicationContext.getEnvironment().setActiveProfiles("cloud");
    } else {
      applicationContext.getEnvironment().setActiveProfiles("dev");
    }
  }
}
&lt;/pre&gt;
&lt;pre style="color: #2A00FF; background: none repeat scroll 0% 0% #F6F8FF"&gt;&amp;lt;mongo:db-factory id="mongoDbFactory"
 dbname="#{serviceProperties['mongodb-db.db']}"
 host="#{serviceProperties['mongodb-db.hostname']}"
 port="#{serviceProperties['mongodb-db.port']}"
 username="#{serviceProperties['mongodb-db.username']}"
 password="#{serviceProperties['mongodb-db.password']}"
/&amp;gt;             

&amp;lt;bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate"&amp;gt;
&amp;lt;constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/&amp;gt;
&amp;lt;/bean&amp;gt;

&amp;lt;beans profile="dev"&amp;gt;
&amp;lt;util:properties id="serviceProperties"&amp;gt;
&amp;lt;prop key="mongodb-db.db"&amp;gt;db&amp;lt;/prop&amp;gt;
&amp;lt;prop key="mongodb-db.hostname"&amp;gt;127.0.0.1&amp;lt;/prop&amp;gt;
&amp;lt;prop key="mongodb-db.port"&amp;gt;27017&amp;lt;/prop&amp;gt;
&amp;lt;prop key="mongodb-db.username"&amp;gt;xxx&amp;lt;/prop&amp;gt;
&amp;lt;prop key="mongodb-db.password"&amp;gt;xxx&amp;lt;/prop&amp;gt;
&amp;lt;/util:properties&amp;gt;
&amp;lt;/beans&amp;gt;

&amp;lt;beans profile="cloud"&amp;gt;
&amp;lt;cloud:service-properties id="serviceProperties"/&amp;gt;
&amp;lt;/beans&amp;gt;
&lt;/pre&gt;
&lt;pre style="color: #66FF00; background: none repeat scroll 0% 0% #000000"&gt;$ vmc apps
+--------------+----+---------+-------------------------------+------------+
| Application  | #  | Health  | URLS                          | Services   |
+--------------+----+---------+-------------------------------+------------+
| petclinicroo | 1  | RUNNING | petclinicroo.cloudfoundry.com |            |
| restgrid     | 1  | RUNNING | restgrid.cloudfoundry.com     | mongodb-db |
+--------------+----+---------+-------------------------------+------------+
$ vmc services
============== System Services ==============
+----------+---------+-------------------------------+
| Service  | Version | Description                   |
+----------+---------+-------------------------------+
| mongodb  | 1.8     | MongoDB NoSQL store           |
| mysql    | 5.1     | MySQL database service        |
| rabbitmq | 2.4     | RabbitMQ messaging service    |
| redis    | 2.2     | Redis key-value store service |
+----------+---------+-------------------------------+
=========== Provisioned Services ============
+------------+---------+
| Name       | Service |
+------------+---------+
| mongodb-db | mongodb |
+------------+---------+
&lt;/pre&gt;
&lt;br/&gt;
Update 09/2011 I'd like to share a project (that recently deployed to the cloud) from &lt;a style="font-weight: bold;" target="_blank" href="http://martinzoldano.blogspot.com/2011/05/embracing-functional-programming.html"&gt;post&lt;/a&gt; which plots in a graph histogram for given datasets (you can select multiple rows to view combined results)
&lt;br/&gt;
&lt;a style="font-weight: bold;" target="_blank" href="https://rest-stats.cloudfoundry.com/"&gt;https://rest-stats.cloudfoundry.com&lt;/a&gt;
&lt;br/&gt;
And the respective System.getProperties() + System.getenv() could be seen &lt;a style="font-weight: bold;" target="_blank" href="https://rest-stats.cloudfoundry.com/rest/env"&gt;here&lt;/a&gt;

Cheers&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-5771568420582271253?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/5771568420582271253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=5771568420582271253' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/5771568420582271253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/5771568420582271253'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2011/04/cloudfoundry-paas-test-drive.html' title='CloudFoundry PaaS Test Drive'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-4869717714788817463</id><published>2011-02-11T15:03:00.000-08:00</published><updated>2011-04-20T21:59:11.104-07:00</updated><title type='text'>Learning Scala</title><content type='html'>I ventured to learn Scala few weeks ago (my new year + long postponed resolution), inspired by its balanced hybrid functional programming and object oriented approach, it's basically like Java on steroids. Scala has so many great features, I can not begin to mention what captivated me from the moment I started reading Martin Odersky's &lt;span style="font-size:85%;"&gt;&lt;a href="http://www.artima.com/shop/programming_in_scala"&gt;book&lt;/a&gt; + &lt;a href="http://www.apress.com/book/view/9781430219897"&gt;book&lt;/a&gt; + &lt;a href="http://oreilly.com/catalog/9780596155957/index.html"&gt;book&lt;/a&gt;&lt;/span&gt; . This post is aimed to share my first steps and my discoveries, perhaps it can help you if you happen to be at the early stages as well.
Primarily what captured my attention was the fact that you can extend the language, in this post we'll see later on how you can code control structure abstractions, this concept has a lot of potential for exploration!
I'll have to admit that my brain is used to think OO the imperative way, as most of us that are Java developers for years, the functional syntax at first bends your mind and tricks your logic, but with time things start blending and sinking in. You'll probably still notice in my code examples I still tend to approach coding with imperative tone, so please forgive my short-comings :)
I'd like to begin with &lt;a href="http://www.scala-lang.org/node/166"&gt;this&lt;/a&gt; and &lt;a href="http://code.google.com/p/simple-build-tool"&gt;SBT&lt;/a&gt;, here are few simple tasks that I added to my first project, just drop this example under &lt;span style="color: rgb(51, 102, 255);"&gt;/projroot/project/build/build.scala&lt;/span&gt; , and you'll see the tasks when invoking sbt at the shell and then 'actions', the 'meta' task is helpful to dump internal settings such as repos, cp, etc, I really like this tool, simple  concise and extendible, you can configure it to  manage dependencies and multiple sub projects, etc.
&lt;pre style="color: rgb(0, 0, 0); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;import sbt._ , sbt.&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;Process&lt;/span&gt;._ , &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;Process&lt;/span&gt;._  
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;class&lt;/span&gt; MySBT(info: ProjectInfo) &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;extends&lt;/span&gt; DefaultProject(info) {

val home = Path.fromFile(&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;System&lt;/span&gt;.getenv(&lt;span style="color: rgb(42, 0, 255);"&gt;"HOME"&lt;/span&gt;))
val libRepo = home / &lt;span style="color: rgb(42, 0, 255);"&gt;"projs"&lt;/span&gt; / &lt;span style="color: rgb(42, 0, 255);"&gt;"repository"&lt;/span&gt; / &lt;span style="color: rgb(42, 0, 255);"&gt;"lib"&lt;/span&gt; ** &lt;span style="color: rgb(42, 0, 255);"&gt;"*.jar"&lt;/span&gt;
&lt;span style="color: rgb(63, 127, 89);"&gt;//override def unmanagedClasspath = super.unmanagedClasspath +++ libRepo   &lt;/span&gt;
&lt;span style="color: rgb(63, 127, 89);"&gt;//override def mainClass = Some("org.martin.cli.ScellMain")
//override def compileOptions = super.compileOptions ++ compileOptions("-verbose","-optimize") &lt;/span&gt;
override def artifactID = &lt;span style="color: rgb(42, 0, 255);"&gt;"xxx"&lt;/span&gt;

lazy val q    = task { println(&lt;span style="color: rgb(42, 0, 255);"&gt;"bye&lt;/span&gt;&lt;span style="color: rgb(42, 0, 255);"&gt;\n&lt;/span&gt;&lt;span style="color: rgb(42, 0, 255);"&gt;"&lt;/span&gt;);&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;System&lt;/span&gt;.exit(0); None } describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"quit"&lt;/span&gt;)
lazy val env  = task { &lt;span style="color: rgb(42, 0, 255);"&gt;"env"&lt;/span&gt; ! log; None } describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"dump env vars"&lt;/span&gt;)
lazy val ll   = task { &lt;span style="color: rgb(42, 0, 255);"&gt;"ls -al"&lt;/span&gt; ! log; None } describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"list all files @ dir"&lt;/span&gt;)
lazy val fjar = task {
&lt;span style="color: rgb(42, 0, 255);"&gt;"find project -name *.jar"&lt;/span&gt; ! log
None
} describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"find project -name *.jar"&lt;/span&gt;)

lazy val xb = task {
&lt;span style="color: rgb(42, 0, 255);"&gt;"./bin/scalaxb -d ./xsd -p com.company.sso -v ./xsd/sso.xsd"&lt;/span&gt; ! log
None
} describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"scalaxb stub generation"&lt;/span&gt;)

lazy val meta = task {
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"repositories"&lt;/span&gt;);
repositories.foreach(println)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"ivyRepositories repositories"&lt;/span&gt;)
ivyRepositories.foreach(println)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"compilation options"&lt;/span&gt;);
compileOptions.foreach(println)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"compilation CP"&lt;/span&gt;)
println(compileClasspath)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"test CP"&lt;/span&gt;)
println(testClasspath)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"main external dependencies"&lt;/span&gt;)
println(mainDependencies.external)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"main libs dependencies"&lt;/span&gt;)
println(mainDependencies.libraries)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"scala dependencies"&lt;/span&gt;)
println(mainDependencies.scalaJars)
println(&lt;span style="color: rgb(42, 0, 255);"&gt;"unmanagedClasspath"&lt;/span&gt;)
println(unmanagedClasspath)
None
} describedAs(&lt;span style="color: rgb(42, 0, 255);"&gt;"dump of main meta properties."&lt;/span&gt;)

&lt;span style="color: rgb(63, 127, 89);"&gt;//...more &lt;/span&gt;&lt;span style="color: rgb(255, 255, 255); background: none repeat scroll 0% 0% rgb(128, 128, 0);"&gt;tasks !!&lt;/span&gt;
}
&lt;/pre&gt;Next, I started coding samples in the $scala interpreter snippets from the books, I found this video an excellent and fun resource &lt;a href="http://www.youtube.com/watch?v=YpjKzKzC7jI"&gt;REPL&lt;/a&gt;, so below is a 'script.scala' skeleton for drop and enhance for your needs, it contains few utility you might find useful.
&lt;pre style="color: rgb(0, 0, 32); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;&lt;span style="color: rgb(89, 89, 121);"&gt;#!/bin/sh&lt;/span&gt;
&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(16, 96, 182);"&gt;"    ________ ___   __   ___     Scala Shell Script"&lt;/span&gt;
&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(16, 96, 182);"&gt;"   / __&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; __&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; _ | / /  / _ |"&lt;/span&gt;
&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(16, 96, 182);"&gt;" __&lt;/span&gt;&lt;span style="color: rgb(15, 105, 255);"&gt;\ &lt;/span&gt;&lt;span style="color: rgb(15, 105, 255);"&gt;\/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; &lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/__&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; __ |&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; &lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/__&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; __ |"&lt;/span&gt;
&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(16, 96, 182);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/____&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(15, 105, 255);"&gt;\_&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;__/_&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; |&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;_/____/_&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt; |_|"&lt;/span&gt;
&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;exec&lt;/span&gt; scala &lt;span style="color: rgb(16, 96, 182);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 125, 69);"&gt;$0&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"&lt;/span&gt; &lt;span style="color: rgb(16, 96, 182);"&gt;"$@"&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;!&lt;/span&gt;&lt;span style="color: rgb(89, 89, 121);"&gt;#&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;
lazy val home    &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; System&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getenv&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"HOME"&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
lazy val usr     &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; System&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getenv&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"USERNAME"&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
lazy val &lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;pwd&lt;/span&gt;     &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; System&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getProperty&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"user.dir"&lt;/span&gt;,&lt;span style="color: rgb(16, 96, 182);"&gt;"."&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
lazy val host    &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; java&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;net&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;InetAddress&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getLocalHost&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getHostName
lazy val props   &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; System&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getProperties&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;list&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;System&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;out&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt; props
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;for&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; arg &lt;span style="color: rgb(227, 74, 220);"&gt;&amp;lt;&lt;/span&gt;- args &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; println&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; arg &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;
println&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; usr + &lt;span style="color: rgb(16, 96, 182);"&gt;"@"&lt;/span&gt; + host + &lt;span style="color: rgb(16, 96, 182);"&gt;":"&lt;/span&gt; + &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;new java&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;util&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;Date&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; + &lt;span style="color: rgb(16, 96, 182);"&gt;":"&lt;/span&gt; + &lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;pwd&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt; below is a naive interpreted script &lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;for&lt;/span&gt; demo
import java&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;io&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;File

def files &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;new File&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;pwd&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;listFiles

def filesMatching&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; String, matcher&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;String, String&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; =&lt;span style="color: rgb(227, 74, 220);"&gt;&amp;gt;&lt;/span&gt; Boolean&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;for&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;file &lt;span style="color: rgb(227, 74, 220);"&gt;&amp;lt;&lt;/span&gt;- files&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;if&lt;/span&gt; matcher&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;file&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;getName, query&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;) yield file
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;}&lt;/span&gt;

def filesEnding&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; String&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;     &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; filesMatching&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query, _&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;endsWith&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;_&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
def filesContaining&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; String&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; filesMatching&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query, _&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;contains&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;_&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
def filesRegex&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; String&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;      &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; filesMatching&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;query, _&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;matches&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;_&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;

def dump&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; list&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt;List&lt;span style="color: rgb(48, 128, 128);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;File&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt; &lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;for&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; x &lt;span style="color: rgb(227, 74, 220);"&gt;&amp;lt;&lt;/span&gt;- list &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; println&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; x&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;toURI &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;}&lt;/span&gt;

dump&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; filesEnding&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"*"&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;toList &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
dump&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; filesContaining&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;"scala"&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;toList &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
dump&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; filesRegex&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;".*"&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;toList &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
/&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;&lt;span style="color: rgb(64, 1, 90);"&gt;/&lt;/span&gt;
&lt;/pre&gt;Once I run many book samples I began writing a small sample project, here's where I found a lack of tooling in the IDE arena, since I use Eclipse I soon noticed this &lt;a href="http://www.scala-ide.org/"&gt;plug-in&lt;/a&gt; is coming along but has few rough edges here and there, I'm sure it's just a matter of time. I find very &lt;span style="font-weight: bold;"&gt;handy&lt;/span&gt; launching from the interpreter os bound commands such as: &lt;span style="color: rgb(51, 51, 255);"&gt;scala&amp;gt; :sh gedit source_file.scala&lt;/span&gt; but that's just a matter of personal preference :)
You can take agile approach by launching the interpreter from your IDE, so at your fingertips you can perform REPL for quick snippet PoCs, then pseudo-code a TDD, then code targeted implementations, then materialize tests, then repeat cycle from step#1 etc, continuous building, testing, bug fixing, etc =&amp;gt; profit!!
David Pollack's book pointed out a very elegant approach with a custom control structure that I adopted in my first project, the capability to augment functionally targeted behaviour, in other words let's look at the below Java sample serialising an obj to the file system, this sample is coded this way to depict the point, notice the convenient closeStream()
&lt;pre style="color: rgb(0, 0, 32); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;public void write&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; final String file , final Serializable serializable &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
throws IOException &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt;
final FileOutputStream     fos &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; new FileOutputStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; file &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
final BufferedOutputStream bos &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; new BufferedOutputStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; fos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
final GZIPOutputStream     zos &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; new GZIPOutputStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; bos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
final ObjectOutputStream   out &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; new ObjectOutputStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; zos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
out&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;writeObject&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; serializable &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
closeStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; out &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
closeStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; zos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
closeStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; bos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
closeStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; fos &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
&lt;span style="color: rgb(64, 96, 128);"&gt;}&lt;/span&gt;
public void closeStream&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; final OutputStream stream &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt;
try &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;   if&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; stream &lt;span style="color: rgb(68, 170, 221);"&gt;!=&lt;/span&gt; null &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;
  stream&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;close&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;;&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt; }&lt;/span&gt; catch &lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt;final Exception e&lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;}&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;}&lt;/span&gt;
&lt;/pre&gt;It'd be nice if we could delegate the control to an abstraction via separation of concern so it can do it for us instead, this 'loan pattern' could be handy if  consumers of your API could potentially forget to close resources such as tcp /db connections (very typical to see that in poorly written direct jdbc + io etc ): let's see how functional can help here
&lt;pre style="color: rgb(0, 0, 0); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;&lt;span style="color: rgb(63, 127, 89);"&gt;&lt;/span&gt;def &lt;span style="font-weight: bold;"&gt;streaming&lt;/span&gt;[T &amp;lt;:{def close():Unit}, R](target: T)(func: T =&amp;gt; R): R =
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;try&lt;/span&gt; {
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;  &lt;/span&gt;func(target)&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&lt;/span&gt;
} &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;finally&lt;/span&gt; {
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;  try&lt;/span&gt; {
  target.close()
  println(&lt;span style="color: rgb(42, 0, 255);"&gt;"closed "&lt;/span&gt;+target)
 } &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;catch&lt;/span&gt; { &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;case&lt;/span&gt; _ =&amp;gt; }
}
&lt;/pre&gt;Don't worry too much on the syntax above, we'll review it later, by looking below at read() you'll see the benefits, syntax looks concise and cleaner:
&lt;pre style="color: rgb(0, 0, 0); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;def read[T]( file:&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;String&lt;/span&gt; ) : T = {
streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;FileInputStream&lt;/span&gt;( file ) )   { fis =&amp;gt;
 streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;BufferedInputStream&lt;/span&gt;( fis ) ){ bis =&amp;gt;
  streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;GZIPInputStream&lt;/span&gt;( bis ) )    { zis =&amp;gt;
   streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;ObjectInputStream&lt;/span&gt;( zis ) )  { ois =&amp;gt; {
    val t = ois.readObject.asInstanceOf[T]
    println("read " + t)
    t
    }
   }
  }
 }
}
}

def write( file:&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;String&lt;/span&gt; , ref:AnyRef ) : Unit = {
require( ref.isInstanceOf[&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;Serializable&lt;/span&gt;] , &lt;span style="color: rgb(42, 0, 255);"&gt;"not @serializable T"&lt;/span&gt; )
streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;FileOutputStream&lt;/span&gt;( file ) )   { fos =&amp;gt;
 streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;BufferedOutputStream&lt;/span&gt;( fos ) ){ bos =&amp;gt;
  streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;GZIPOutputStream&lt;/span&gt;( bos ) )    { zos =&amp;gt;
   streaming( &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;ObjectOutputStream&lt;/span&gt;( zos ) )  { out =&amp;gt;
    out.writeObject( ref )
    println("wrote " + ref )
   }
  }
 }
}
}
&lt;/pre&gt;Let's review the control parameterised signature:
&lt;span style="color: rgb(51, 51, 255);"&gt;def streaming[ T , R ]( target: T )( func: T =&amp;gt; R ): R = { .. }&lt;/span&gt;
type T func(target) returns a type R which R can then be accessed within scope
&lt;span style="color: rgb(51, 51, 255);"&gt;def streaming[T &amp;lt;:{def close():Unit}, R](target: T)(func: T =&amp;gt; R): R = {.. }&lt;/span&gt;
now with a structural type bound on type T that must have public 'close' method in T.
Scala allows you to define types based on their structure and pass functions as parameters, which is a very powerful thing.
&lt;pre style="color: rgb(0, 0, 0); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;@serializable
@SerialVersionUID(1234L)
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;class&lt;/span&gt; SerializableType(
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;   private&lt;/span&gt; val id: Int,
 @BeanProperty val name: &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;String&lt;/span&gt;,
 @BeanProperty val list: &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;List&lt;/span&gt;[Int] ) {
 val tm: Long = System.currentTimeMillis
 override def toString() = {
 tm + " ID: " + id + " - " + name + " : " + list
}
}

object IoDemo {
def main(args: Array[String]) = {
import org.martin.scala.{SerializableType =&amp;gt; Pojo} // aliased
val ser:IoDemo = new IoDemo
val file = "/tmp/scala.gzip"
val t = new Pojo(100,"serialization test",List(1,2,3,4,5))
ser.write( file , t )
val tt = ser.read[Pojo]( file )
}
&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&lt;/span&gt;}
&lt;/pre&gt;Here we have a pojo class with @serializable annotation, one being a List (immutable) collection and a companion object (singleton) with a main() as a poor-man-test, if then compiled and run it yields:
&lt;pre style="color: rgb(85, 204, 102); background: none repeat scroll 0% 0% rgb(0, 24, 0);"&gt;wrote 1297557333613 ID: 100 - serialization test : List(1,2,3,4,5)
closed java.io.ObjectOutputStream@1a786c3
closed java.util.zip.GZIPOutputStream@18088c0
closed java.io.BufferedOutputStream@1922221
closed java.io.FileOutputStream@191d8c1

read 1297557333613 ID: 100 - serialization test : List(1,2,3,4,5)
closed java.io.ObjectInputStream@c832d2
closed java.util.zip.GZIPInputStream@1808199
closed java.io.BufferedInputStream@1bc887b
closed java.io.FileInputStream@a46701
&lt;/pre&gt;We can now see from output how the streams are closed accordingly in relevant order.

Below is another handy one, with conditional logic, appending to a mutable list buffer of T and returning an immutable list of T.
&lt;pre style="color: rgb(0, 0, 32); background: none repeat scroll 0% 0% rgb(246, 248, 255);"&gt;def whiletrue&lt;span style="color: rgb(48, 128, 128);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;T&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; &lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;continue&lt;/span&gt; &lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; =&lt;span style="color: rgb(227, 74, 220);"&gt;&amp;gt;&lt;/span&gt; Boolean &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; &lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;in&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; =&lt;span style="color: rgb(227, 74, 220);"&gt;&amp;gt;&lt;/span&gt; T &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;:&lt;/span&gt; List&lt;span style="color: rgb(48, 128, 128);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;T&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;{&lt;/span&gt;
val buffer &lt;span style="color: rgb(68, 170, 221);"&gt;=&lt;/span&gt; new ListBuffer&lt;span style="color: rgb(48, 128, 128);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(16, 96, 182);"&gt;T&lt;/span&gt;&lt;span style="color: rgb(48, 128, 128);"&gt;]&lt;/span&gt;
&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;  while&lt;/span&gt;&lt;span style="color: rgb(64, 96, 128);"&gt;(&lt;/span&gt; &lt;span style="color: rgb(119, 121, 187); font-weight: bold;"&gt;continue&lt;/span&gt; &lt;span style="color: rgb(64, 96, 128);"&gt;)&lt;/span&gt; buffer += &lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;in&lt;/span&gt;
buffer&lt;span style="color: rgb(32, 0, 128); font-weight: bold;"&gt;.&lt;/span&gt;toList
&lt;span style="color: rgb(64, 96, 128);"&gt;}&lt;/span&gt;
&lt;/pre&gt;Conclusion, imagine taking these concepts even further, combining them with even more abstractions, by now you should have a taste of some functional approach and few of so many great Scala features, I could enumerate some that stand out: type inference, foster immutable state, pattern matching, actors, traits, closures, implicit conversions, and the list goes on.
Learning a new language is a quite an experience, you need to step out of your comfort zone and take a whole bunch of new stuff in,  after few weeks of reading and coding in Scala, I can tell you that it's been an amazing venture for me, and the journey has just begun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-4869717714788817463?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/4869717714788817463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=4869717714788817463' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4869717714788817463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4869717714788817463'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2011/02/learning-scala.html' title='Learning Scala'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-3238370890666865216</id><published>2011-01-02T13:39:00.000-08:00</published><updated>2011-01-02T22:21:38.623-08:00</updated><title type='text'>HMAC(rfc2104) based RESTful service Auth*</title><content type='html'>HMAC: Keyed-Hashing for Message Authentication is a good way to assure content from source has not been tampered when it reaches end-point in an un-secured network.
I remember implementing many SOAP web services compliant to most OASIS WS-* specs which at the end one could feel the over engineering aspect of it, the soap headers ended up bloated with ws-security-messaging-policy-*, etc. In contrast nowadays with RESTful services there's not much about it due to the nature of being fairly recent in the industry, I kept thinking the other day how one can somewhat use hmac approach but instead of hashing on the check-sum of msg content, instead it would then do it on a predetermined token given by the server, so in this case let's say we're interested more on authenticity than data integrity.
Let's imagine we have a RESTful service at hand and you then get a  requirement to secure it with a auth-messaging way,  eventually having SSL privacy at the transport layer would be ideal scenario combined with this. With a predetermined token which then via a secret shared key would yield a different hash per request which then can be regenerated and verified on the server side. Let's say the secret shared key (in this example) is based on chronological time-stamp + some offset secret computation that both ends know in advance (but you could dictate how that is formulated), then hashing it say via sha-1, that would yield a unique nonce per request which server can even detect brute-force attacks with static token spoofing. This one-off approach is what I wanted to base the experiment on. After reading few sources &lt;a href="http://oauth.net/"&gt;oauth&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/HMAC"&gt;wiki&lt;/a&gt;, &lt;a href="http://www.faqs.org/rfcs/rfc2104.html"&gt;rfc2104&lt;/a&gt;, &lt;a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/2007-05-01/SQSDeveloperGuide/SummaryOfAuthentication.html"&gt;amazon&lt;/a&gt;, etc, I then got inspired to start off the new year with this new experiment. First I wanted to make it easy to throw a filter into the chain and let it take care of the matter without touching a line of code my existing rest services, the only impact would be that the client would have to first get a security token prior to accessing services.
Here's a chart to depict the flow of execution:
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/TSFFqnh4EKI/AAAAAAAAAds/eIRd6mfuyXY/s1600/HMAC-RESTful-AUTH.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 247px; height: 320px;" src="http://2.bp.blogspot.com/_M94eDahX5rM/TSFFqnh4EKI/AAAAAAAAAds/eIRd6mfuyXY/s320/HMAC-RESTful-AUTH.png" alt="" id="BLOGGER_PHOTO_ID_5557800013619794082" border="0" /&gt;&lt;/a&gt;
Step-3 could be removed or changed, it checks if client source address matches the one generated upon client obtaining token, if consumer comes through say a proxy then same token will be given but then the nonce check will have to be respected to pass check-1, or you could pre-generate tokens per client/ip and look up that list to verify, etc.
So the experiment worked just fine, up until I then I created a thin web client to consume and test it, and by thin I mean with html + js, which anybody can right-click and then.....sniff in, so enter code obfuscation + encoding as a way to at least make things harder to reverse-engineer. Here's the &lt;a href="http://oauth.googlecode.com/svn/code/javascript/sha1.js"&gt;sha-1&lt;/a&gt; impl used and upon consumer obtaining /sectoken the server then returns the obfuscated+encoded js which then you could dynamically inject it into to the dom (see ref-impl). Again it's not perfect it but it'll sure take some work to puzzle it together :)
Now the filter implementation is based on a &lt;a href="http://martinzoldano.blogspot.com/2009/12/thread-safe-mapcache-with-reaper_07.html"&gt;ConcurrentHashMap&lt;/a&gt; that has an eviction reaper, if a client does not refresh cache access times-tamp it'll evict token and client will have to fetch a token once again, for the most part you could just read the code and follow through, I included the thin html client.
One thing I wanted to mention is that upon emulating a brute-force flood of reqs (kinda DoS attack from same source) with a static nonce spoof, the filter detects it and sends an HTTP err, since the salt on client is based on time-stamp (factored by / 500) -&gt; consumer can send up to couple requests per second, server side will serve in discrete mode as long as nonce is unique and incrementally sequential in chronological order from last request, that also causes the hash to be unique per request, below is a screen dump from my fire-bug console displaying some ajax calls, let's take a look:
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/TSEJjKoViAI/AAAAAAAAAdk/ZFLDBqLZYeg/s1600/Screenshot.jpg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 180px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/TSEJjKoViAI/AAAAAAAAAdk/ZFLDBqLZYeg/s320/Screenshot.jpg" alt="" id="BLOGGER_PHOTO_ID_5557733914905511938" border="0" /&gt;&lt;/a&gt;Well, this experiment was fun to implement, as always, take it with a "grain of salt" :)  enhance accordingly if taken as is, maybe it inspires you as well or it gives you an idea as it occurred to me, as long as the secret key is unique in your implementation then you'll be ok.
Here's the reference implementation archive &lt;a href="http://bit.ly/gXmXXF"&gt;link&lt;/a&gt;.
Happy 2011!, cheers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-3238370890666865216?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/3238370890666865216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=3238370890666865216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3238370890666865216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3238370890666865216'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2011/01/hmacrfc2104-based-restful-service-auth.html' title='HMAC(rfc2104) based RESTful service Auth*'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M94eDahX5rM/TSFFqnh4EKI/AAAAAAAAAds/eIRd6mfuyXY/s72-c/HMAC-RESTful-AUTH.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-876501596013280130</id><published>2010-10-31T20:06:00.000-07:00</published><updated>2010-12-04T17:36:32.932-08:00</updated><title type='text'>XSS + SQL Injection Filter</title><content type='html'>The dangers are vast from blindly accepting requests these days for any public service that receives requests from clients in the web galaxy out there which could potentially lead to malicious xss | sql | etc injections, last week we started installing mod_security for apache httpd which is an open source intrusion detection that can run embedded or as a reverse proxy. The problem is, what if you do &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; run httpd in front of your servlet container or jee app server, then you need to have a way to intercept all requests before they reach your application, that's where filters come to the rescue, here's a naive reference implementation filter that wraps the HttpServletRequest object by cloning the parameters state and sanitising  them via naive regex token replacement, I recommend reading the OWASP instructions for &lt;a href="http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet"&gt;XSS&lt;/a&gt; and &lt;a href="http://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet"&gt;SQL&lt;/a&gt; there you'll see the top 10 most important rules to follow to avoid becoming a victim of sneaky malicious intents from our widely open and untrustworthy www.
I see two approaches here, a pessimistic IDS as intrusion detection (kind of mod_security)  or a more optimistic one via content sanitation, take source as a reference implementation and adjust it to your needs, configure the rules with "log" and watch the noise and also the false positives (paranoid rules) and craft then specific regular expressions since I'm sure there'll be new tricky permutations over time. I included the OWASP encoding api calls there for you to investigate, drop me a line with your experiences | discoveries, again this is by no means a full fledged silver bullet but it'll give you an idea on how to approach xss via a filter, security is a huge matter as we know it.
I'm kind of troubled to see how much overhead mod_security will add to the farm by pre-processing hundreds of crazy regular expressions on every request (on top of the ones that the load balancer already does prior), seems to me a bit too exhaustive, so we'll just have to find out soon :)

Few rules with their corresponding regex, the paranoid ones should always log, once a specific rule+expression behaves as intended then promote it to deny (just make sure you're certain it won't deny on false positive, the tricky part!).
&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;
###################################################################################################################
# XSS injections
# html paranoid xss regex base exp (traps lots of false +)
0=log all ^(.*?)(?i)((\\%3C)|\\&amp;lt;)[^\\n]+((\\%3E)|\\&amp;gt;)(.*?)$
# http://www.owasp.org/index.php/HTTP_Response_Splitting
1=log all ^(.*?)(?i)((\\r\\n)+|\\r|\\n|(%0d%0a)+|%0d|%0a)(.*?)$
2=log all ^(.*?)(?i)(\\&amp;lt;|(\\%3C)|&amp;amp;#x73;lt;|&amp;amp;amp;lt;|&amp;amp;lt;|&amp;amp;#60;|&amp;amp;#x3C;)(script|img|%0D)(.*?)$
3=log all ^(.*?)(?i)eval\\((.*)\\)(.*?)$
4=log all ^(.*?)(?i)[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\'](.*?)$
# SQL-ANSI naive meta keywords injections
#paranoid: ^(.*?)(?i)(delete|grant|insert|drop|replace|truncate|update|create|rename|describe|union|exec|openquery|openrowset|xp_cmdshell|addextendedproc)(.*?)$
5=log all ^(.*?)(?i)[(\\%27)|(\\')]{1}[%20|\\s|:cntrl:]*[(\\%6F)|o|(\\%4F)][(\\%72)|r|(\\%52)]{1}((\\s|\\+|:cntrl:)+).*(delete|grant|insert|drop|alter|replace|truncate|update|create|rename|describe|union)((\\s|\\+|:cntrl:)+)(.*?)$
# MS-SQL-SVR specific meta keywords + hex 0x
6=log all ^(.*?)(?i)(exec|openquery|openrowset|xp_cmdshell|addextendedproc|0x)((\\s|\\+|:cntrl:)+)(.*?)$
###################################################################################################################
&lt;/code&gt;&lt;/pre&gt;Reference source &lt;a href="http://bit.ly/hGICor"&gt;link&lt;/a&gt;.
Cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-876501596013280130?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/876501596013280130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=876501596013280130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/876501596013280130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/876501596013280130'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2010/10/xss-sql-injection-filter.html' title='XSS + SQL Injection Filter'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-8067060202724462697</id><published>2010-10-07T18:24:00.000-07:00</published><updated>2010-10-07T20:09:21.204-07:00</updated><title type='text'>Search Capabilities with Lucene</title><content type='html'>Last weekend I needed to implement a text search feature, I visited apache foundation and reviewed Solr and Lucene projects, about over a decade ago (geez it's been that long) I remember exploring &lt;a href="http://en.wikipedia.org/wiki/Inktomi"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Inktomi&lt;/span&gt;&lt;/a&gt; which after the dot.com bubble was acquired by Yahoo, now with Solr (built on top of Lucene) it offers a large array of features just to mention restful capabilities to manage/submit/query/retrieve content, since I wanted direct access and control over it, here's a straight-forward yet full-fledged implementation class which covers some of the most important topics, eventually it's not possible to go over all of them in a blog post but here's my experience I'd like to share.&lt;div&gt;First, I used the RAMDirectory for in-memory flavor, if you think the index can fit in memory the results will be really snappy, if you have massive content to be index then storing in a file system is the next step, if you run your container on Linux you can use then NIOFSDirectory so then the fs journaling is optimized via NIO (not on MS*s).&lt;/div&gt;&lt;div&gt;Second it's recommendable to always use a single instance of IndexWriter and Searcher over the index, specially if updating on the fly documents/fields, remember to optimize accordingly so then changes are committed.&lt;/div&gt;&lt;div&gt;Third, it is important to mention that QueryParser is not thread-safe.&lt;/div&gt;&lt;div&gt;Fourth, try to keep a single instance of Document | Field, use field.setValue() so then when indexing massive content you avoid GC deallocations of redundant instances.&lt;/div&gt;&lt;div&gt;And last but not least, StandardAnalyzer offers base token digestion but you can implement one as needed to customize the behavior.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Alright then, below are the impl details:&lt;/div&gt;
&lt;pre class="brush: java;"&gt;
package com.martin.server;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class SearchService {

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SearchService.class);

private static final String TOKENIZED = "tok";

private RAMDirectory    index = null;
private IndexWriter    writer = null;
private Searcher     searcher = null;
private Analyzer     analyzer = null;
private IndexableDocument doc = null;

public SearchService() { }

@javax.annotation.PostConstruct
public void start() {
try {
index = new RAMDirectory();
// Directory index = NIOFSDirectory.getDirectory("/fs/.."); // NIO on linux :)
analyzer = new StandardAnalyzer(Version.LUCENE_30);
writer   = new IndexWriter( index ,analyzer, true, IndexWriter.MaxFieldLength.LIMITED);// 10k terms max
//writer.setRAMBufferSizeMB(48); //IndexWriter.DEFAULT_RAM_BUFFER_SIZE_MB 16megs find your sweet-spot
//writer.setMaxFieldLength(40000);  // adjust as needed
//writer.setMergeFactor(300);       // adjust as needed
//writer.setMaxBufferedDocs(150);   // adjust as needed in function of setRAMBufferSizeMB
//writer.setMaxMergeDocs(x)         // adjust as needed if reached 2GB limit at 8M set it to 7M
log.info( "--==[ STARTED ]==--");
} catch (final Exception e) {
 log.error("start()", e);
}
}

@javax.annotation.PreDestroy
public void stop() {
try {
   analyzer.close();
   searcher.close();
   writer.close();
   index.close();
   log.info( "--==[ STOPPED ]==--");
} catch (final Exception e) {
  log.error("stop()", e);
}
}

public void buildIndex() {
try {
  writer.commit();
  writer.optimize(true); // block till done
  log.info( "Search.index.mem.size {} bytes"   , index.sizeInBytes()         );
  log.info( "Search.writer.size.buffer {} megs", writer.getRAMBufferSizeMB() );
  writer.close();
  ////////////////////////////////////
  searcher = new IndexSearcher(index);
  ////////////////////////////////////
} catch (final Exception e) {
  log.error("buildIndex()", e);
}
}

public void addIndexableDocument( final String id , final String name , final String content ) {
try {
if ( doc == null ) {
     doc = new IndexableDocument();
}

doc.setFields( id , name , content );

//////////////////////////////////////  
writer.addDocument(doc.getDocument());
//////////////////////////////////////

log.debug("search.index.added {}",doc.toString());

} catch (final Exception e) {
log.error("addDoc()", e);
}
}

public java.util.List&amp;lt;Document&amp;gt; query( final String text , final int max ) {
java.util.List&amp;lt;Document&amp;gt; results = null;
QueryParser parser = null;
try {
  final String txt = QueryParser.escape( java.net.URLDecoder.decode( text ,"UTF-8") ); //sanitize accordingly
  final String qtx = txt+"*"; // (txt + "* OR " + txt + "~"); // etc, craft your query here
  // Note that QueryParser is not thread-safe !!
  parser = new QueryParser(Version.LUCENE_30, TOKENIZED , analyzer );
  // MultiFieldQueryParser(Version.LUCENE_30, String[] fields, analyzer);
  results = doSearch(  parser.parse( qtx ) , max ) ;
} catch (final Exception e) {
  log.error("search()", e);
}
return results;
}

public java.util.List&amp;lt;Document&amp;gt; doSearch( final Query query , final int max ) throws Exception {
 log.debug("search.query {}", query.toString() );
 final java.util.List&amp;lt;Document&amp;gt; results = new java.util.ArrayList&amp;lt;Document&amp;gt;();
  //final TopScoreDocCollector collector = TopScoreDocCollector.create( max , true );  
  ////////////////////////////////////////////////
  //searcher.search( query , collector );
  final TopDocs hits = searcher.search(query,max);
  ////////////////////////////////////////////////  
  log.info("tothits {} , hits.scoreDocs.length {}", hits.totalHits , hits.scoreDocs.length );    
  if ( hits != null &amp;amp;&amp;amp; hits.scoreDocs.length &amp;gt; 0 ) {
   for( int i=0; i &amp;lt; hits.scoreDocs.length; i++) {
    // log.debug("explain {} ",searcher.explain(query,hits[i].doc));
    results.add( searcher.doc(hits.scoreDocs[i].doc) ); 
   }
  }      
  return results;
}

// customize as needed
public static class IndexableDocument {
public static final String ID = "i";
public static final String NM = "n";

private final Document doc;
private final Field     id;
private final Field   name;
private final Field    tok;

public IndexableDocument() {
 doc  = new Document();
 id   = new Field(ID, "", Field.Store.YES, Field.Index.NOT_ANALYZED);
 name = new Field(NM, "", Field.Store.YES, Field.Index.NOT_ANALYZED);
 tok  = new Field(TOKENIZED, new java.io.StringReader("") ); // not STORED + ANALYZED
 doc.add(id);
 doc.add(name);
 doc.add(tok);
}

public Document getDocument() {
    return doc;
}
     
public void setFields( final String i , final String n , final String tokens ) {
       id.setValue(i);
       name.setValue(n);
       tok.setValue(new java.io.StringReader(tokens)); // use char[]
}
     
@Override
public String toString() {
    return doc.toString();
}
}

}
&lt;/pre&gt;
&lt;div&gt;
And below is a quick test case just to depict usage:
&lt;/div&gt;
&lt;pre class="brush: java;"&gt;
@Test
public void searchQuery() {
try {  

 final SearchService search = new SearchService();  

 search.start();

 for( int i=0; i &amp;lt; 1000; i++) {
 search.addIndexableDocument(String.valueOf(i),"Denim"+String.valueOf(i)    , "denim jeans shorts pant");
 search.addIndexableDocument(String.valueOf(i+1),"Jackets"+String.valueOf(i)  , "jackets collar long sleeve shorts sleeve ");
 search.addIndexableDocument(String.valueOf(i+2),"Underwear"+String.valueOf(i), "underwear bra panties shorts");
 search.addIndexableDocument(String.valueOf(i+3),"Sale"+String.valueOf(i)     , "sale shoes denim jewlery accessories jeans pants shorts jackets watches t-shirts");
 }

 search.buildIndex();

 final List&amp;lt;Document&amp;gt; results = search.query("short",30); 
  
 for( final Document doc : results ) {
    log.info("[ {} ] = {} ",
    doc.get(SearchService.IndexableDocument.ID),
    doc.get(SearchService.IndexableDocument.NM) );
 }

 search.stop();

} catch (final Exception e) {
  e.printStackTrace();
}
}
&lt;/pre&gt;The id fields you choose to store in the index should be as direct and at minimum as possible, so then you can re-hydrate from cache or DB search results, see IndexableDocument and adjust accordingly based on your needs,  wrap that into a restful API returning say json | xml format and voila!  there you have it, or simply go with the Solr wrapper if you need more features, such as admin web interface, distributed index management which could be challenging if one thinks of rolling your own, etc ,etc. In a production environment you would have to account for many other important things, yet here's 'in-a-nut-shell' reference implementation.&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Till the next experiment!, cheers&lt;/div&gt;&lt;div&gt;Martin&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-8067060202724462697?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/8067060202724462697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=8067060202724462697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8067060202724462697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8067060202724462697'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2010/10/search-capabilities-with-lucene.html' title='Search Capabilities with Lucene'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-3883641227772708957</id><published>2010-07-31T10:22:00.000-07:00</published><updated>2010-08-03T08:21:29.267-07:00</updated><title type='text'>Asynchronous Processing via @Annotation + Dynamic Proxy + ExecutorService</title><content type='html'>Hello, I'd like to share an experiment based on a simple asynchronous processing class that acts as a factory and a dynamic proxy to wrap legacy implementation methods that take potentially long execution time blocking from sequential flow into asynchronous non-blocking simplest possible custom refactoring migration.&lt;div&gt;
&lt;/div&gt;&lt;div&gt;The challenges encountered here are:&lt;/div&gt;&lt;div&gt;[1] Legacy overloaded method signature + implementations that return a type.&lt;/div&gt;&lt;div&gt;[2] Provide a clean and easy meta annotation to instruct that a method is a potential task to be wrapped into it's own execution thread.&lt;/div&gt;&lt;div&gt;[3] Such meta annotation should also provide a way to register callback user implementations.&lt;/div&gt;&lt;div&gt;[4] Delegate the task to a proxy that handles all implementation details to clearly separate concerns, utilizing: thread pool, concurrent executor with runnable wrappers, etc.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Let's depict a simple legacy implementation scenario:&lt;/div&gt;
&lt;pre class="brush: java;"&gt;
public interface LegacyDemoInterface {
 public T legacyProcess( final String n , final Long l );
}
// ........
public class LegacyDemoImpl implements LegacyDemoInterface {
 public String legacyProcess( final String n , final Long l ) {
   // usr impl here with long ex tm
   return "x";		
 }
}
&lt;/pre&gt;

So now imagine we could then easily annotate such method like this:

&lt;pre class="brush: java;"&gt;
public class LegacyDemoImpl implements LegacyDemoInterface {

 @AsynchProcess(onSuccess="onAsyncSuccess",onFailure="onAsyncFailure")
 public String legacyProcess( final String n , final Long l ) {
  // usr impl here
  return "x";		
 }
 public &amp;lt;T&amp;gt; void onAsyncSuccess( final T result ) {
   System.out.println("&gt;&gt;onAsyncSuccess : " + result );
 }
 public void onAsyncFailure( final Throwable t ) {
  System.err.println("&gt;&gt;onAsyncFailure : " + t.toString());
 }
}
&lt;/pre&gt;
Providing couple callback user implementations where on the asynchronous notification will take place upon success or failure, without using Future&amp;lt;T&amp;gt; but with similar semantics such as @Async from Spring framework, in this case method 'legacyProcess(..)' returns a type(String) which will be passed as a parameter onto success callback.

So let's dive into the implementation details, first the @AsynchProcess:
&lt;pre class="brush: java;"&gt;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AsynchProcess {
 String onSuccess() default "onSuccess";
 String onFailure() default "onFailure";
}
&lt;/pre&gt;
Then the trick is in Dynamic Proxy Factory, note that it has anonymous class approach (on steroids :) to somewhat aprox + emulate the programming concept of 'closure' which in my words I define as: 'the ability to implement embedded functions with the capability for the inner ones to access variables outside of their scope' with corresponding 'final' parameter declarations, there's also an approach to avoid annotating interfaces as part of a &lt;a href="http://download.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html"&gt;proxy&lt;/a&gt; nature, in this case we annotated implementation class method shown above to bend some rules.
&lt;pre class="brush: java;"&gt;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AsyncProcessEngine {

private static final AsyncProcessEngine instance = new AsyncProcessEngine(); //eagerly
private final Logger log = LoggerFactory.getLogger(AsyncProcessEngine.class);
private final ConcurrentHashMap&amp;lt;string,method&amp;gt; methodCache;
private final ExecutorService execService;

private AsyncProcessEngine() {
 execService = Executors.newCachedThreadPool();
 methodCache = new ConcurrentHashMap&amp;lt;string,method&amp;gt;();
 log.info("-=[ AsyncProcessor singleton ]=-");
}

public static AsyncProcessEngine getInstance() {
 return instance;
}

public static void shutdown() {
 instance.methodCache.clear();
 instance.execService.shutdown();
}

public &amp;lt;T&amp;gt; T createAsyncProxyProcess( final Object target , final Class&amp;lt;T&amp;gt; expectedType ) {
return
expectedType.cast(
  Proxy.newProxyInstance(
    target.getClass().getClassLoader() ,
    target.getClass().getInterfaces()  ,
      new InvocationHandler() {
        @Override
        public Object invoke( final Object proxy  ,
                              final Method method ,
                              final Object[] args ) throws Throwable {
       
          final Method implMethod = target.getClass().
          getMethod( method.getName() , method.getParameterTypes() );
                                                                                                
          if ( !implMethod.isAnnotationPresent( AsynchProcess.class ) ) {
               return method.invoke( target , args ); // filter
          }
        
          log.debug("{} method introspection for: {}" , target.toString() , implMethod.toGenericString() );
       
          instance.execService.submit(
             new Runnable() {
               @Override
               public void run() {
                  Method onSuccess = null;
                  Method onFailure = null;
                  try {
                                         
                     final AsynchProcess async = implMethod.getAnnotation( AsynchProcess.class );                                             
                     final String   keySuccess = target.getClass().getName() + target.hashCode() + async.onSuccess();
                     final String   keyFailure = target.getClass().getName() + target.hashCode() + async.onFailure();
                                          
                     if ( !methodCache.containsKey( keySuccess ) || !methodCache.containsKey( keyFailure ) ) {
                       try {
                         onSuccess = target.getClass().getMethod( async.onSuccess() , new Class&amp;lt;?&amp;gt;[] { Object.class    } );
                         onFailure = target.getClass().getMethod( async.onFailure() , new Class&amp;lt;?&amp;gt;[] { Throwable.class } );
                       } catch (final Exception e) { }
                       if ( onSuccess == null || onFailure == null ) {
                          return;
                       } else {
                          methodCache.put( keySuccess , onSuccess );
                          methodCache.put( keyFailure , onFailure );                
                       }
                     } else {
                       onSuccess = methodCache.get( keySuccess );
                       onFailure = methodCache.get( keyFailure );
                     }

                     ////////////////////////////////////////////////////////////////                             
                     try {                             
                        ////////////////////////////////////////////////////////////
                        //invoke target method and pass ret val into success usrImpl
                        onSuccess.invoke( target , method.invoke( target , args ) );
                        ////////////////////////////////////////////////////////////                             
                     } catch (final Throwable t ) {
                        onFailure.invoke( target , t.getCause() );
                     }
                     ////////////////////////////////////////////////////////////////

                 } catch (final Throwable e) {
                   log.error("woha@run()",e);
                 }
            }
          }
          );                    
          return null;
         }
     }     
 )
);
}
}
&lt;/pre&gt;
We could inject via DI proxied objs as shown previously &lt;a href="http://martinzoldano.blogspot.com/2010/01/hibernate-transaction-management-via.html"&gt;here&lt;/a&gt; with a Spring post processor &lt;meta equiv="content-type" content="text/html; charset=utf-8"&gt;&lt;span class="Apple-style-span"   style="  color: rgb(128, 128, 128); font-family:'Trebuchet MS', Trebuchet, Verdana, sans-serif;font-size:13px;"&gt;@InjectProxiedHbmTxMgr&lt;/span&gt;, but as usual I like keeping things lean and to have control over the behavior that I expect with minimal dependencies possible.

Summary: Again, this concept could be taken to so many different levels, as demonstrated it touches very exciting topics :) specially when approaching legacy code refactoring with minimal impact possible, there are other approaches, here's one I thought of.

Here's the source archive for &lt;a href="http://bit.ly/byUmDe"&gt;download&lt;/a&gt; with a sample reference test.

Alright then, till the next experiment...cheers!
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-3883641227772708957?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/3883641227772708957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=3883641227772708957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3883641227772708957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3883641227772708957'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2010/07/asynchronous-processing-via-annotation.html' title='Asynchronous Processing via @Annotation + Dynamic Proxy + ExecutorService'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-5002741221945811279</id><published>2010-01-22T20:18:00.000-08:00</published><updated>2011-09-16T12:46:17.910-07:00</updated><title type='text'>WebSockets + Netty</title><content type='html'>&lt;div&gt;Web applications have evolved significantly the past decade,  we've all seen an evolution from thin-client with  predominant client/server template-driven paradigms to newer Web2.0 RIA technologies providing smarter clients since now they can do more  with  plugin run-times.&lt;/div&gt;&lt;div&gt;So far, all requests have been orchestrated from the client 'only', there was no standard connectivity over the network in which the server side could push data down to the client at any point of time.&lt;/div&gt;&lt;div&gt;There's a new revolutionising (incubating) technology: &lt;a href="http://dev.w3.org/html5/websockets"&gt;WebSocket&lt;/a&gt;,  in simple words it provides that key connectivity enhancement with full-duplex (bidirectional) communications. It basically eliminates some of the approaches like inefficient polling or long polling developers have been forced to implement in the past wasting redundant network bandwidth and keeping servers bloated with chatty clients.&lt;/div&gt;&lt;div&gt;Moreover, now that &lt;a href="http://jcp.org/en/jsr/detail?id=315"&gt;JSR315 / Servlet3.0&lt;/a&gt; is being adopted by the key player server containers (example Jetty continuations) , we can see that very exciting things are evolving on the server side as well, enabling asynch-NIO + eliminating the blocking thread req/con limitation. &lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Even though specs on both sides are still in draft status, I decided to peek and learn by experimenting on a very simple proof of concept, inspired by few blogs out there, I thought of emulating server broadcasts to client (spawning different threads)  simulating somewhat a real time scenario, so here it goes:&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;First the client, since not all browsers have websocket support yet, I used latest google chrome[4.0.249.43] on my linux ubuntu distribution to test drive this experiment, here's a bare-bone straight-forward html + js client that depicts new features:&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;WebSocket&amp;lt;/title&amp;gt;
&amp;lt;script&amp;gt;
var socket;

function openWebSocket() {
  if (window.WebSocket) {
      socket = new WebSocket('ws://127.0.0.1:8080/websocket');
      socket.onopen    = function(event) { alert('WebSocket open!');  };
      socket.onclose   = function(event) { alert('WebSocket closed'); };
      socket.onmessage = function(event) { parse(event.data);         };
  } else {
      alert('Your browser does not support WebSockets yet.');
  }
}

function closeWebSocket() {
 socket.close();
}

function $(id) {
 return document.getElementById(id);
}

function send(message) {
 if (!window.WebSocket) { return; }
 if (socket.readyState == WebSocket.OPEN) {
     socket.send(message);
 } else {
     alert('The WebSocket is not open!');
 }
}

function parse( response ) {
 // parse response: json or xml, etc
 $('out').innerHTML = response;
}

&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body onload='openWebSocket()' onunload='closeWebSocket()'&amp;gt;
&amp;lt;div id='out'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;!-- more html here --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;And on the  server side, since I wanted to provide a sample project download I wanted to keep it lean and mean, when learning the new jboss messaging project &lt;a href="http://www.jboss.org/hornetq"&gt;hornetq&lt;/a&gt; I noticed that it is based on &lt;a href="http://www.jboss.org/netty"&gt;netty&lt;/a&gt; : client/server NIO framework for network protocols (which by the way its developer has done a great job with a clean impl, kudos! &lt;a href="http://twitter.com/trustin"&gt;Trustin&lt;/a&gt;).&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Below is a link to get the project, look for class EnvStatsProcessor which you will see that it spawns 3 threads (if run on linux), each writes data to corresponding channel simulating almost a real time processing per half &amp;amp; 1 sec sleep intervals. The http handshake + upgrade is on class WebSocketServerHandler  taken from netty), modify EnvStatsProcessor for your needs, you could enhance it to send json/xml fmt, and client could then use js ajax/dom utilities, note that netty supports binary serializations fmt as well, for that you could use its client api in a rich-client like a swing app and using hessian or google protocol buffers for example.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Here's a quick 30 sec screen-cast to see  running: "Look Ma' no polling :)"&lt;/div&gt;&lt;div&gt; (sorry for the low res video, watch in full screen :) &lt;/div&gt;&lt;div&gt;
&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/f0lbm_1sYMU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/f0lbm_1sYMU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Instructions:&lt;/div&gt;&lt;div&gt;[1] download &lt;a href="http://bit.ly/ruzjLK"&gt;project&lt;/a&gt;  (source is included).&lt;/div&gt;&lt;div&gt;[2] extract and cd /mypath/bin&lt;/div&gt;&lt;div&gt;[3] ./run  (or .bat if windows)&lt;/div&gt;[4] open in browser http://127.0.0.1:8080
&lt;div&gt;
Update 09/16/2011: upgraded netty to 3.2.5.final version and works now on my linux ubuntu 11 distro and also latest ms-*

&lt;/div&gt;&lt;div&gt;Cheers.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-5002741221945811279?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/5002741221945811279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=5002741221945811279' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/5002741221945811279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/5002741221945811279'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2010/01/websockets-netty.html' title='WebSockets + Netty'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-4266084431367713384</id><published>2010-01-01T20:07:00.000-08:00</published><updated>2010-01-06T16:04:21.136-08:00</updated><title type='text'>Hibernate Transaction Management via Dynamic Proxy</title><content type='html'>&lt;div&gt;&lt;div&gt;In enterprise applications, transaction management strategy is a very important concept developers need to analyze at early stages of any project architecture cycle.  &lt;/div&gt;&lt;div&gt;Inspired by reading &lt;a href="http://www.packtpub.com/spring-persistence-with-hibernate/book"&gt;book&lt;/a&gt;, I started thinking in how to strike a balance in working directly with hibernate but yet reducing all that boiler-plate redundant session/transaction(commit,rollback) code,  also taking the less intrusive approach via demarcation similar as spring 3 @Transactional as well as reducing external dependencies lock-in. So here's a custom lab reference implementation sample yet simple transaction proxy, let's revisit few patterns in which we'll cover in this post:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
Proxy Pattern: &lt;a href="http://en.wikipedia.org/wiki/Proxy_pattern"&gt;proxy&lt;/a&gt; is a wrapper functioning as an interface intercepting targeted object.
Decorator Pattern: &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;decorator&lt;/a&gt; allows additional behaviour to be added to an existing object dynamically.
DAO pattern: &lt;a href="http://en.wikipedia.org/wiki/Data_access_object"&gt;data layer&lt;/a&gt;/access/persistent operations should be isolated in DAO interfaces + implementations.&lt;/div&gt;&lt;div&gt;
Let's begin by looking at a partial sample configuration:
&lt;pre class="brush: xml;"&gt;
...
&lt;jee:jndi-lookup id="sessionFactory" name="java:/HibernateSessionFactory"&gt;&lt;/jee:jndi-lookup&gt;
...
&lt;bean id="hbmTxMgrProc" class="com.martin.orm.tx.HbmTransactionProxyProcessor"&gt;
&lt;constructor-arg ref="sessionFactory"&gt;&lt;/constructor-arg&gt;
&lt;/bean&gt;

&lt;bean id="someDao" class="com.martin.domain.service.dao.SampleDaoImpl"&gt;
&lt;constructor-arg ref="sessionFactory"&gt;&lt;/constructor-arg&gt;
&lt;/bean&gt;

&lt;bean id="someService" class="com.martin.domain.service.ServiceImpl"&gt;
&lt;flex:remoting-destination channels="asynch-amf"&gt;&lt;/flex:remoting-destination&gt;
&lt;/bean&gt;
...
&lt;/pre&gt;
We certainly could use @Autowire or @Inject internally for collaborators but for the sake of simplicity and demonstration purposes we'll leave as is for now to set the stage and later on we'll inject a proxied target, note that we'll foster composition over inheritance in the implementations, now let's take a look at a simple annotation(method target) for our transaction demarcations:&lt;div&gt;&lt;pre class="brush: java;"&gt;
package com.martin.orm.tx.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HbmProxiedTransaction { }
&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;Here's a sample interface:&lt;pre class="brush: java;"&gt;package com.martin.domain.service.dao;
import java.util.List;
import com.martin.domain.service.dto.Profile;
import com.martin.orm.tx.annotation.HbmProxiedTransaction;
public interface SampleInterface {
// note that is not demarcated, usr programmatic hbm approach
public Profile authenticatePrincipal( final String principal, final String pwd );

@HbmProxiedTransaction
public [T] List[T] execSomeQueryHere( final String someCriteriaBy );
}
&lt;/pre&gt;
Note that demarcation takes place at the interface level, this is due to java &lt;a href="http://java.sun.com/j2se/1.4.2/docs/guide/reflection/proxy.html"&gt;proxies&lt;/a&gt; nature (if you need to proxy a class that has no interface you would need a library like cglib to do so&lt;span class="Apple-style-span"  style="  -webkit-border-horizontal-spacing: 1px; -webkit-border-vertical-spacing: 1px; font-family:verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;)&lt;/span&gt;&lt;span class="Apple-style-span"  style=" -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px;  font-family:Georgia, serif;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;, it could well also be demarcated at the service interface (preferable).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;
Now here's the proxy implementation (based on org.hibernate.context.&lt;a href="https://www.hibernate.org/hib_docs/v3/api/org/hibernate/context/ThreadLocalSessionContext.html"&gt;ThreadLocalSessionContext&lt;/a&gt; configuration)
&lt;pre class="brush: java;"&gt;
package com.martin.orm.tx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.martin.orm.tx.annotation.HbmProxiedTransaction;

public class HbmTransactionProxyMgr implements InvocationHandler {

private final Logger log = LoggerFactory.getLogger(HbmTransactionProxyMgr.class);

private final Object target;
private final SessionFactory sf;

private HbmTransactionProxyMgr( final SessionFactory sf , final Object target ) {
this.sf  = sf;
this.target = target;
}

public static [T] T
newInstance(final SessionFactory sf, final Object target, final Class[T] expectedType ) {
return expectedType.cast(
  Proxy.newProxyInstance(
     target.getClass().getClassLoader() ,
     target.getClass().getInterfaces()  ,
     new HbmTransactionProxyMgr( sf , target )
   )
 );
}

@Override
public Object
invoke( final Object proxy , final Method method , final Object[] args ) throws Throwable {
if ( proxy == null || method == null ) return null;
Object ret = null;
try {

if ( !method.isAnnotationPresent( HbmProxiedTransaction.class )) {
 return method.invoke( target , args );
}

 sf.getCurrentSession().beginTransaction();
 /////////////////////////////////////
 ret = method.invoke( target , args );
 /////////////////////////////////////
 sf.getCurrentSession().getTransaction().commit();

 log.debug("-=[ tx.proxy ]=-commited()");

} catch (final InvocationTargetException ex) {
 if(sf.getCurrentSession().getTransaction().isActive()) {
    sf.getCurrentSession().getTransaction().rollback();
    log.warn("-=[ tx.proxy ]=-({})rolledback() -&gt; {}" ,
    method.getName(),((ex.getCause()!=null)?ex.getCause().getMessage():ex) );
 }
 throw ex.getTargetException();
} finally {
 if ( ret != null &amp;amp;&amp;amp; log.isDebugEnabled() )
 log.debug("-=[ tx.proxy ]=-ret: {}",ret.toString());
}
return ret;
}
}
&lt;/pre&gt;
And here's a new annotation to instruct a tx bean processor for the proxied injection:
&lt;pre class="brush: java;"&gt;
package com.martin.orm.tx.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectProxiedHbmTxMgr { }
&lt;/pre&gt;
And the spring bean post processor to inject @InjectProxiedHbmTxMgr
&lt;pre class="brush: java;"&gt;
package com.martin.orm.tx;

import java.lang.reflect.Field;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ReflectionUtils;
import com.martin.orm.tx.annotation.InjectProxiedHbmTxMgr;

public class HbmTransactionProxyProcessor implements BeanPostProcessor {

private final Logger log = LoggerFactory.getLogger(HbmTransactionProxyProcessor.class);

@Autowired
private ApplicationContext ctx;
private final SessionFactory sf;

public HbmTransactionProxyProcessor( final SessionFactory sf ) {
 this.sf = sf;
}

public Object
postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
 return bean;
}

public Object
postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {

ReflectionUtils.doWithFields( bean.getClass() , new ReflectionUtils.FieldCallback() {
public void doWith(final Field field ) {
 if (field != null &amp;amp;&amp;amp; field.isAnnotationPresent(InjectProxiedHbmTxMgr.class) ) {
   final Class type = field.getType();
   final Object dao = ctx.getBean( type );
   if ( dao != null ) {
    try {
      field.setAccessible(true);
      field.set( bean , HbmTransactionProxyMgr.newInstance( sf , dao , type ) ); //!! set
      log.debug("Injected @InjectProxiedHbmTxMgr {}.{} field" , bean.toString() , field.getName() );
    } catch (final IllegalAccessException e) {
      log.error("Injection @InjectProxiedHbmTxMgr for {}.{} field", bean.toString() , field.getName() );
      throw new FatalBeanException(e.getMessage());
    }
   } else {
      log.error("Injection type({}) not found @InjectProxiedHbmTxMgr", field.getType() );
      throw new FatalBeanException(field.getType()+" not found in appContext");
   }
 }
}
});
return bean;
}
}
&lt;/pre&gt;
And finally a snippet of a service impl:
&lt;pre class="brush: java;"&gt;
package com.martin.domain.service;
import java.util.List;
import com.martin.domain.service.dao.SampleDaoInterface;
import com.martin.domain.service.dto.Profile;
import com.martin.orm.tx.HbmTransactionProxyFactoryMgr;

public class ServiceImpl implements ServiceInterface {

// for reference processor will inject a proxied obj
@InjectProxiedHbmTxMgr
private SampleDaoInterface dao;

// for reference this dao impl would internally do usr manual/programmatic tx approach
public Profile authenticatePrincipal( final String principal , final String pwd ) {
 return dao.authenticatePrincipal(principal,pwd);
}

// for reference this method is annotated so dao impl would not have boiler-plate code
public [T] List[T] getSomeEntities( final String someCriteriaBy ) throws SomeException {
 return dao.execSomeQueryHere( someCriteriaBy );
}

}
&lt;/pre&gt;
Note that the dao will contain an assigned proxied dao in which interfaces annotated @HbmProxiedTransaction will be wrapped within transaction (commit/rollback) which eliminates tons of boiler-plate + redundant code, also note that if we instead annotate service interface then multiple daos then could participate within a session transaction context.
&lt;div&gt;&lt;/div&gt;
Summary: This dynamic proxy concept could be applied to many other needs and taken to so many different levels which as demonstrated is based on the decorator pattern in which for instance the AOP concept is based on as well: foster modularization via separation of concerns with the capability to override / intercept / advice targeted behavior, in real production project I would eventually and preferably go with a well known and standard implementation (spring @Transactional, etc) approach for many reasons outside of this scope (if JTA with global transactions, etc), yet this example is just to depict how a dynamic proxy could be applied in an application with a custom local transaction management implementation.

Cheers!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-4266084431367713384?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/4266084431367713384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=4266084431367713384' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4266084431367713384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4266084431367713384'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2010/01/hibernate-transaction-management-via.html' title='Hibernate Transaction Management via Dynamic Proxy'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-1142261809215369646</id><published>2009-12-13T11:08:00.000-08:00</published><updated>2009-12-21T11:44:16.818-08:00</updated><title type='text'>Hibernate LazyInitializationException + Flex / BLazeDS AMF Serializations</title><content type='html'>On one of my previous &lt;a href="http://martinzoldano.blogspot.com/2009/05/serialization-directive-with-filter.html"&gt;posts&lt;/a&gt; I shared how I pruned hibernate proxied entities | collections with an annotation directive to avoid lots of DTO handling as a practical approach  for prototyping,
that is one indirect way of tackling the issue of running across the culprit of &lt;a href="https://www.hibernate.org/hib_docs/v3/api/org/hibernate/LazyInitializationException.html"&gt;LazyInitializationException&lt;/a&gt; when reflecting over proxied objects outside of &lt;a href="https://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html"&gt;Session&lt;/a&gt; context. The concept of configuring Hibernate to perform eager fetching of relationships is really a &lt;b&gt;bad&lt;/b&gt; idea specially when object graphs could go too deep with massive n+1 hierarchies, moreover the 'session-in-view' perhaps may be what you not want as well. .&lt;div&gt;So in this particular instance with BlazeDS/Flex AMF binary serializations and using Spring + Hibernate for persistence I'd like to share one personal approach.&lt;/div&gt;&lt;div&gt;The verdict: you could do pruned DTO by hand or if dealing with raw hibernate objects then: (may not apply to all cases) but try to stay with &lt;b&gt;lazy&lt;/b&gt; (default) as much as possible, when there's a need to walk through an object graph do it programaticaly  or use 'fetch join' in hql queries as an alternative, if BlazeDS barks here and there with LazyInitException then below is a reference implementation approach that worked ok (when prototyping), so it'll instruct serializers via a custom bean proxy which registers Serializable type (or register more granular types as needed) to filter hibernate proxied beans | persistent collections when the marshaling happens in detach mode outside session.transactional context. You could take it a bit further to utilize &lt;a href="https://www.hibernate.org/hib_docs/v3/api/org/hibernate/Hibernate.html#initialize(java.lang.Object)"&gt;Hibernate.initialize(obj)&lt;/a&gt; within current session context as it is explained &lt;a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html"&gt;here&lt;/a&gt; (look for Initializing collections and proxies).&lt;/div&gt;&lt;div&gt;Cheers!&lt;/div&gt;&lt;div&gt;&lt;pre class="brush: java;"&gt;
package com.martin.orm.io;

import java.io.Serializable;
import flex.messaging.io.BeanProxy;
import flex.messaging.io.PropertyProxyRegistry;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.collection.AbstractPersistentCollection;

public class HbmLazyAmfFilterProxy extends BeanProxy {
private static final long serialVersionUID = 7538263979358789547L;
public HbmLazyAmfFilterProxy() {
 super();
 PropertyProxyRegistry.getRegistry().register(Serializable.class,this);
}

@Override
public Object getValue(Object o, String p) {
 Object val = super.getValue( o , p );
   if ( ( val instanceof HibernateProxy) ||
        ( val instanceof AbstractPersistentCollection ) ) {  
          val = null;
   }
   return val;
 }
}
&lt;/pre&gt;&lt;/div&gt;
Or, a more generic bean utility dto reflective populator could be something like this:&lt;div&gt;
&lt;/div&gt;
&lt;pre class="brush: java;"&gt;
//////////////////////////////////////////////////////////////////////////
public void filter( final T orig , final T dest ) throws Exception {
    final PropertyUtilsBean propertyUtilsBean  = new PropertyUtilsBean();  
    final PropertyDescriptor[] origDescriptors = 
          propertyUtilsBean.getPropertyDescriptors(orig);
        for (int i = 0; i &lt; origDescriptors.length; i++) {
            final String name = origDescriptors[i].getName();
            if ("class".equals(name)) continue;                          
            if ( propertyUtilsBean.isReadable ( orig , name ) &amp;&amp;
                 propertyUtilsBean.isWriteable( dest , name ) ) {
                 try {
                   final Object value = 
                         propertyUtilsBean.getSimpleProperty( orig , name );
                   if ( ( value instanceof HibernateProxy) || 
                        ( value instanceof AbstractPersistentCollection ) ) { 
                          continue; // filter
                   }                    
                   BeanUtils.copyProperty( dest , name , value );
                 } catch (final NoSuchMethodException e) { 
                   // deal with it
                 }
            }
       }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-1142261809215369646?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/1142261809215369646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=1142261809215369646' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/1142261809215369646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/1142261809215369646'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/12/hibernate-lazyinitializationexception.html' title='Hibernate LazyInitializationException + Flex / BLazeDS AMF Serializations'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-8406057139064004578</id><published>2009-12-07T19:51:00.000-08:00</published><updated>2009-12-28T10:07:15.481-08:00</updated><title type='text'>Thread-safe MapCache with Reaper</title><content type='html'>Sometimes when writing middle-ware applications there's a need for a simple thread safe  parameterized mem map cache with eviction reaper, generally non locking on retrieval and with internal &lt;v&gt; wrapper class. By reading the latest &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html"&gt;java.util.concurrent&lt;/a&gt;&lt;/v&gt; api doc there is a rich list of collections built with concurrency in mind, I could not find one with an eviction reaper built-in so today I assembled one and here's a reference implementation I'd like to share.

&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;package com.martin.cache;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Externalizable;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
 
/**
 * Thread safe simple parameterized map cache with eviction reaper, 
 * generally non locking on retrieval + internal &amp;lt;V&amp;gt; wrapper class.
 * @author MartinZ 12/07/2009
 * @param K key type
 * @param V value type
 */ 
public final class MapCache&amp;lt; K , V &amp;gt; {
   
  private class Reaper implements Runnable {
    public void run() {
      evict();
    }
  }

  public interface EvictionListener&amp;lt; K &amp;gt; {
    void evicted( K key );
  }
     
  /////////////////////////////////////////////////////////////////////
  public static final long DEFAULT_EVICT_INTERVAL_MS = (30 * 1000);
  public static final long DEFULT_15MINUTES_CACHE_MS = (15 * 60 * 1000); 
  ///////////////////////////////////////////////////////////////////// 
  
  private final ConcurrentHashMap&amp;lt; K , Value&amp;lt;V&amp;gt; &amp;gt; map;
  private final ScheduledThreadPoolExecutor timer;
  private final HashSet&amp;lt;EvictionListener&amp;lt;K&amp;gt;&amp;gt; listeners;
    private final long interval;
    
  public MapCache() {
      this(DEFAULT_EVICT_INTERVAL_MS);
  }
  
  public MapCache( Long tm ) {
    interval  = (tm==null)?DEFAULT_EVICT_INTERVAL_MS:tm;
    map       = new ConcurrentHashMap&amp;lt;K,Value&amp;lt;V&amp;gt;&amp;gt;();
    timer     = new ScheduledThreadPoolExecutor(1);
    listeners = new HashSet&amp;lt;EvictionListener&amp;lt;K&amp;gt;&amp;gt;();
  }
 
  public void addEvictionListener(EvictionListener&amp;lt;K&amp;gt; l) {
    listeners.add(l);
  }
  public void removeEvictionListener(EvictionListener&amp;lt;K&amp;gt; l) {
    listeners.remove(l);
  }

  public int getSize() {
    return map.size();
  }

  public void clear() {
    map.clear();
  }
  
  public void start() {
    timer.scheduleWithFixedDelay(
       new Reaper(),0,interval,TimeUnit.MILLISECONDS
    );
  }

  public void stop() {
    timer.shutdown();
  }

  /**   
   * @param key != null
   * @param val != null
   * uses default 15 minute time to live since last get   
   */  
  public V put( K key , V val ) {
    return put( key , val , DEFULT_15MINUTES_CACHE_MS );
  }  
  
  /**   
   * @param key != null
   * @param val != null
   * @param time ms to keep an entry alive. 0 = never evict.    
   */  
  public V put( K key , V val , long tm ) {
    if(key == null &amp;#124;&amp;#124; val == null ) return null;
    Value&amp;lt;V&amp;gt; value  = new Value&amp;lt;V&amp;gt;( val , tm );
    Value&amp;lt;V&amp;gt; retval = map.put( key , value );
    return (retval != null ? retval.value : null);
  }

  public V get(K key) {
    if(key == null) return null;
    Value&amp;lt;V&amp;gt; val = map.get(key);
    if(val == null) return null;    
    val.refreshTimestamp();
    return val.value;
  }

  public Value&amp;lt;V&amp;gt; getEntry( K key ) {
    if(key == null) return null;
    Value&amp;lt;V&amp;gt; val = map.get(key);
    if(val == null) return null;
    val.refreshTimestamp();
    return val;
  }

  public V remove(K key) {
    Value&amp;lt;V&amp;gt; val = map.remove(key);
    return (val != null ? val.value : null);
  }

  public Set&amp;lt;Map.Entry&amp;lt;K,Value&amp;lt;V&amp;gt;&amp;gt;&amp;gt; entrySet() {
    return map.entrySet();
  }
 
  private void evict() {
    for( Iterator&amp;lt;Map.Entry&amp;lt;K,Value&amp;lt;V&amp;gt;&amp;gt;&amp;gt; it = 
       map.entrySet().iterator(); it.hasNext();) {
       Map.Entry&amp;lt;K,Value&amp;lt;V&amp;gt;&amp;gt; entry = it.next();
       Value&amp;lt;V&amp;gt; val = entry.getValue();
       if(val != null) {
        if( (val.timeout &amp;gt; 0) &amp;amp;&amp;amp; 
            (System.currentTimeMillis() &amp;gt; 
              (val.insertion + val.timeout))) {
            it.remove(); // rm from iterator
            notifyListeners( entry.getKey() );
        }
       }
    }
  }

  private void notifyListeners( K key ) {
    for(EvictionListener&amp;lt;K&amp;gt; l: listeners) {
      try { l.evicted(key);
      } catch(Throwable t) { }
    }
  }

  public String toString() {
    StringBuilder sb=new StringBuilder();
    for(Map.Entry&amp;lt;K,Value&amp;lt;V&amp;gt;&amp;gt; entry: map.entrySet()) {
      Value&amp;lt;V&amp;gt; val=entry.getValue();
      sb.append(entry.getKey()).append(&amp;quot;: &amp;quot;);
      sb.append(entry.getValue().getValue());
      sb.append(&amp;quot; (expiration tm.ms: &amp;quot;);
      sb.append(val.getTimeout()).append(&amp;quot;)\n&amp;quot;);
    }
    return sb.toString();
  }  
  
    ///////////////////// internal wrapper ////////////////////  
  public static class Value&amp;lt; V &amp;gt; implements Externalizable {
    private V value;
    private long timeout;
    private transient long insertion=System.currentTimeMillis();
    private static final long serialVersionUID = 1100000000001L;
    
    public Value( V value , long timeout ) {
      this.value   = value;
      this.timeout = timeout;
    }

    public V getValue()            { return value;     }
    public long getTimeout()       { return timeout;   }
    public long getInsertionTime() { return insertion; }
    
    public void refreshTimestamp() {
      if( timeout &amp;gt; 0 )
      insertion=System.currentTimeMillis();
    }
    
    public void writeExternal(ObjectOutput out) 
    throws IOException {
      out.writeLong(timeout);
      out.writeObject(value);
    }

    @SuppressWarnings(&amp;quot;unchecked&amp;quot;)
    public void readExternal(ObjectInput in) 
    throws IOException,ClassNotFoundException {
      timeout   = in.readLong();
      value     = (V) in.readObject();
      insertion = System.currentTimeMillis();      
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-8406057139064004578?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/8406057139064004578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=8406057139064004578' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8406057139064004578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8406057139064004578'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/12/thread-safe-mapcache-with-reaper_07.html' title='Thread-safe MapCache with Reaper'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-2045263293178786697</id><published>2009-11-15T14:09:00.000-08:00</published><updated>2009-11-16T19:38:58.627-08:00</updated><title type='text'>Distributed computing concepts</title><content type='html'>Whether load-balancing,  fail-over, replication, distributed FS, cloud capabilities, etc, for clustering application servers nowadays, the ultimate goal is to improve quality of &lt;span class="bodycopy"&gt;highly available + scalable&lt;/span&gt; service with less latency and &lt;span class="bodycopy"&gt;fault tolerance features&lt;/span&gt;.
By looking under the hood on how J2EE servers do it, I came across JGroups library which is the toolkit JBoss uses per instance.
&lt;a href="http://www.jgroups.org/"&gt;JGroups&lt;/a&gt; is a library for reliable multicast communication, it provides a flexible protocol stack which allows developers to adapt to specific application requirements and specific network topology characteristics, its main features:
&lt;ul&gt;&lt;li&gt;Transport protocols: UDP (IP Multicast), TCP, JMS&lt;/li&gt;&lt;li&gt;Fragmentation of large messages&lt;/li&gt;&lt;li&gt;Reliable unicast and multicast message transmission. Lost messages are retransmitted&lt;/li&gt;&lt;li&gt;Failure detection: crashed members are excluded from the membership&lt;/li&gt;&lt;li&gt;Ordering protocols: Atomic (all-or-none delivery), Fifo, Causal, Total Order&lt;/li&gt;&lt;li&gt;Membership&lt;/li&gt;&lt;li&gt;Encryption&lt;/li&gt;&lt;/ul&gt;With this lower level reliable communication library, developers could then implement sophisticated middle-ware applications with distributed computing based features,  just to mention couple ones that come to my mind: memcache ( distributed map ), map-reduce / fork-join model for task execution in a private cluster/cloud, and many more capabilities, here's a partial reference source implementation that I experimented with:
&lt;pre class="brush: java;"&gt;
// create
org.jgroups.JChannelFactory factory = new JChannelFactory("udp.xml"); //tcp.xml etc
org.jgroups.JChannel channel = (JChannel) factory.createChannel();
channel.setOpt( Channel.AUTO_RECONNECT , true );
channel.setOpt( Channel.AUTO_GETSTATE  , true );
...
// start
channel.connect( "CLUSTER-NAME" );
org.jgroups.blocks.PullPushAdapter adapter = new PullPushAdapter(channel,this,this);
channel.getState(null,10000); // 10 secs conn tolerance
...
// stop
channel.disconnect();
channel.close();

// simple serialized user defined type msg send
ClusterMsg m = new ClusterMsg( action );
byte[] buffer = org.jgroups.util.Util.objectToByteBuffer( m );
Message msg = new Message( dest , src , buffer , 0 , buffer.length );
channel.send( msg );

// from Interface org.jgroups.MessageListener
public byte[] getState() { ... }
public void receive( Message msg ) {
Serializable s = (Serializable)
    org.jgroups.util.Util.objectFromByteBuffer(msg.getBuffer());
    if( s instanceof ClusterMsg ) {
       ClusterMsg cmsg = (ClusterMsg) s;
       switch( cmsg.getAction() ) {
        // do something
       }
    }
}
public void setState( byte[] newState ) { ... }

// from Interface org.jgroups.MembershipListener
public void viewAccepted( org.jgroups.View currentView ) { ... }

&lt;/pre&gt;
&lt;a href="http://en.wikipedia.org/wiki/Parallel_computing"&gt;parallelism&lt;/a&gt; pseudo-code concept [divide-conquer | map-reduce | fork-join]

Result solve(Problem problem) {
if (problem is small enough)
  result = problem.solve()
else {
  split problem into independent parts
  fork new subtasks to solve each part
  join all subtasks
 compose result from sub-results
}
}

In general, split tasks could then be allocated | distributed to available nodes for execution, the middle-ware could be able to perform a network node pre-inspection to determine its hardware capabilities of each node corresponds for computing or data storage based on their processor, memory, HD power, etc. Thus depending on what a certain task does, allocation should be in function of what a certain node can provide at its best.

Here's a static img for illustration of my simple PoC experiment, I'll spawn 3 instances (same host) with one being the master node, and two slave ones, there's a simple map being serialized and acting as a simple memcache implementation as well as a simple distributed task execution capability, I created a simple web UI which shows all nodes in cluster along with the protocol stack configured, and one can run tasks, send sessages to all nodes and shut-down a targeted node or all cluster in view:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/SwCTTpI91iI/AAAAAAAAAbM/AswLYd113sI/s1600/cluster.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_M94eDahX5rM/SwCTTpI91iI/AAAAAAAAAbM/AswLYd113sI/s320/cluster.png" alt="" id="BLOGGER_PHOTO_ID_5404481518514853410" border="0" /&gt;&lt;/a&gt;Hard to see it all working from img, but the main concept is there and functional, now the cool thing is that if either node goes down (including master one) the whole cluster is aware of it and the state is being serialized and distributed upon node bootstrap via the  org.jgroups.MessageListener.
No need to reinvent the wheel here, as we know most containers have clustering built-in and there are already middle-ware open source projects: &lt;a href="http://www.gridgain.com/"&gt;GridGain&lt;/a&gt; , &lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt; and other products in the arena such as: &lt;a href="http://www.oracle.com/technology/products/coherence/index.html"&gt;Coherence&lt;/a&gt; , &lt;a href="http://www.terracotta.org/"&gt;Terracota&lt;/a&gt; , etc.

Finally, with the new explosion of cloud services such as bottom up: &lt;a href="http://aws.amazon.com/ec2"&gt;IaaS&lt;/a&gt;, &lt;a href="http://code.google.com/appengine"&gt;PaaS&lt;/a&gt;, &lt;a href="http://www.salesforce.com/"&gt;SaaS&lt;/a&gt; with flexible 'pay as you need' on demand features, we can see that there's a new trend to provide cloud services in which under the covers it is dynamic provisioning of distributed computing platform at its core.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-2045263293178786697?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/2045263293178786697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=2045263293178786697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/2045263293178786697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/2045263293178786697'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/11/distributed-computing-concepts.html' title='Distributed computing concepts'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M94eDahX5rM/SwCTTpI91iI/AAAAAAAAAbM/AswLYd113sI/s72-c/cluster.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-8846426213241171398</id><published>2009-09-18T11:53:00.001-07:00</published><updated>2009-11-11T07:39:09.594-08:00</updated><title type='text'>Windows installer for a java swing app</title><content type='html'>Early this year I contracted a very small project where the desktop java swing app needed to be installed and run on MS-OS(s), since I used a cross-platform java executable wrapper: launch4j to generate an .exe I could then automate an installer with features like: un-installer, detect core dependencies such as JRE and install it not present as well as Adobe reader,  registry settings, readme file, logo splash, etc, etc, and more.

Simple cmd compiler invokation as:
makensis.exe /V4 InstallScriptSample.nsi

Resolution:
NSIS did the job, scriptable installer with rich set of options. Below is an example configuration I used, take it as a guideline and modify accordingly for your needs.
Cheers!&lt;pre class="brush: plain;"&gt;
;----------------------------------------------------
; File: InstallScriptSample.nsi
; Installer using -&gt; http://nsis.sourceforge.net
;----------------------------------------------------
; Note replace "MyApp" with desired app name
;----------------------------------------------------

SetCompressor /SOLID lzma

!include "MUI.nsh"
!insertmacro MUI_PAGE_WELCOME
#!insertmacro MUI_PAGE_DIRECTORY
#!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_CHECKED
!define MUI_FINISHPAGE_RUN_TEXT "Start MyApp"
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
!define MUI_FINISHPAGE_SHOWREADME_CHECKED
!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\README.txt
!insertmacro MUI_PAGE_FINISH

;----------------------------------
!insertmacro MUI_LANGUAGE "English"
;----------------------------------

#Page directory
#Page components
#Page instfiles

;--------------------------------
; Main Install settings
;--------------------------------

Name "MyApp"
Caption "MyApp Installer | Please wait!"
Icon "icon.ico"
#InstallDir "$PROGRAMFILES\MyApp"
InstallDir "c:\MyApp"
OutFile "Setup.exe"
ShowInstDetails show
ShowUninstDetails show
AutoCloseWindow true
RequestExecutionLevel admin
BrandingText "MyApp v1.0"
AllowRootDirInstall false
InstallColors 00FF00 000000
InstallDirRegKey HKCU "Software\MyApp" ""
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "UninstallString"

#---------------- installer section start ----------------
section

Call Includes
Call CheckJRE
Call InstallJre
Call InstallAdobe

Success:
Call CreateShortCutsAndUninstaller
Goto Done

Done:

# messageBox MB_OK "Installation was successful @ $INSTDIR $\r$\n \
# Please use desktop shortcut [MyApp] to start-up application."

sectionEnd

#---------------- installer section end --------------------


#---------------- uninstaller section start ----------------

section "uninstall"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayName" ""
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "UninstallString" ""
DeleteRegKey /ifempty HKCU "Software\MyApp"
delete "$DESKTOP\MyApp.lnk"
delete "$STARTMENU\MyApp.lnk"
delete "$SMPROGRAMS\MyApp.lnk"
rmdir /r $INSTDIR

sectionEnd

#---------------- uninstaller section end ------------------

Function LaunchLink
ExecShell "" "$INSTDIR\MyApp.exe"
FunctionEnd


;--------------------------------
Function Includes

WriteRegStr HKCU "Software\MyApp" "" $INSTDIR

SetOverwrite on

SetOutPath $INSTDIR

File run.cmd
File MyApp.exe
File README.txt
File QA.txt

SetOutPath $INSTDIR\config
File .\config\config.xml
File .\config\hbm.cfg.xml
File .\config\log4j.xml

SetOutPath $INSTDIR\db
File .\db\HSQLDB.app.log
File .\db\HSQLDB.backup
File .\db\HSQLDB.data
File .\db\HSQLDB.properties
File .\db\HSQLDB.script

SetOutPath $INSTDIR\img
File /r ".\img\*.*"

SetOutPath $INSTDIR\lib
File /r ".\lib\*.*"

SetOutPath $INSTDIR\rpt
File /r ".\rpt\*.*"

SetOutPath $INSTDIR\inc
File .\inc\jre-6u11-windows-i586-p.exe
File .\inc\AdbeRdr90_en_US.exe

SetOverwrite off

FunctionEnd

;--------------------------------

Function InstallJre

ExecWait '$INSTDIR\inc\jre-6u11-windows-i586-p.exe /quiet' $0

FunctionEnd

;--------------------------------

Function InstallAdobe

ExecWait '$INSTDIR\inc\AdbeRdr90_en_US.exe /sAll /rs' $0

FunctionEnd

;--------------------------------

Function CreateShortCutsAndUninstaller

#    push $0
#	FileOpen $0 $INSTDIR\MyApp.cmd w
#	FileWrite $0 "cd $INSTDIR\bin$\r$\n"
#	FileWrite $0 "run.cmd$\r$\n"	
#	FileClose $0
#    pop $0

CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\MyApp.exe" \

"" "$INSTDIR\img\icon.ico" 0 SW_SHOWNORMAL CONTROL|SHIFT|F5 "MyApp"



CreateShortCut "$SMPROGRAMS\MyApp.lnk" "$INSTDIR\MyApp.exe" \

"" "$INSTDIR\img\icon.ico" 0 SW_SHOWNORMAL CONTROL|SHIFT|F5 "MyApp"



CreateShortCut "$STARTMENU\MyApp.lnk" "$INSTDIR\MyApp.exe" \

"" "$INSTDIR\img\icon.ico" 0 SW_SHOWNORMAL CONTROL|SHIFT|F5 "MyApp"



WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayName" "MyApp (Uninstall)"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "UninstallString" "$INSTDIR\Uninstall.exe"



writeUninstaller "$INSTDIR\Uninstall.exe"



FunctionEnd



;--------------------------------

Function CheckJRE

push $0

push $1


ClearErrors

ReadRegStr $0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"

ReadRegStr $1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$0" "JavaHome"

StrCpy $1 "$1\bin\java.exe"

pop $0

exch $1

FunctionEnd

;--------------------------------
; eof
;--------------------------------
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-8846426213241171398?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/8846426213241171398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=8846426213241171398' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8846426213241171398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8846426213241171398'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/09/windows-installer-for-java-swing-app.html' title='Windows installer for a java swing app'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-8726976408870222605</id><published>2009-09-18T11:50:00.000-07:00</published><updated>2009-11-11T07:39:02.301-08:00</updated><title type='text'>Cross-platform java executable wrapper</title><content type='html'>Early this year I needed to wrap a small project java swing app into a native MS-OS executable,  after deliberating on few products out there I chose &lt;a href="http://launch4j.sourceforge.net/"&gt;launch4j&lt;/a&gt;
Resolution:
It did the job, it has easy to use streamlined UI which generates an xml configuration file which then you can reuse to rebuild exe. Below is an example configuration I used, take it as a guideline and modify accordingly for your needs.
Cheers!

&lt;pre class="brush: xml;"&gt;
&lt;!-- http://launch4j.sourceforge.net Cross-platform Java executable wrapper:  Note replace "MyApp" with desired app name --&gt;

&lt;launch4jconfig&gt;
&lt;dontwrapjar&gt;true&lt;/dontwrapjar&gt;
&lt;headertype&gt;gui&lt;/headertype&gt;
&lt;jar&gt;lib\org.myapp_1_0_0.jar&lt;/jar&gt;
&lt;outfile&gt;C:\tmp\MyApp.exe&lt;/outfile&gt;
&lt;errtitle&gt;Java Runtime Error&lt;/errtitle&gt;
&lt;cmdline&gt;config/log4j.xml config/config.xml&lt;/cmdline&gt;
&lt;chdir&gt;.&lt;/chdir&gt;
&lt;priority&gt;normal&lt;/priority&gt;
&lt;downloadurl&gt;http://java.com/download&lt;/downloadurl&gt;
&lt;supporturl&gt;http://java.sun.com&lt;/supporturl&gt;
&lt;customprocname&gt;false&lt;/customprocname&gt;
&lt;stayalive&gt;false&lt;/stayalive&gt;
&lt;manifest&gt;&lt;/manifest&gt;
&lt;icon&gt;icon.ico&lt;/icon&gt;
&lt;singleinstance&gt;
&lt;mutexname&gt;MyApp&lt;/mutexname&gt;
&lt;windowtitle&gt;MyApp&lt;/windowtitle&gt;
&lt;/singleinstance&gt;
&lt;classpath&gt;
&lt;mainclass&gt;org.myns.myproj.MyAppMain&lt;/mainclass&gt;
&lt;cp&gt;lib/org.myapp_1_0_0.jar&lt;/cp&gt;
&lt;cp&gt;lib/commons-collections-3.1.jar&lt;/cp&gt;
&lt;cp&gt;lib/commons-io-1.4.jar&lt;/cp&gt;
&lt;cp&gt;lib/commons-lang.jar&lt;/cp&gt;
&lt;cp&gt;lib/commons-logging-1.1.jar&lt;/cp&gt;
&lt;!-- add more or remove accordingly from list as needed / required !!! --&gt;
&lt;/classpath&gt;
&lt;jre&gt;
&lt;path&gt;C:\Program Files\Java\jre6&lt;/path&gt;
&lt;minversion&gt;1.6.0_11&lt;/minversion&gt;
&lt;maxversion&gt;&lt;/maxversion&gt;
&lt;jdkpreference&gt;preferJre&lt;/jdkpreference&gt;
&lt;initialheapsize&gt;128&lt;/initialheapsize&gt;
&lt;maxheapsize&gt;256&lt;/maxheapsize&gt;
&lt;/jre&gt;
&lt;splash&gt;
&lt;file&gt;img\logo.bmp&lt;/file&gt;
&lt;waitforwindow&gt;true&lt;/waitforwindow&gt;
&lt;timeout&gt;60&lt;/timeout&gt;
&lt;timeouterr&gt;true&lt;/timeouterr&gt;
&lt;/splash&gt;
&lt;messages&gt;
&lt;startuperr&gt;An error occurred while starting the application.&lt;/startuperr&gt;
&lt;bundledjreerr&gt;This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted.&lt;/bundledjreerr&gt;
&lt;jreversionerr&gt;This application requires a Java Runtime Environment&lt;/jreversionerr&gt;
&lt;launchererr&gt;The registry refers to a nonexistent Java Runtime Environment installation or the runtime is corrupted.&lt;/launchererr&gt;
&lt;instancealreadyexistsmsg&gt;An application instance is already running.&lt;/instancealreadyexistsmsg&gt;
&lt;/messages&gt;
&lt;/launch4jconfig&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-8726976408870222605?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/8726976408870222605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=8726976408870222605' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8726976408870222605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8726976408870222605'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/09/cross-platform-java-executable-wrapper.html' title='Cross-platform java executable wrapper'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-7959925073778032998</id><published>2009-08-31T21:23:00.001-07:00</published><updated>2010-12-27T08:32:40.075-08:00</updated><title type='text'>JVM Agent - Class Spy Utility</title><content type='html'>I've been experimenting recently on a PoC java agent utility which dumps high &amp;amp; &lt;a href="http://www.aqute.biz/Code/Clsd"&gt;&lt;/a&gt;low level details for any class loaded by JVM at any point of time.
It does not perform any bytecode instrumentation manipulation / alteration but rather loads all classes available / loaded by the JVM in context into a UI in which it organizes classes by package namespace into a hierarchical tree structure.
This utility comes handy when you need to introspect class bytecode blueprint signatures that may be in question at runtime, similar to the &lt;span style="font-weight: bold;"&gt;javap&lt;/span&gt; utility that ships with jdk.

According to the specs the agent jar must contain:
&lt;pre class="brush: plain;"&gt;
MANIFEST.MF
...
Agent-Class: org.martin.agent.jvm.JvmAgent
Premain-Class: org.martin.agent.jvm.JvmAgent
Boot-Class-Path: jvmagent_1_0_0.jar
Can-Redefine-Classes: false
Can-Retransform-Classes: false
&lt;/pre&gt;&lt;span style="color: rgb(255, 0, 0);font-size:78%;" &gt;(note that redefinitions + transformations are not set since neither is needed here)&lt;/span&gt;

and method premain &lt;span style="font-size:85%;"&gt;(similar to a 'main')&lt;/span&gt; signature hook is as follows:
&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="color: rgb(51, 102, 255);"&gt;org.martin.agent.jvm.JvmAgent&lt;/span&gt;&lt;/span&gt;
&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;public static void &lt;span style="color: rgb(0, 153, 0);"&gt;premain&lt;/span&gt;(String agentArgs, Instrumentation inst) { ... }&lt;/span&gt;&lt;/span&gt;

once we have &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html"&gt;instrumentation&lt;/a&gt; access we can then:
[1] register a custom class transformer
&lt;pre class="brush: java;"&gt;
instrumentation.addTransformer( new MyClassLoadTransformer() );
...
class MyClassLoadTransformer implements ClassFileTransformer {
public byte[] transform(
ClassLoader loader,
String fullyQualifiedClassName,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classofileBuffer) throws IllegalClassFormatException {
// illustration here!
}
}
&lt;/pre&gt;
[2] and invoke the instrumentation method:
&lt;span style="color: rgb(51, 102, 255);"&gt;final Class[] clsArr = instrumentation.getAllLoadedClasses()&lt;/span&gt;;
which feeds the UI by representing pkgs hierarchicaly in a tree:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/Spylz7gXCzI/AAAAAAAAAZ4/VzIB9XyP_Zs/s1600-h/agentUI"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/Spylz7gXCzI/AAAAAAAAAZ4/VzIB9XyP_Zs/s320/agentUI" alt="" id="BLOGGER_PHOTO_ID_5376354366738860850" border="0" /&gt;&lt;/a&gt;Once a desired class node is selected, it prompts for high / low level detail?, either selection will dump its details on to System.out, below is a console sample of output:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/Sp1JXcjdOiI/AAAAAAAAAaI/9nBA4ib2YMM/s1600-h/agentConsole"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 303px; height: 320px;" src="http://2.bp.blogspot.com/_M94eDahX5rM/Sp1JXcjdOiI/AAAAAAAAAaI/9nBA4ib2YMM/s320/agentConsole" alt="" id="BLOGGER_PHOTO_ID_5376534197300967970" border="0" /&gt;&lt;/a&gt;Instructions:
[1] &lt;a href="http://martinzoldano.googlepages.com/jvmagent_1_0_0.jar"&gt;download jar&lt;/a&gt; (only 22+k) and place it either in /lib or /bin of your app
[2] Then you just need to add &lt;span style="color: rgb(51, 102, 255);"&gt;-javaagent&lt;/span&gt; parameter such as:
&lt;span style="color: rgb(51, 102, 255);"&gt;java -javaagent:jvmagent_1_0_0.jar  &lt;span style="font-size:85%;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;...(more options here)&lt;/span&gt;
&lt;span style="font-size:78%;"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;(depending on where it is : relative path&lt;span style="color: rgb(255, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);font-size:78%;" &gt;-javaagent:../lib/jvmagent_1_0_0.jar&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; , so configure accordingly!)&lt;/span&gt;&lt;/span&gt;

Agent will launch and load a UI with an initial draw, if your bootstrap process takes a bit longer then at any point you can press refresh button to re-load jvm state, the jvm + your application will be dynamically loading on demand classes based on the dependencies needed, so refresh accordingly.

&lt;span style="font-size:100%;"&gt;Bytecode class dump disassembler &lt;a href="http://www.aqute.biz/Code/Clsd"&gt;credits&lt;/a&gt;.&lt;/span&gt;

Conclusion
Now imagine taking this concept further, profilers per say, or by using bytecode manipulation libraries such as &lt;a href="http://asm.ow2.org/"&gt;asm&lt;/a&gt; or &lt;a href="http://jboss.org/javassist"&gt;javassist&lt;/a&gt; an example is &lt;a href="http://www.zeroturnaround.com/javarebel/comparison"&gt;javarebel&lt;/a&gt; which allows reloading classes dynamically at runtime (even if making significant changes) without needing to restart container. I do have a working version agent where does hotswap (as long as new bytecode &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/Instrumentation.html#redefineClasses%28java.lang.instrument.ClassDefinition%5B%5D%29"&gt;respects same signature&lt;/a&gt; and only changes within method implementation), however JVM can become very stale if you violate that limitation (at least up until now in jdk 6+).

Update 12-27-2010: There's a new VM that allows unlimited class redefinition at runtime &lt;a href="http://ssw.jku.at/dcevm/"&gt;http://ssw.jku.at/dcevm&lt;/a&gt;

Till next time, cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-7959925073778032998?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/7959925073778032998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=7959925073778032998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/7959925073778032998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/7959925073778032998'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/08/jvm-agent-class-spy-utility.html' title='JVM Agent - Class Spy Utility'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M94eDahX5rM/Spylz7gXCzI/AAAAAAAAAZ4/VzIB9XyP_Zs/s72-c/agentUI' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-3668447785305034498</id><published>2009-06-23T16:34:00.001-07:00</published><updated>2009-06-23T20:16:34.386-07:00</updated><title type='text'>Java shell</title><content type='html'>&lt;div&gt;I've been having fun writting a utility java shell, I use cygwin on windows but I needed something more integrated with java such has building class paths, invoking java/ant/groovy /os scripts, scanning in context class loader certain classes | @Annotations,  etc, etc. And also when I switch to Linux there it is for me as well. Some basic commands are os file system handling such as ls / rm / mk / grep / etc.&lt;/div&gt;&lt;div&gt;Internals use java.io.Console and a custom annotation:&lt;/div&gt;&lt;div&gt;&lt;pre class="brush: java;"&gt;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Command {
String name()        default "";
String description() default "";
String abbrev()      default "";
String def()         default "";
}
&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;So anytime I need a new command I can annotate it like below and instantly it becomes available via method reflection invocation:
&lt;pre class="brush: java;"&gt;
@Command(name="cmd", description="sample cmd", abbrev=".", def="?")
public void cmd( String str ) throws Exception {
...
}
&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Here's an example below for few common file system cmds: ls , lsr (just like ls but with recursive capabilities building a tree)&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_M94eDahX5rM/SjOd9zX7K8I/AAAAAAAAAYQ/aQnusR2AsYA/s1600-h/shellExample.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 303px;" src="http://4.bp.blogspot.com/_M94eDahX5rM/SjOd9zX7K8I/AAAAAAAAAYQ/aQnusR2AsYA/s320/shellExample.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5346790867707046850" /&gt;&lt;/a&gt;Note that commands can be chained 'piped' taking res output as input like in *nix such as:&lt;div&gt;lsr src | grep '06-11'&lt;/div&gt;&lt;div&gt;And also io redirect '&gt;' result:&lt;/div&gt;&lt;div&gt;ls . | lsr src | grep '06-11' &gt; result.log&lt;/div&gt;&lt;div&gt;Or io redirect appended '&gt;&gt;'&lt;/div&gt;&lt;div&gt;ls . | lsr src | grep '06-11' &gt;&gt; result.log
etc
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/SjOejYkO6nI/AAAAAAAAAYo/QFQ1tNhr_Yw/s1600-h/result.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 42px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/SjOejYkO6nI/AAAAAAAAAYo/QFQ1tNhr_Yw/s320/result.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5346791513345944178" /&gt;&lt;/a&gt;I'll have to admit that grep command which takes regular expressions to search is my favorite command of them all (specially in windows cuz u know y), it's so powerfull when combined with others.&lt;/div&gt;&lt;div&gt;Here's a list of the help for all cmds implemented so far (keeps growing by the day)

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/SjOeHDhMPFI/AAAAAAAAAYg/eJ2XulEJ1hg/s1600-h/shellHelp.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 165px;" src="http://2.bp.blogspot.com/_M94eDahX5rM/SjOeHDhMPFI/AAAAAAAAAYg/eJ2XulEJ1hg/s320/shellHelp.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5346791026659703890" /&gt;&lt;/a&gt;Today I included a disassembler via 'javap' which scans in context class loader via a package prefix and shows public class signatures, it comes handy when you need to introspect bytecode loaded and being currently invoked. It also can open a script file and sequentially execute cmds but for that there's a groovy cmd which I can invoke and run groovy scripts with dyn-language richness, one example is I run [def ant = new AntBuilder()] via groovy ;-).&lt;/div&gt;&lt;div&gt;
Now one thing I hate to do is walking by hand on file system typing long paths, so I added a simple 'fs' cmd which launches a swing UI which facilitates file system operations, I hooked most common cmds in a menu and results are directed to console:&lt;/div&gt;&lt;div&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/SkFvPScIfTI/AAAAAAAAAZI/9KYidbsGgD4/s1600-h/ui.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 319px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/SkFvPScIfTI/AAAAAAAAAZI/9KYidbsGgD4/s320/ui.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5350680140731415858" /&gt;&lt;/a&gt;I know it looks like a toy but it surely comes handy on day by day con$ole operations, heck I don't know what I'll add next but it sure saves the day, I love being productive with tools that do things my way ;-) and I can easily throw a new feature at it in a matter of minutes.

One final trick (for windows) is that you can invoke it directly from windows file explorer anytime you right-click on a folder (shows on menu):
file: reg.reg
&lt;pre class="brush: plain;"&gt;
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\jell]
@="jell"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\jell\command]
@="cmd.exe /k \"cd %L\"&amp;amp;jell"
&lt;/pre&gt;
I'll probably pack it once it becomes stable so I can share as GA, that is if anybody finds this useful,
Well, till next time, cheers...


&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-3668447785305034498?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/3668447785305034498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=3668447785305034498' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3668447785305034498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3668447785305034498'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/06/java-shell.html' title='Java shell'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_M94eDahX5rM/SjOd9zX7K8I/AAAAAAAAAYQ/aQnusR2AsYA/s72-c/shellExample.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-8075995122205965470</id><published>2009-06-12T20:42:00.001-07:00</published><updated>2009-06-13T05:07:25.241-07:00</updated><title type='text'>Ant + Ivy &gt; Repository +</title><content type='html'>I'd like to share my Ivy configuration that I use to build my Java repository and to manage transitive dependencies / conflicts, first I'd like to point out that I prefer controlling internals, the 'convention over configuration ease' which by the way is a great concept but seems to fall short sooner or later when it comes to opening the hood and morphing things, I like simplicity and once a tool works for you the way you want then leave it as is. I've read many posts regarding Ant &lt;&gt; Maven which at the end of the day the reality is that there's no such a thing as a 'silver bullet' when building complex + modularized projects.
I think that: "it's not just what a tool can do for you magically, but you can do 'with' the tool in a harmonious/flexible/extensible way" ;-)
I guess that's what I love most about Spring framework, BTW both mentioned products are great, evaluate what you're getting into [pros/cons] and choose wisely. My choice = ubiquitous Ant + Ivy cuts it for me.

&lt;pre class="brush: xml;"&gt;
&lt;ivy-module version="2.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:extra="http://ant.apache.org/ivy/extra"
   xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
&gt;
  &lt;info organisation="org.martin.repository" module="main-repository"&gt;
   &lt;description homepage="http://martinzoldano.blogspot.com"&gt;
    This is the main dependency repository list.
   &lt;/description&gt;
 &lt;/info&gt;
 &lt;!--
 &lt;configurations&gt;               
 &lt;/configurations&gt;
 &lt;publications&gt;  
 &lt;/publications&gt;
 --&gt;
    &lt;dependencies&gt;
        &lt;dependency org="org.apache.ant"              name="ant"                    rev="1.7.0"&gt;&lt;/dependency&gt;
        &lt;dependency org="xerces"                      name="xercesImpl"             rev="2.6.2"&gt;&lt;/dependency&gt;
        &lt;dependency org="xerces"                      name="xmlParserAPIs"          rev="2.6.2"&gt;&lt;/dependency&gt;
        &lt;dependency org="com.thoughtworks.xstream"    name="xstream"                rev="1.3.1"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-lang"                name="commons-lang"           rev="2.3"revConstraint="[1.0,3.0[" &gt;&lt;/dependency&gt;
        &lt;dependency org="commons-collections"         name="commons-collections"    rev="3.2.1"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-beanutils"           name="commons-beanutils"      rev="1.8.0"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-httpclient"          name="commons-httpclient"     rev="3.1"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-codec"               name="commons-codec"          rev="1.3"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-io"                  name="commons-io"             rev="1.4"&gt;&lt;/dependency&gt;
        &lt;dependency org="commons-cli"                 name="commons-cli"            rev="1.2"&gt;&lt;/dependency&gt;
        &lt;dependency org="hsqldb"                      name="hsqldb"                 rev="1.8.0.10"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.mortbay.jetty"           name="jetty"                  rev="6.1.18"&gt;&lt;/dependency&gt;
        &lt;dependency org="quartz"                      name="quartz"                 rev="1.5.2"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.apache.xmlbeans"         name="xmlbeans"               rev="2.4.0"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.apache.velocity"         name="velocity"               rev="1.6.2"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.springframework"         name="spring"                 rev="2.5.6"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.springframework.security" name="spring-security-core"  rev="2.0.4"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.springframework.ws"      name="spring-ws"              rev="1.5.7"&gt;&lt;/dependency&gt;
        &lt;dependency org="org.hibernate"               name="hibernate"              rev="3.2.5.ga"&gt;&lt;/dependency&gt;
        &lt;dependency org="junit"                       name="junit"                  rev="3.8.2"&gt;&lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/ivy-module&gt;
&lt;/pre&gt;

Ant (partial) snippet:

&lt;pre class="brush: xml;"&gt;
&lt;!-- partial build.xml --&gt;
&lt;target name="resolve" depends="prep" description="fetch transitive dependencies with ivy"&gt;
     &lt;record name="verbose.log" action="start" loglevel="verbose"&gt;&lt;/record&gt;
         &lt;ivy:retrieve file="ivy.xml" transitive="true" haltonfailure="false"&gt;&lt;/ivy:retrieve&gt;
         &lt;ivy:report todir="report"&gt;&lt;/ivy:report&gt;
         &lt;delete failonerror="false"&gt;      
           &lt;fileset dir="${dir.repository.lib}"&gt;
                &lt;patternset refid="docsrc.files"/&gt;
           &lt;/fileset&gt;
         &lt;/delete&gt;
     &lt;record name="verbose.log" action="stop"&gt;&lt;/record&gt;
&lt;/target&gt; 
&lt;!-- partial build.xml --&gt;
&lt;/pre&gt;

Cheers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-8075995122205965470?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/8075995122205965470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=8075995122205965470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8075995122205965470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/8075995122205965470'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/06/ant-ivy-repository.html' title='Ant + Ivy &gt; Repository +'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-6742714373312959641</id><published>2009-05-10T08:47:00.000-07:00</published><updated>2009-11-13T18:08:17.575-08:00</updated><title type='text'>AppEngine &amp; BlazeDS (Messaging)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_M94eDahX5rM/Sgb5ngtIDZI/AAAAAAAAAYI/gY96VYsgtKE/s1600-h/BlazeMsg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 165px;" src="http://3.bp.blogspot.com/_M94eDahX5rM/Sgb5ngtIDZI/AAAAAAAAAYI/gY96VYsgtKE/s320/BlazeMsg.png" alt="" id="BLOGGER_PHOTO_ID_5334225265856351634" border="0" /&gt;&lt;/a&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="color: rgb(128, 128, 128);font-family:'Trebuchet MS';" &gt;&lt;a href="http://riaspringblaze.appspot.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;b&gt;http://riaspringblaze.appspot.com&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;
&lt;a style="font-weight: bold;" href="https://riaspringblaze.appspot.com"&gt;https://riaspringblaze.appspot.com&lt;/a&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;
Hello!&lt;/div&gt;&lt;div&gt;I added a simple messaging test drive to existing flex PoC app, this time I updated Spring version from 2.5.5 to 3.0.0M2 and from flexM1 to flex-1.0.0.RC1 with my already existing 'slight-hacked' core.jar from my previous &lt;a href="http://martinzoldano.blogspot.com/2009/04/appengine-adobe-blazeds-fix.html"&gt;blog&lt;/a&gt; , it went pretty well and here are the results:&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Note that Spring changed @ web-application-config.xml to new 'remoting-destination'  -&gt;&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: xml;"&gt;
   &lt;flex:message-broker&gt;
   &lt;bean id="flexService" class="com.martin.blaze.ServiceImpl"&gt;
      &lt;!-- Note old spring way from M2 ver &lt;flex:remote-service&gt; --&gt;
      &lt;flex:remoting-destination&gt; 
   &lt;/flex:remoting-destination&gt;
   &lt;flex:message-destination id="DESTINATION-TEST" subtopics="true"&gt;
&lt;/flex:message-destination&gt;&lt;/bean&gt;&lt;/flex:message-broker&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Here's a snippet flex client set up -&gt;&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: plain;"&gt;
&lt;mx:channelset id="channelMsgSet"&gt;
 &lt;mx:amfchannel url="{HOST?:PORT?}/messagebroker/amfpolling"&gt;
&lt;/mx:amfchannel&gt;

&lt;mx:consumer id="consumer" destination="DESTINATION-TEST" subtopic="TOPIC-TEST" channelset="{channelMsgSet}" message="messageHandler(event)" fault="faultMsgHandler(event)" acknowledge="acknowledgeMsgHandler(event)"&gt;
&lt;/mx:consumer&gt;&lt;/mx:channelset&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;And finally this is my new list of libraries/dependencies deployed to the cloud for your reference-&gt;&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: plain;"&gt;
martin@martin-ubuntu9 ~/projs/blazeappengine/war/WEB-INF/lib
$ ls -1
antlr-3.0.1.jar
aopalliance.jar
appengine-api-1.0-sdk-1.2.0.jar
asm-3.1.jar
aspectjrt.jar
backport-util-concurrent.jar
cfgatewayadapter.jar
cglib-2.2.jar
commons-beanutils.jar
commons-collections-3.1.jar
commons-fileupload-1.2.1.jar
commons-lang.jar
commons-logging-1.1.jar
concurrent.jar
datanucleus-appengine-1.0.0.final.jar
datanucleus-core-1.1.0.jar
datanucleus-jpa-1.1.0.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
geronimo-jpa_3.0_spec-1.1.1.jar
geronimo-jta_1.1_spec-1.1.1.jar
jackson-core-asl-0.9.9-6.jar
jdo2-api-2.3-SNAPSHOT.jar
org.springframework.aop-3.0.0.M2.jar
org.springframework.aspects-3.0.0.M2.jar
org.springframework.beans-3.0.0.M2.jar
org.springframework.context-3.0.0.M2.jar
org.springframework.context.support-3.0.0.M2.jar
org.springframework.core-3.0.0.M2.jar
org.springframework.expression-3.0.0.M2.jar
org.springframework.flex-1.0.0.RC1.jar
org.springframework.transaction-3.0.0.M2.jar
org.springframework.web-3.0.0.M2.jar
org.springframework.web.servlet-3.0.0.M2.jar
xalan.jar
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;Give it a try, subscribe to pre-determined dest+topic and emulate a msg push from server, you'll see there an asynch msg received by the client consumer, better yet
launch 2 or 3 browsers, subscribe from all and send msgs from only one browser isntance, you'll see all consumers being published since they all subscribe to same
predetermined topic.... ;-)&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Cheers.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-6742714373312959641?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/6742714373312959641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=6742714373312959641' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/6742714373312959641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/6742714373312959641'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/05/appengine-blazeds-messaging.html' title='AppEngine &amp; BlazeDS (Messaging)'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M94eDahX5rM/Sgb5ngtIDZI/AAAAAAAAAYI/gY96VYsgtKE/s72-c/BlazeMsg.png' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-914151831225062178</id><published>2009-05-08T08:40:00.000-07:00</published><updated>2009-05-08T11:37:19.329-07:00</updated><title type='text'>Bean @Filter Annotation</title><content type='html'>Hello!&lt;div&gt;When performing introspections through your own reflective or 3rd party library and specially if your objects are 'proxied' within a certain context, sometimes there's a need to instruct reflective libraries to 'filter' certain class memebers somewhat similar to intrinsic 'transient' keyword (serializations), in this case I thought of a non-intrusive way to annotate with metadata a runtime directive which respects encapsulation paradigm since it would be used throught the pojo public members().&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Here's a simple runtime directive marker interface so we can illustrate concept:&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: java;"&gt;
// org.martin.metatag.Filter
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Filter { }
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;And here we have an implementation class that uses org.apache.commons.beanutils.BeanUtils impl:&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: java;"&gt;
import java.io.Serializable;
import java.beans.PropertyDescriptor;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class BeanUtil&lt; T extends Serializable &gt; {

 public String toString( T entity ) throws Exception {
   return ToStringBuilder.reflectionToString( entity , ToStringStyle.MULTI_LINE_STYLE );
    }
 
 public void populate( T orig , T dest ) throws Exception {
   BeanUtils.copyProperties( dest , orig );
 }

    // @org.martin.metatag.Filter impl
 public void filter( T orig , T dest ) throws Exception {
   PropertyUtilsBean propertyUtilsBean  = new PropertyUtilsBean();  
          PropertyDescriptor[] origDescriptors = propertyUtilsBean.getPropertyDescriptors(orig);
          for (int i = 0; i &lt; origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if ("class".equals(name)) continue;
            if ( origDescriptors[i].getReadMethod().isAnnotationPresent(  org.martin.metatag.Filter.class ) ) continue;
            if ( origDescriptors[i].getWriteMethod().isAnnotationPresent( org.martin.metatag.Filter.class ) ) continue;
            if ( propertyUtilsBean.isReadable ( orig , name ) &amp;&amp;
              propertyUtilsBean.isWriteable( dest , name ) ) {
                 try {
                    Object value = propertyUtilsBean.getSimpleProperty( orig , name );
                    BeanUtils.copyProperty( dest , name , value );
                 } catch (NoSuchMethodException e) { 
                    // deal with it or ignore
                 }
            }
          }
 }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;Here's our entity pojo with the @Filter:&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: java;"&gt;
public class User implements java.io.Serializable {

   private int id;
   private String name;
   private Set&lt;userroles&gt; roles;

   public int getId() {
       return id;
   }   
   public void setId(int id) {
       this.id = id;
   }

   public String getName() {
       return name;
   }   
   public void setName(String n){
       name = n
   }

   @org.martin.metatag.Filter
   public java.util.Set&lt;userroles&gt; getUserRoleses() {
       return roles;
   }   
   public void setUserRoleses(java.util.Set&lt;userroles&gt; s) {
       roles = s;
   }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;And finally here's a snippet for util class:&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: java;"&gt;
   User orig = ( User ) ormTemplate.get( User.class , id );// fetch Entity from DB
   User dest = new User();                                // allocate a destination TO entity
   (new BeanUtil()).filter( orig , dest );                 // perform filtering though reflexion
   // result dest obj should be populated with everything but filtered roles, ready to be delegated further
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;The concept here is that @annotations are a powerful new feature from Java language which allow us to control | manipulate object state | behaviour. This illustration depicts how to use a filter mechanism dealing with pojo getters() reflective population which is very common in java apps.&lt;/div&gt;&lt;div&gt;Imagine taking this concept to many different levels, new frameworks are starting to inject more and more metadata directives, this is a PoC impl which worked for me when serializing pojos into AMF binary protocol, and also dealing with hibernate entities which are proxied with CGLIB bytecode generation library such as LazyInitializer, Callback, etc, etc.&lt;/div&gt;&lt;div&gt;Hope you find this useful ;-), let me know your thoughts.&lt;/div&gt;&lt;div&gt;Cheers.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-914151831225062178?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/914151831225062178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=914151831225062178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/914151831225062178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/914151831225062178'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/05/serialization-directive-with-filter.html' title='Bean @Filter Annotation'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-3510145297956406515</id><published>2009-05-06T09:19:00.000-07:00</published><updated>2009-05-14T11:28:21.916-07:00</updated><title type='text'>JNLP Experiment</title><content type='html'>Hello!&lt;div&gt;Something triggered me to evaluate at existing technologies to distribute + install rich java desktop clients in contrast of new RIA apps that run on browser + their own runtime (which has to be previously installed on the client), therefore if one already has a Java Swing desktop app, the distribution / install to clients could be simply managed by JavaWebStart [JNLP], so I decided to give it a try and experiment using a host such as AppEngine in static mode to serve the .jnlp file as well as java libraries.&lt;div&gt;I did not have a GUI app to play with so I decided to provide an existing one such as the Groovy UI console as an example.&lt;/div&gt;&lt;div&gt;Here's a ?.jnlp file for demonstration purposes:
&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: xml;"&gt;
&lt;jnlp spec="1.0+" codebase="http://martin-engine.appspot.com" href="groovy.jnlp"&gt;
&lt;information&gt;
&lt;vendor&gt;Groovy&lt;/vendor&gt;
&lt;homepage href="http://groovy.codehaus.org"&gt;
&lt;description&gt;Groovy UI Console launched as JNLP.&lt;/description&gt;
&lt;offline-allowed&gt;
&lt;/offline-allowed&gt;
&lt;/homepage&gt;
&lt;/information&gt;
&lt;security&gt;
&lt;all-permissions&gt;
&lt;/all-permissions&gt;
&lt;/security&gt;
&lt;resources&gt;
&lt;j2se version="1.5+"&gt;
&lt;jar href="groovy.jar"&gt;&lt;/jar&gt;
&lt;/j2se&gt;
&lt;/resources&gt;
&lt;application-desc class="groovy.ui.Console"&gt;
&lt;/application-desc&gt;
&lt;/jnlp&gt;
&lt;/pre&gt;
And it can be run + tested @ &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;a href="http://martin-engine.appspot.com/"&gt;here!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238);"&gt;&lt;img src="http://3.bp.blogspot.com/_M94eDahX5rM/SgG7fza8C1I/AAAAAAAAAYA/9OvIZqmc7Os/s320/trust.PNG" alt="" id="BLOGGER_PHOTO_ID_5332749588836911954" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" border="0" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;You'll have to check &lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;'Always trust content from this publisher'&lt;/span&gt; because JNLP specs force you to sign jars ('if unrestricted access to the local system is needed') and I did that with a temp keystore/cert. Note: as you can imagine this opens a security risk, what you run in that console is at your own risk ;-) this is just to illustrate a concept.
And perhaps you'll have to double-click on downloaded jnlp file due to MIME &lt;span class="Apple-style-span"  style="font-family:Arial;"&gt;&lt;code  style="color: rgb(68, 68, 68);font-family:Monaco,Courier,'Courier New',monospace;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;application/x-java-jnlp-file&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;not being understood, just in case you may need to instruct your browser to open and associate it with JAVA_HOME/bin/javaws&lt;span class="Apple-style-span"  style="font-family:Arial;"&gt;&lt;code face="Monaco,Courier,'Courier New',monospace" style="color: rgb(68, 68, 68);"&gt;&lt;/code&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:Arial;"&gt;&lt;code face="Monaco,Courier,'Courier New',monospace" style="color: rgb(68, 68, 68);"&gt;&lt;/code&gt;&lt;/span&gt;, part of this could be taken care of (server side) by a servlet wrapper which dynamically writes appropriate mime content-type header and contents to result output stream.
&lt;span class="Apple-style-span"  style="font-family:Arial;"&gt;&lt;code face="Monaco,Courier,'Courier New',monospace" style="color: rgb(68, 68, 68);"&gt;
&lt;/code&gt;&lt;/span&gt;Once it downloads and runs, you should be able to see the groovy gui console there at your fingertips to execute some new dynamic language stuff ;-)&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Update 05/10/09: I uploaded a simpler sample which downloads much faster since jar is only 19k and can be tested &lt;a href="http://riaspringblaze.appspot.com/jnlp/fsbuddy.jnlp"&gt;here&lt;/a&gt;. It's a simple PoC swing ui utility which builds from user.dir a tree component so you can easily navigate to or open resources for 'windows' OS, make sure you click on desired tree nodes so you can delegate to windows file protocol handler, here's the trick for that:&lt;/div&gt;&lt;div&gt;
&lt;pre class="brush: java;"&gt;
public static void openResourceInWindows( String resourcePahName ) throws Exception {
Runtime.getRuntime().
exec("rundll32 url.dll,FileProtocolHandler " + resourcePahName );   
}
&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Hope you find this interesting!&lt;/div&gt;&lt;div&gt;Cheers!&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-3510145297956406515?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/3510145297956406515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=3510145297956406515' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3510145297956406515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3510145297956406515'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/05/jnlp-experiment.html' title='JNLP Experiment'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M94eDahX5rM/SgG7fza8C1I/AAAAAAAAAYA/9OvIZqmc7Os/s72-c/trust.PNG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-2922853150374889366</id><published>2009-04-25T09:36:00.001-07:00</published><updated>2009-11-13T18:14:23.969-08:00</updated><title type='text'>AppEngine &amp; Adobe BlazeDS (fix)</title><content type='html'>&lt;div style="text-align: center;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/SfM8fcaO3RI/AAAAAAAAAX4/xQm_1WTpBME/s1600-h/blazeGAE.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 216px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/SfM8fcaO3RI/AAAAAAAAAX4/xQm_1WTpBME/s320/blazeGAE.png" alt="" id="BLOGGER_PHOTO_ID_5328669295009258770" border="0" /&gt;&lt;/a&gt;&lt;a href="http://riaspringblaze.appspot.com/"&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;http://riaspringblaze.appspot.com&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:100%;"&gt;

&lt;/span&gt;&lt;a href="https://riaspringblaze.appspot.com/"&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;https://riaspringblaze.appspot.com&lt;/span&gt;&lt;/a&gt;
&lt;/div&gt;Hello,

Today I was able to get [ 'remoting only' ] BlazeDS (Community release 3.2.0.3978) to work on GAE, there seems to be an issue with current production GAE Servlet Container in which consequently causes BlazeDS class flex.messaging.io.amf.AbstractAmfInput.java when gets InputStream http request to throw an EOFException = (GAE 1339) resulting a context to resolve into MessageIOConstants.STATUS_NOTAMF in the flex.messaging.endpoints.amf.SerializationFilter class.
&lt;div&gt;&lt;/div&gt;&lt;div&gt;Here's my un-official 'fix' to the issue (which just worked for me this morning):

So couple things:

[1] First make sure config file services-config.xml has
&lt;pre class="brush: xml;"&gt;&lt;manageable&gt;false&lt;/manageable&gt;&lt;/pre&gt;
, so it's not JMX managed (restricted by GAE)

&lt;pre class="brush: xml;"&gt;
&lt;system&gt;
&lt;manageable&gt;false&lt;/manageable&gt;
&lt;redeploy&gt;
&lt;enabled&gt;false&lt;/enabled&gt;
&lt;!--              &lt;watch-interval&gt;20&lt;/watch-interval&gt;&lt;br /&gt;            &lt;watch-file&gt;{context.root}/WEB-INF/flex/services-config.xml&lt;/watch-file&gt;&lt;br /&gt;            &lt;watch-file&gt;{context.root}/WEB-INF/flex/proxy-config.xml&lt;/watch-file&gt;&lt;br /&gt;            &lt;watch-file&gt;{context.root}/WEB-INF/flex/remoting-config.xml&lt;/watch-file&gt;&lt;br /&gt;            &lt;watch-file&gt;{context.root}/WEB-INF/flex/messaging-config.xml&lt;/watch-file&gt;&lt;br /&gt;            &lt;watch-file&gt;{context.root}/WEB-INF/flex/data-management-config.xml&lt;/watch-file&gt;&lt;br /&gt;            &lt;touch-file&gt;{context.root}/WEB-INF/web.xml&lt;/touch-file&gt;&lt;br /&gt;             --&gt;
&lt;/redeploy&gt;
&lt;/system&gt;
&lt;/pre&gt;

[2] And Second: on BlazeDS source look for
flex.messaging.io.amf.AbstractAmfInput.java and replace line #58 (aprox)

this.in = new DataInputStream( in );
for
this.in = new DataInputStream( new java.io.BufferedInputStream( in ) );

So it would look as:

&lt;pre class="brush: java;"&gt;
public abstract class AbstractAmfInput extends AmfIO implements ActionMessageInput
{
protected BeanProxy beanProxy = new BeanProxy();

protected DataInputStream in = null;

public AbstractAmfInput(SerializationContext context)
{
super(context);
}

public void setInputStream(InputStream in)
{
this.in = new DataInputStream( new BufferedInputStream( in ) );
}

... more
&lt;/pre&gt;

run BlazeDS ant build.xml in the following targets order : clean,sdk,common,core and replace the &lt;span style="font-weight: bold;"&gt;flex-messaging-core.jar&lt;/span&gt; into your application WEB-INF/lib folder, and deploy new war to GAE cloud.

&lt;div&gt;The one I deployed also contains Spring (3.0.0.M2) and &lt;a href="http://www.springsource.org/spring-flex"&gt;http://www.springsource.org/spring-flex&lt;/a&gt;(1.0.0.RC1)&lt;/div&gt;&lt;div&gt;&lt;div&gt;
Here's a demo app to demonstrate that it works:
&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;(Note: Flex app is a proof of concept for demonstration purpose)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;
&lt;span class="Apple-style-span"  style="font-size:100%;"&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://riaspringblaze.appspot.com/"&gt;http://riaspringblaze.appspot.com&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;
&lt;a href="https://riaspringblaze.appspot.com"&gt;&lt;span&gt;https://riaspringblaze.appspot.com&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;

For those of you interested in compiled flex-messaging-core.jar drop a request in this blog's comments and I'll send it asap (&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;do not send to my email directly, thanks&lt;/span&gt;&lt;/span&gt;).

&lt;span style="font-size:130%;"&gt;Note:&lt;/span&gt; this is an unofficial community effort, so it is delivered &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;'as is'&lt;/span&gt; for you to experiment with ;-)

&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Update on 4/28/09&lt;/span&gt;, Another issue dealing with server sessions on messaging flex.messaging.endpoints.BaseHTTPEndpoint class detects a REQUEST_ATTR_DUPLICATE_SESSION_FLAG and throws "flex.messaging.request.DuplicateSessionDetected", it'd be nice if one could add to config file a no session management parameter. So for now on [line# 405 aprox] flex.messaging.endpoints.BaseHTTPEndpoint class I basically removed the duplicateSessionDetected check (temporarily) till this matures a bit more.&lt;/div&gt;&lt;div&gt;Which by the way on deployment [appengine-web.xml] descriptor you'll need:
&lt;pre class="brush: xml;"&gt;
&lt;sessions-enabled&gt;true&lt;/sessions-enabled&gt;
&lt;/pre&gt;
&lt;span style="font-weight: bold;"&gt;Update on 09/28/2009&lt;/span&gt;: &lt;a href="http://bugs.adobe.com/jira/browse/BLZ-444"&gt;http://bugs.adobe.com/jira/browse/BLZ-444&lt;/a&gt;

I've received lots of emails asking me what libraries I'm packing under /WEB-INF/lib from G-sdk along with all other 3rd party dependencies, here's the list I have in my war (you may need more or less depending on what your app does):
&lt;pre class="brush: plain;"&gt;
martin@martin-ubuntu9 ~/projs/blazeappengine/war/WEB-INF/lib
$ ls -1
antlr-3.0.1.jar
aopalliance.jar
appengine-api-1.0-sdk-1.2.0.jar
asm-3.1.jar
aspectjrt.jar
backport-util-concurrent.jar
cfgatewayadapter.jar
cglib-2.2.jar
commons-beanutils.jar
commons-collections-3.1.jar
commons-fileupload-1.2.1.jar
commons-lang.jar
commons-logging-1.1.jar
concurrent.jar
datanucleus-appengine-1.0.0.final.jar
datanucleus-core-1.1.0.jar
datanucleus-jpa-1.1.0.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
geronimo-jpa_3.0_spec-1.1.1.jar
geronimo-jta_1.1_spec-1.1.1.jar
jackson-core-asl-0.9.9-6.jar
jdo2-api-2.3-SNAPSHOT.jar
org.springframework.aop-3.0.0.M2.jar
org.springframework.aspects-3.0.0.M2.jar
org.springframework.beans-3.0.0.M2.jar
org.springframework.context-3.0.0.M2.jar
org.springframework.context.support-3.0.0.M2.jar
org.springframework.core-3.0.0.M2.jar
org.springframework.expression-3.0.0.M2.jar
org.springframework.flex-1.0.0.RC1.jar
org.springframework.transaction-3.0.0.M2.jar
org.springframework.web-3.0.0.M2.jar
org.springframework.web.servlet-3.0.0.M2.jar
xalan.jar
&lt;/pre&gt;Let me know how it goes.....&lt;/div&gt;&lt;div&gt;Also, I'd appreciate comments/feed-back/critiques on my blog as well so we can all share experiences / discoveries, thanks.
Cheers!

&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-2922853150374889366?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/2922853150374889366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=2922853150374889366' title='217 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/2922853150374889366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/2922853150374889366'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/04/appengine-adobe-blazeds-fix.html' title='AppEngine &amp; Adobe BlazeDS (fix)'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M94eDahX5rM/SfM8fcaO3RI/AAAAAAAAAX4/xQm_1WTpBME/s72-c/blazeGAE.png' height='72' width='72'/><thr:total>217</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-6319699327331537628</id><published>2009-04-23T13:09:00.000-07:00</published><updated>2009-05-11T09:15:16.276-07:00</updated><title type='text'>Simple Java CP Builder &amp; Bootstrap</title><content type='html'>&lt;div&gt;Greetings!
How many time have you had the need to launch your java app and you wish you could organize a /lib folder such that it would look like this with neat sub-folders with their pertaining jars:
&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/SfDLptUN3bI/AAAAAAAAAXQ/_CMJrmRcCf0/s1600-h/libs.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 218px;" src="http://2.bp.blogspot.com/_M94eDahX5rM/SfDLptUN3bI/AAAAAAAAAXQ/_CMJrmRcCf0/s320/libs.png" alt="" id="BLOGGER_PHOTO_ID_5327982276578762162" border="0" /&gt;&lt;/a&gt;
One could then write a batch launcher such as:
&lt;pre class="brush: plain;"&gt;
set ROOT=.
set CP=%ROOT%/lib/com.app.desktop_1_0_0.jar
set CP=%CP%;%ROOT%/lib/antlr/antlr-2.7.6.jar
set CP=%CP%;%ROOT%/lib/antlr/antlr-runtime-3.1.1.jar
set CP=%CP%;%ROOT%/lib/commons/commons-beanutils.jar
set CP=%CP%;%ROOT%/lib/commons/commons-codec-1.3.jar
set CP=%CP%;%ROOT%/lib/other/x.jar
set CP=%CP%;%ROOT%/lib/other/y.jar
..and more here!!
set JAVA_EXE=%JAVA_HOME%\bin\java
set JVM_OPTS=-ea:com.martin... -Xms128m -Xmx256m -XX:PermSize=128m -XX:MaxPermSize=256m
set CLASS=com.martin.server.Bootstrap
set CONFIG=config/log4j.xml config/config.xml
"%JAVA_EXE%" -cp %CP% %JVM_OPTS% %CLASS% %CONFIG%
&lt;/pre&gt;
Here's an approach to let a java class build dynamically a CP from a root folder down recursively for us and could easily port and run on different environments  (note: this is a guideline, below code is incomplete):
&lt;pre class="brush: java;"&gt;
// recurseFileSystem from root folder
MyClassPath classpath = new MyClassPath( root );
String cp = System.getProperty("java.class.path");
System.setProperty("java.class.path", cp + ';' + classpath.getCPListAsString() );
Thread.currentThread().setContextClassLoader( classpath.getClassLoader() );
Policy policy = Policy.getPolicy();
if (policy != null)
policy.refresh();
classpath.getClassLoader().loadClass(classname).
getDeclaredMethod("main",paramTypes).invoke(null,params);

&lt;/pre&gt;
Where the trick is performing a file system recursive jar fetcher and inject it into
System.setProperty("java.class.path",x); and then invoking a main from a arg class specified, below is a sample recursive file system code:

&lt;div&gt;
&lt;pre class="brush: java;"&gt;
private void recurseFileSystem( File dir ) throws IOException {

File[] jars = dir.listFiles( new FilenameFilter()  {
public boolean accept(File dir, String name)  {
 String namelc = name.toLowerCase();
   return namelc.endsWith(".jar");
 // could add more file extensions here
}
} );

for (int i=0; jars!=null &amp;amp;&amp;amp; i&lt;jars.length; boolean="" added="classpath.addComponent(jars[i].getCanonicalPath());"&gt;cp+=":"  !#")+jar);
}

File[] dirs = dir.listFiles(
new FilenameFilter()  {
   public boolean accept(File dir, String name)  {
   return dir.isDirectory();
   }
     }
);

for (int i=0;i&lt;dirs.length; i++)
{ 
recurseFileSystem( new File( dirs[i].getCanonicalPath() ) );
}

&lt;/pre&gt;
&lt;/div&gt;
By doing so here's the result from a console with our CP built for us:
&lt;pre class="brush: plain;"&gt;
Root  -&gt; C:/martin/projs/demo
Config-&gt; C:/martin/projs/demo/config
Class -&gt; com.martin.server.Bootstrap
Libs  -&gt; C:/martin/projs/com.martin.svr/lib
Args  -&gt; log4j.xml config.xml
-&gt;cp+=C:/martin/projs/demo/lib/com.martin.bootstrap_1_0_0.jar
-&gt;cp+=C:/martin/projs/demo/lib/com.martin.svr_1_0_0.jar
-&gt;cp+=C:/martin/projs/demo/lib/antldr/antlr-2.7.6.jar
-&gt;cp+=C:/martin/projs/demo/lib/antldr/antlr-runtime-3.1.1.jar
-&gt;cp+=C:/martin/projs/demo/lib/commons/commons-beanutils.jar
-&gt;cp+=C:/martin/projs/demo/lib/commons/commons-codec-1.3.jar
-&gt;cp+=C:/martin/projs/demo/lib/commons/commons-lang.jar
-&gt;cp+=C:/martin/projs/demo/lib/commons/commons-logging-1.1.jar
-&gt;cp+=C:/martin/projs/demo/lib/jetty/jetty-naming-6.1.16.jar
-&gt;cp+=C:/martin/projs/demo/lib/jetty/jetty-util-6.1.16.jar
-&gt;cp+=C:/martin/projs/demo/lib/jetty/jetty.jar
-&gt;cp+=C:/martin/projs/demo/lib/jgroup/jgroups-core.jar
context            -&gt;C:/martin/projs/com.martin.svr
classloader        -&gt;java.net.URLClassLoader
classloader.parent -&gt;sun.misc.Launcher$AppClassLoader
================[  start  ]=============
&lt;/pre&gt;
Console example:&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238);"&gt;&lt;img src="http://2.bp.blogspot.com/_M94eDahX5rM/SfDUbg9VSfI/AAAAAAAAAXY/iyn7JZ8AZ-0/s320/run.png" alt="" id="BLOGGER_PHOTO_ID_5327991928348035570" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 122px;" border="0" /&gt;&lt;/span&gt;
So we would invoke our app simply as:

&lt;span style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 51, 255);"&gt;java -jar run.jar ./ /lib org.myapp.MyClassWithMain&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;
&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 204);"&gt;//usage : java -jar run.jar rootPath libPathFromRoot className cmdArguments&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

Cheers!
Martin


&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-6319699327331537628?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/6319699327331537628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=6319699327331537628' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/6319699327331537628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/6319699327331537628'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/04/simple-java-cp-bootstrapper.html' title='Simple Java CP Builder &amp; Bootstrap'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M94eDahX5rM/SfDLptUN3bI/AAAAAAAAAXQ/_CMJrmRcCf0/s72-c/libs.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-9158801075838683677</id><published>2009-04-23T09:51:00.000-07:00</published><updated>2009-04-24T22:36:33.731-07:00</updated><title type='text'>Lean Server Container</title><content type='html'>&lt;div&gt;Greetings!&lt;/div&gt;I have worked in the past with full stack J2EE: JBoss,Websphere, and servlet containers: Tomcat, Jetty, Resin,  although sometimes I felt some were too heavy with many bells + whistles and plain servlet container lacked few other features, I was thinking perhaps I could glue together a middle ground container assembled via a dependency injection framework.&lt;div&gt;The result was that I ended up assembling my own simple container as an experiment, here's the full stack so far:&lt;/div&gt;&lt;div&gt;[0] Log4j for logging.&lt;/div&gt;&lt;div&gt;[1] Spring for main configuration and IoC.&lt;/div&gt;&lt;div&gt;[2] JMX Kernel for managed MBeans support.&lt;/div&gt;&lt;div&gt;[3] Embbeding Jetty servlet container.&lt;/div&gt;&lt;div&gt;[4] JGroups for a simple cloud support.
&lt;/div&gt;&lt;div&gt;[5] Embbeded Hypersonic  RDBM in-proc DB  support.&lt;/div&gt;&lt;div&gt;[6] Hibernate for ORM support.&lt;/div&gt;&lt;div&gt;[7] A simple FIFO Queue support.&lt;/div&gt;&lt;div&gt;[8] A simple Map mem cache with fail over capabilities via JGroups.&lt;/div&gt;&lt;div&gt;And many other collaboration frameworks such as Jasper reporting engine, JFreeCharting, Drools rules engine, Quartz scheduling, BlazeDS for AMF serializations, etc, etc.&lt;/div&gt;&lt;div&gt;Container bootstraps in less that 5 seconds with all features, here's the start up sequence console:&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_M94eDahX5rM/SfCj4K0LltI/AAAAAAAAAWo/w9mR5_SygQk/s1600-h/svr_console.png" style="text-decoration: none;"&gt;&lt;img src="http://2.bp.blogspot.com/_M94eDahX5rM/SfCj4K0LltI/AAAAAAAAAWo/w9mR5_SygQk/s320/svr_console.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5327938544550516434" style="text-decoration: underline;display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 194px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;
&lt;span class="Apple-style-span"  style="  white-space: pre-wrap; font-family:-webkit-monospace;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;I'd like to share my spring main config file to depict all collaboration objects:&lt;/span&gt;&lt;/span&gt;&lt;pre class="brush: xml;"&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans" xsi="http://www.w3.org/2001/XMLSchema-instance" util="http://www.springframework.org/schema/util" context="http://www.springframework.org/schema/context" schemalocation="        http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-2.0.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;
&lt;description&gt;
     Martin Z. 04/23/2009
     Main configuration.
     Register in bootstrap.services class all [Services]
&lt;/description&gt;

&lt;!--:::::::::::::::::: SERVICES REGISTRY ::::::::::::::::::: --&gt;

&lt;bean id="bootstrap" class="com.martin.server.Bootstrap"&gt;
    &lt;property name="services"&gt;
    &lt;!-- Serviceable implementors --&gt;
        &lt;list&gt;
          &lt;value&gt;cluster&lt;/value&gt;
          &lt;value&gt;dbserver&lt;/value&gt;          
  &lt;value&gt;ormservice&lt;/value&gt; 
  &lt;value&gt;mqservice&lt;/value&gt;
  &lt;value&gt;cacheservice&lt;/value&gt;
  &lt;value&gt;http&lt;/value&gt;  
  &lt;!--          &lt;value&gt;rulesservice&lt;/value&gt;      &lt;br /&gt;              &lt;value&gt;jmxservice&lt;/value&gt; &lt;br /&gt;     --&gt;
        &lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;

&lt;!--:::::::::::::::::: JMX-MBEANS ::::::::::::::::::    &lt;bean id="'gridMbean'" class="'com.martin.server.jmx.JmxCloudServiceManager'"&gt;&lt;br /&gt;      &lt;constructor-arg type="'com.martin.server.CloudService'" ref="'cluster'/"&gt;&lt;br /&gt;   &lt;/bean&gt; &lt;br /&gt;   &lt;bean id="'jmxservice'" class="'com.martin.server.JmxService'"&gt;&lt;br /&gt;      &lt;property name="'domain'" value="'DOMAIN'/"&gt;&lt;br /&gt;      &lt;property name="'htmlViewerPort'" value="'8082'/"&gt;&lt;br /&gt;      &lt;property name="'mbeans'"&gt;&lt;br /&gt;            &lt;map&gt;&lt;br /&gt;                &lt;entry key="'JmxGridServiceBMean'"&gt;&lt;ref bean="'gridMbean'/"&gt;&lt;/entry&gt;             &lt;br /&gt;            &lt;/map&gt;&lt;br /&gt;      &lt;/property&gt;      &lt;br /&gt;   &lt;/bean&gt;  &lt;br /&gt;   &lt;bean id="'springMBean'" class="'org.springframework.jmx.support.MBeanServerFactoryBean'" on="'jmxservice'"&gt;&lt;br /&gt;     &lt;property name="'locateExistingServerIfPossible'" value="'true'/"&gt;&lt;br /&gt;   &lt;/bean&gt; &lt;br /&gt;   --&gt;
  
&lt;!--:::::::::::::::::: CLUSTER :::::::::::::::::: --&gt;

&lt;bean id="cluster" class="com.martin.server.CloudService" on="bootstrap"&gt;
     &lt;property name="clusterName" value="CLUSTER"&gt;
     &lt;property name="clusterTopologyConfig" value="../config/net/udp.xml"&gt;                 
&lt;/property&gt;&lt;/property&gt;&lt;/bean&gt;

&lt;!--::::::::::::::::::: CTX STATIC CONFIG ::::::::::::::::::: --&gt;

&lt;bean id="ctx" class="com.martin.config.CtxConfig" on="bootstrap"&gt;
    &lt;constructor-arg type="com.martin.server.Bootstrap" ref="bootstrap"&gt;
    &lt;property name="properties"&gt; &lt;!-- app scope static properties --&gt;
        &lt;map&gt;
            &lt;entry key="anykey" value="anyval"&gt;
        &lt;/entry&gt;&lt;/map&gt;
    &lt;/property&gt;      
&lt;/constructor-arg&gt;&lt;/bean&gt;

&lt;!--::::::::::::::::: HTTP SERVLET CONTAINER :::::::::::::::: --&gt;
&lt;bean id="http" class="com.martin.server.JettyService" on="bootstrap"&gt;
     &lt;property name="lib" value="../lib"&gt;
     &lt;property name="config" value="../config/jetty/jetty.xml"&gt;    
&lt;/property&gt;&lt;/property&gt;&lt;/bean&gt;    
                  
&lt;!--::::::::::::::::::::::: DB SERVER ::::::::::::::::::::::::: --&gt;

&lt;bean id="jdbc" class="org.hsqldb.jdbcDriver"&gt;

&lt;bean id="hsqldb" class="org.hsqldb.Server" on="jdbc"&gt;
  &lt;!-- running inProc , if server mode is desired then rem-out                                  &lt;property name="'address'" value="'localhost'"&gt;&lt;br /&gt;       &lt;property name="'port'" value="'9001'"&gt;&lt;br /&gt;       &lt;property name="'silent'" value="'false'"&gt;  &lt;br /&gt;       &lt;property name="'trace'" value="'true'"&gt;&lt;br /&gt;       &lt;property name="'tls'" value="'false'"&gt;      &lt;br /&gt;       --&gt;
&lt;/bean&gt;

&lt;bean id="dbserver" class="com.martin.server.HsqldbServer" on="hsqldb"&gt;
   &lt;constructor-arg type="org.hsqldb.Server" ref="hsqldb"&gt;
   &lt;property name="dbPath" value="../db/HSQLDB"&gt;
   &lt;property name="dbName" value=""&gt;
   &lt;property name="usr" value="???"&gt;
   &lt;property name="pwd" value="???"&gt;     
&lt;/property&gt;&lt;/property&gt;&lt;/property&gt;&lt;/property&gt;&lt;/constructor-arg&gt;&lt;/bean&gt;

&lt;!--::::::::::::::::::::::: HBM ORM ::::::::::::::::::::::::: --&gt;
  
&lt;bean id="ormservice" class="com.martin.server.HibernateService" on="dbserver"&gt;
   &lt;property name="configFile" value="hbm.cfg.xml"&gt;
   &lt;property name="turnStatsOn" value="false"&gt;
   &lt;!-- watch-dog thread [HMB log4j in INFO lvl] --&gt; 
&lt;/property&gt;&lt;/property&gt;&lt;/bean&gt;

&lt;bean id="flexdomain" class="com.martin.orm.impl.FlexDomain" on="ormservice" scope="prototype"&gt;
   &lt;constructor-arg type="com.martin.server.HibernateService" ref="ormservice"&gt;
&lt;/constructor-arg&gt;&lt;/bean&gt;

&lt;!--::::::::::::::::::::::: REPORTING ::::::::::::::::::::::::: --&gt;

&lt;bean id="reportEngine" class="com.martin.flex.svr.rpt.JasperReportEngine" on="ormservice" scope="prototype"&gt;
   &lt;constructor-arg type="com.martin.server.HibernateService" ref="ormservice"&gt;
    &lt;property name="reports"&gt;
        &lt;map&gt;  &lt;!-- register [jrxml] reports to be served here --&gt;
            &lt;entry key="rptProperty" value="../web/reports/ReportProperty.jrxml"&gt; 
            &lt;entry key="rptMlsTot" value="../web/reports/MlsTotalReport.jrxml"&gt;
            &lt;entry key="rptPieChart" value="../web/reports/PieChartReport.jrxml"&gt;                               
        &lt;/entry&gt;&lt;/entry&gt;&lt;/entry&gt;&lt;/map&gt;
    &lt;/property&gt;   
&lt;/constructor-arg&gt;&lt;/bean&gt;

&lt;bean id="chartEngine" class="com.martin.flex.svr.rpt.ChartImageImpl" scope="prototype"&gt;
    &lt;property name="charts"&gt;
        &lt;map&gt;  &lt;!-- register [chart resources] reports to be served here --&gt;
            &lt;entry key="chartPie" value="../web/charts/pie.png"&gt; 
            &lt;entry key="chartBar" value="../web/charts/bar.png"&gt;
            &lt;entry key="chartBarG" value="../web/charts/barg.png"&gt;                               
        &lt;/entry&gt;&lt;/entry&gt;&lt;/entry&gt;&lt;/map&gt;
    &lt;/property&gt;   
&lt;/bean&gt;
 
&lt;!--::::::::::::::::::::::: QUEUEs ::::::::::::::::::::::::: --&gt;

&lt;bean id="in-queue" class="com.martin.mq.queue.Queue"&gt;
   &lt;constructor-arg value="IN-QUEUE"&gt;
&lt;/constructor-arg&gt;&lt;/bean&gt;
&lt;bean id="out-queue" class="com.martin.mq.queue.Queue"&gt;
   &lt;constructor-arg value="OUT-QUEUE"&gt;
&lt;/constructor-arg&gt;&lt;/bean&gt;
     
&lt;bean id="in-dispatcher" class="com.martin.server.impl.sample.TestQueueDispatcherImpl"&gt;
   &lt;constructor-arg index="0" type="com.martin.mq.queue.Queue" ref="in-queue"&gt;
   &lt;constructor-arg index="1" value="true"&gt;   &lt;!-- blocking queue --&gt;
   &lt;constructor-arg index="2" value="true"&gt;   &lt;!-- persist to FS --&gt;
&lt;/constructor-arg&gt;&lt;/constructor-arg&gt;&lt;/constructor-arg&gt;&lt;/bean&gt;
&lt;bean id="out-dispatcher" class="com.martin.server.impl.sample.TestQueueDispatcherImpl"&gt;
   &lt;constructor-arg index="0" type="com.martin.mq.queue.Queue" ref="out-queue"&gt;
   &lt;constructor-arg index="1" value="true"&gt;   &lt;!-- blocking queue --&gt;
   &lt;constructor-arg index="2" value="true"&gt;   &lt;!-- persist to FS --&gt;
&lt;/constructor-arg&gt;&lt;/constructor-arg&gt;&lt;/constructor-arg&gt;&lt;/bean&gt;
              
&lt;bean id="mqservice" class="com.martin.server.MQService"&gt;
    &lt;property name="queueDispatchers"&gt;
    &lt;!-- AbstractQueueServiceImpl --&gt;
        &lt;list&gt;
           &lt;ref bean="in-dispatcher"&gt;
           &lt;ref bean="out-dispatcher"&gt;
        &lt;/ref&gt;&lt;/ref&gt;&lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;       

&lt;!--::::::::::::::::::::::: CACHEs ::::::::::::::::::::::::: --&gt;

&lt;bean id="cache-pojo" class="com.martin.cache.Cache"&gt;
   &lt;constructor-arg value="CACHE-POJO"&gt;
   &lt;property name="sleepInterval" value="60000"&gt;  &lt;!-- 60000  : 1m | 3600000 = 1hr --&gt;
   &lt;property name="expireInterval" value="12000"&gt;   &lt;!-- 900000 : 15 minutes --&gt;
&lt;/property&gt;&lt;/property&gt;&lt;/constructor-arg&gt;&lt;/bean&gt;
     
&lt;bean id="cache-session" class="com.martin.cache.Cache"&gt;
   &lt;constructor-arg value="CACHE-SESS"&gt;
   &lt;property name="sleepInterval" value="60000"&gt;
   &lt;property name="expireInterval" value="900000"&gt;
&lt;/property&gt;&lt;/property&gt;&lt;/constructor-arg&gt;&lt;/bean&gt;
      
&lt;bean id="cacheservice" class="com.martin.server.CacheService"&gt;
    &lt;property name="caches"&gt;
        &lt;list&gt;
           &lt;ref bean="cache-pojo"&gt;
           &lt;ref bean="cache-session"&gt;           
        &lt;/ref&gt;&lt;/ref&gt;&lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;

&lt;!--:::::::::::::::::::: RULES ENGINE ::::::::::::::::::::::::      &lt;bean id="'rulesservice'" class="'com.martin.server.RulesService'"&gt;&lt;br /&gt;        &lt;property name="'configFiles'"&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;../config/rules.drl&lt;/value&gt;         &lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;   &lt;br /&gt;        &lt;property name="'facts'"&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;               &lt;ref bean="'fact1'"&gt;            &lt;br /&gt;               &lt;ref bean="'fact2'"&gt;&lt;br /&gt;               &lt;ref bean="'fact3'"&gt;                              &lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;  &lt;/bean&gt;       &lt;br /&gt;--&gt;
 
&lt;!--::::::::::::::::::::::: TASKs :::::::::::::::::::::::::::: --&gt;
&lt;!--     &lt;bean id="'task'" class="'com.martin.task.SimpleTask'"&gt;   &lt;br /&gt;                  &lt;br /&gt;  &lt;bean class="'org.springframework.scheduling.timer.ScheduledTimerTask'"&gt;&lt;br /&gt;    &lt;property name="'delay'" value="'4000'"&gt;&lt;br /&gt;    &lt;property name="'period'" value="'2000'"&gt;&lt;br /&gt;    &lt;property name="'timerTask'" ref="'task'"&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;  --&gt;

&lt;!--     &lt;bean id="'job'" class="'org.springframework.scheduling.quartz.JobDetailBean'"&gt;&lt;br /&gt;      &lt;property name="'jobClass'" value="'com.martin.task.SimpleJob'"&gt;&lt;br /&gt;  &lt;/bean&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;bean id="'cronTrigger'" class="'org.springframework.scheduling.quartz.CronTriggerBean'"&gt;&lt;br /&gt;       &lt;property name="'jobDetail'" ref="'job'/"&gt;      &lt;br /&gt;       &lt;property name="'cronExpression'" value="'*"&gt; &lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;       &lt;br /&gt;  &lt;bean id="'scheduler'" class="'org.springframework.scheduling.quartz.SchedulerFactoryBean'"&gt;&lt;br /&gt;    &lt;property name="'triggers'"&gt;&lt;br /&gt;      &lt;list&gt;&lt;br /&gt;         &lt;ref bean="'cronTrigger'/"&gt;&lt;br /&gt;      &lt;/list&gt;&lt;br /&gt;    &lt;/property&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt; --&gt;

&lt;!--::::::::::::::::::::::: EMAILING :::::::::::::::::::::::::::     &lt;bean id="'mailSender'" class="'org.springframework.mail.javamail.JavaMailSenderImpl'"&gt;&lt;br /&gt;    &lt;property name="'host'" value="'mail.company.com'/"&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;  &lt;bean id="'templateMessage'" class="'org.springframework.mail.SimpleMailMessage'"&gt;&lt;br /&gt;    &lt;property name="'from'" value="'recipient@company.com'/"&gt;&lt;br /&gt;    &lt;property name="'subject'" value="'Title"&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;  &lt;bean id="'orderManager'" class="'com.martin.task.SimpleMail'"&gt;&lt;br /&gt;    &lt;property name="'mailSender'" ref="'mailSender'/"&gt;&lt;br /&gt;    &lt;property name="'templateMessage'" ref="'templateMessage'/"&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;--&gt;

&lt;/bean&gt;&lt;/beans&gt;

&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Now I prototype quickly on my self-managed container, I have tested portability by deploying a war web app on JBoss 5 with [ -cweb ] configuration and it all worked just fine.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Anyways, this is it for today ;-)&lt;/div&gt;&lt;div&gt;Cheers!&lt;/div&gt;&lt;div&gt;Martin&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-9158801075838683677?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/9158801075838683677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=9158801075838683677' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/9158801075838683677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/9158801075838683677'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/04/simple-lean-server-container.html' title='Lean Server Container'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M94eDahX5rM/SfCj4K0LltI/AAAAAAAAAWo/w9mR5_SygQk/s72-c/svr_console.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-3289589258211557512</id><published>2009-04-22T12:11:00.000-07:00</published><updated>2009-11-13T18:09:25.730-08:00</updated><title type='text'>AppEngine 2nd Experiment</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_M94eDahX5rM/Se9-0NJhRZI/AAAAAAAAAWg/-gStL4OYrqY/s1600-h/weather.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 237px;" src="http://3.bp.blogspot.com/_M94eDahX5rM/Se9-0NJhRZI/AAAAAAAAAWg/-gStL4OYrqY/s320/weather.png" alt="" id="BLOGGER_PHOTO_ID_5327616319550473618" border="0" /&gt;&lt;/a&gt;
&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;a href="http://riaconcept.appspot.com/ria/Wind.swf"&gt;http://riaconcept.appspot.com/ria/Wind.swf&lt;/a&gt;
&lt;/div&gt;&lt;div&gt;&lt;a href="https://riaconcept.appspot.com/ria/Wind.swf"&gt;https://riaconcept.appspot.com/ria/Wind.swf&lt;/a&gt;

&lt;/div&gt;So I added cron support for a simple scheduled job that fetches (via fetchurl impl wrapped as java.net.URL) weather data from sources and places in a local cache. Also I played with yahoo map swc component.&lt;div&gt;
&lt;pre class="brush: xml;"&gt;
cron.xml
&lt;cronentries&gt;
&lt;cron&gt;
&lt;url&gt;/urltoaccess&lt;/url&gt;
&lt;description&gt;Fetch the weather cache every 15 minutes&lt;/description&gt;
&lt;schedule&gt;every 15 minutes of 09:00 18:00&lt;/schedule&gt;
&lt;timezone&gt;America/Tijuana&lt;/timezone&gt;
&lt;/cron&gt;
&lt;/cronentries&gt;
&lt;/pre&gt; Although schedule for time range is still not implemented @ GAE, which I added a request &lt;a href="http://code.google.com/p/googleappengine/issues/detail?id=1398"&gt;here .&lt;/a&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;

&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-3289589258211557512?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/3289589258211557512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=3289589258211557512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3289589258211557512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/3289589258211557512'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/04/appengine-2nd-experiment.html' title='AppEngine 2nd Experiment'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M94eDahX5rM/Se9-0NJhRZI/AAAAAAAAAWg/-gStL4OYrqY/s72-c/weather.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4926719740036603542.post-4137387061701629371</id><published>2009-04-15T07:15:00.000-07:00</published><updated>2009-11-13T18:08:42.725-08:00</updated><title type='text'>Google AppEngine - RIA PoC Experiment</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_M94eDahX5rM/SeYGGM6QzAI/AAAAAAAAAV0/M-pn-EaA4Sg/s1600-h/ria.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 161px;" src="http://1.bp.blogspot.com/_M94eDahX5rM/SeYGGM6QzAI/AAAAAAAAAV0/M-pn-EaA4Sg/s320/ria.png" alt="" id="BLOGGER_PHOTO_ID_5324950313026767874" border="0" /&gt;
&lt;/a&gt;&lt;div&gt;&lt;p class="MsoNormal"&gt;So I decided to take Google’s AppEngine for a quick test drive last night, here’s the result after few deploys :&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;(Note: not all features are implemented, this is a quick proof of concept ;-)&lt;/span&gt;
&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;a href="http://riaconcept.appspot.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;http://riaconcept.appspot.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;a href="http://riaconcept.appspot.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;a href="https://riaconcept.appspot.com"&gt;https://riaconcept.appspot.com&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;This is a Flex simple app based on  &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 17px;"&gt;&lt;a href="http://www.thinserverarchitecture.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;http://www.thinserverarchitecture.com)&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="line-height: normal;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt; principle running on Google's AppEngine + cloud:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;&lt;p class="MsoNormal"&gt;
&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Experiment Results:&lt;/span&gt;
&lt;/p&gt;&lt;p class="MsoNormal"&gt;[1] Careful using 3rd party libraries that use reflexion, even if library introspects your own classes, Google sandboxes it, application still deploys without warning but fails on runtime @ cloud, even though app works fine on local development environment with current Google’s SDK 1.2.0 ver. Oh and spawning threads are a no no also.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Here’s link so you can check what JRE classes are available:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;a href="http://code.google.com/appengine/docs/java/jrewhitelist.html"&gt;http://code.google.com/appengine/docs/java/jrewhitelist.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;[2] Instead of doing JSP on view I decided to do the UI as RIA via Flex which talks over HTTP / XML to a servlet, I'' try the BlazeDS / AMF soon.&lt;/p&gt;&lt;p class="MsoNormal"&gt;[3] Make sure you specify static + non-static content @  \WEB-INF\appengine-web.xml deployment descriptor and if you want SSL support.
&lt;/p&gt;&lt;p class="MsoNormal"&gt;[4] JDO POJO Entities via annotation demarcation is nice + easy, example:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;@PersistenceCapable(identityType = IdentityType.APPLICATION)
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;public class User {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    @PrimaryKey&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)private Long id;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    @Persistent&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;private String name;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    @Persistent private String email;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    @Persistent private Date created;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;public Long getId() {&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;return id; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;     …setters() and getters()&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;So dealing with Entity persistant was almost a snap, I just wish JDOQL was a bit more robust, but overall if you know any ORM you would feel very familiar to persist and retrieve entities from Bigtable thru JDO wrapper (datanuleous).&lt;/p&gt;&lt;p class="MsoNormal"&gt;[5] My PDF proxy does not work, not sure why yet, but perhaps it has to do with http header Content-Disposition",method + ";filename=" + name&lt;/p&gt;&lt;p class="MsoNormal"&gt;[6] Internal dev SDK servlet container is Jetty with jasper support for JSP, and they provide ANT scripts for those who do not want to use Eclipse plug-in.&lt;/p&gt;&lt;p class="MsoNormal"&gt;[7] AppEngine web console is easy to navigate and intuitive, you can see logs and filter them by different levels, and details on resource consumption is well displayed.&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;img src="http://1.bp.blogspot.com/_M94eDahX5rM/SeYIKHa0oTI/AAAAAAAAAV8/7mP3T7r0Jno/s320/appengine-console.png" /&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: left;"&gt;current free quotas&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); line-height: 14px;font-family:Verdana;font-size:11px;"  &gt;&lt;ul style="margin: 0px 0px 0.75em 30px; padding: 0px; background-repeat: repeat-y; list-style-type: disc;"&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;request size - 10 megabytes&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;response size - 10 megabytes&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;request duration - 30 seconds&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;simultaneous dynamic requests - 30&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;maximum number of application files - 1,000&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;maximum number of static files - 1,000&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;maximum size of an application file - 10 megabytes&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;maximum size of a static file - 10 megabytes&lt;/li&gt;&lt;li style="margin: 0px; padding: 0px; text-align: left;"&gt;maximum total size of all application and static files - 150 megabytes&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: left;"&gt;Overall, for couple hrs of play, I experienced after few deploys the google cloud, you have to abide to few rules + (expected) restrictions here and there but it’s still on a early stage. With free quota one can only experiment to a certain extent but gives you enough to get your feet wet.
&lt;/p&gt;&lt;p class="MsoNormal"&gt;Cheers.  ;-)&lt;/p&gt;&lt;p class="MsoNormal"&gt;Have fun!&lt;/p&gt;&lt;p class="MsoNormal"&gt;Martin&lt;/p&gt;&lt;div&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4926719740036603542-4137387061701629371?l=martinzoldano.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://martinzoldano.blogspot.com/feeds/4137387061701629371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4926719740036603542&amp;postID=4137387061701629371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4137387061701629371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4926719740036603542/posts/default/4137387061701629371'/><link rel='alternate' type='text/html' href='http://martinzoldano.blogspot.com/2009/04/google-appengine-ria-poc-experiment.html' title='Google AppEngine - RIA PoC Experiment'/><author><name>Martin Zoldano</name><uri>http://www.blogger.com/profile/07988812002919971712</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_M94eDahX5rM/SeXrTng1BjI/AAAAAAAAAVQ/c73C1wM3Eww/S220/Martin2007.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M94eDahX5rM/SeYGGM6QzAI/AAAAAAAAAV0/M-pn-EaA4Sg/s72-c/ria.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
