<?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-19518284</id><updated>2012-01-17T06:32:47.914-06:00</updated><category term='java'/><category term='clojure'/><category term='mule'/><category term='jfreechart'/><category term='soa'/><category term='data-service'/><category term='aop'/><category term='swingbuilder'/><category term='oepe'/><category term='api'/><category term='web services'/><category term='groovy-1.7'/><category term='gae'/><category term='scriptom'/><category term='google-collection'/><category term='leiningen'/><category term='outlook'/><category term='grails'/><category term='gep3'/><category term='compojure'/><category term='osb'/><category term='groovy'/><category term='activex'/><category term='rss'/><category term='administration'/><category term='mind-map'/><category term='dsl'/><category term='weblogic'/><category term='ast-transformation'/><category term='middleware'/><category term='collections'/><category term='service bus'/><category term='jmx'/><title type='text'>Kartik Shah</title><subtitle type='html'>/src/blog</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>28</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19518284.post-3398658744809993126</id><published>2011-07-09T13:15:00.000-05:00</published><updated>2011-07-09T13:15:09.615-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><category scheme='http://www.blogger.com/atom/ns#' term='soa'/><title type='text'>SOA Composite deployment - Oracle SOA Suite</title><content type='html'>&lt;div&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="font-family: Menlo; font-size: medium;"&gt;&lt;span style="font-family: Menlo;"&gt;&lt;span style="font-family: Verdana;"&gt;&lt;strong&gt;&lt;span style="border-collapse: separate; color: #000000; font-family: Times; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;span style="font-size: small;"&gt;This post is going to be about very specific subject - SOA Composite deployment on Oracle SOA Suite. I am going to capture few issues faced while deploying SOA composite.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="border-collapse: separate; color: #000000; font-family: Menlo; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: small;"&gt;&lt;span style="font-family: Menlo;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="border-collapse: separate; color: #000000; font-family: Menlo; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: small;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;Sample Composite&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;For purpose of this blog, consider a simple SOA composite that does the following:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Read entries from a database&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Create XML from the entries&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Store XML entries to another database&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Read XML entries&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Post each XML entry to a web service&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;There is good amount of workflow and business logic that makes it a perfect use case for doing it with BPEL, but that is beyond the purpose of this entry.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;Composite Dependencies&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Sample SOA composite had following dependencies:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Couple of Datasource (one to read source data and other to store XML Entries)&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;JMS Queue (Weblogic&amp;rsquo;s Uniform Distributed Queues)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;Deployment Process&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;em&gt;&lt;span style="letter-spacing: 0px;"&gt;1. Datasources&lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;em&gt;Create Generic Datasources&lt;/em&gt;&amp;nbsp;pointing to individual Oracle RAC node and a&amp;nbsp;&lt;em&gt;Multi Datasource&lt;/em&gt;&amp;nbsp;using WLST scripts. (Most of the scripts are written for Weblogic 10.3.3, so haven&amp;rsquo;t explored newly introduced GridLinked Datasource in Weblogic 10.3.4.)&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;em&gt;2. JMS Resources&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Create JMS Server, JMS Module, Sub deployment, Connection Factory and JMS Queues using WLST scripts.&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;em&gt;3. DBAdapter.rar&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;The composite uses DBAdapter connector to interact with databases, so add outbound connection pools the DBAdapter.rar pointing to actual Weblogic Datasources and redeploy application&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;4. Deploy Composite&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Finally, deploy the composite using Enterprise Manager Console.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;Lessons Learned&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;strong&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;1. Server Start parameters&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Using Enterprise Manager to deploy, the deployment window got stuck and never returned back. The issue, it turns out, is that the deployment was not able to communicate among instance servers. If SOA cluster is using multicast to communicate across weblogic instances, you will required following parameters on each server instance. The parameter adds well known address&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;-Dtangosol.coherence.wka1=soa01.mycompany.com&amp;nbsp;-Dtangosol.coherence.wka2=soa02.&lt;/span&gt;&lt;/span&gt;&lt;a href="http://suddenlink.cequel3.com/"&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;ycompany.com&amp;nbsp;-Dtangosol.coherence.localhost=soa01.mycompany.com&amp;nbsp;-Xmx2048m&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;2. Failure updating DBAdapter.rar connector application&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;On attempt to create outbound connection pool pointing to weblogic datasource, activation fails complaining FileNotFoundException: Plan.xml. The file is present on the primary server instance, but it isn't replicated on other nodes. I am not sure why but for some reason the Plan.xml was required to present on all the nodes, even if deployment is being done from machine with AdminServer.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;3. Failure on interaction with DB on some instances.&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;span style="font-weight: normal;"&gt;Even after the deployment was successful, any DB activities from nodes other than primary node failed giving following error:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;BINDING.JCA-12511&lt;br /&gt; JCA Binding Component connection issue.&lt;br /&gt; JCA Binding Component is unable to create an outbound JCA (CCI) connection.&lt;br /&gt; apptools:InsertLogDB [ InsertLogDB_ptt::insert(TestLogCollection,TestLogCollection) ] : The JCA Binding Component was unable to establish an outbound JCA CCI connection due to the following issue: BINDING.JCA-12510&amp;nbsp;JCA Resource Adapter location error.&lt;br /&gt; Unable to locate the JCA Resource Adapter via .jca binding file element &amp;lt;connection-factory/&amp;gt;&amp;nbsp;The JCA Binding Component is unable to startup the Resource Adapter specified in the &amp;lt;connection-factory/&amp;gt; element:&amp;nbsp; location='eis/DB/application-ds'.&amp;nbsp;The reason for this is most likely that either&amp;nbsp;1) the Resource Adapters RAR file has not been deployed successfully to the WebLogic Application server or&amp;nbsp;2) the '&amp;lt;jndi-name&amp;gt;' element in weblogic-ra.xml has not been set to eis/DB/application-ds. In the last case you will have to add a new WebLogic JCA connection factory (deploy a RAR).&amp;nbsp;Please correct this and then restart the Application Server&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Please make sure that the JCA connection factory and any dependent connection factories have been configured with a sufficient limit for max connections. Please also make sure that the physical connection to the backend EIS is available and the backend itself is accepting connections.&lt;/p&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;span style="font-family: Verdana;"&gt;&lt;span style="font-weight: normal;"&gt;One noticeable thing on weblogic console was that under testing tab of DBAdapter.rar all outbound connection pools were not visible. The issue is that updated Plan.xml is not replicated to all other nodes. You have to manually copy the Plan.xml containing all outbound connection pool to all server instance nodes.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;span style="font-weight: normal;"&gt;Here is what you need to do:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Copy the Plan.xml containing all outbound connection pool to all nodes&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Update the connector application DBAdapter.rar&lt;/span&gt;&lt;/li&gt;&lt;li style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;Restart DBAdapter.rar and Application server instance&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; min-height: 15px; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;&lt;strong&gt;4. BAM Cluster Multicast misconfiguration&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="letter-spacing: 0px; font-family: verdana, geneva;"&gt;A misconfiguration on the Multicast address of BAM cluster resulted in Access Forbidden 403. The issue was that BAM server was trying to communicate with another environment cluster. (i.e. prod bam cluster trying to communicate with test bam cluster).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;Here is the error:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;&amp;lt;BEA-000141&amp;gt; &amp;lt;TCP/IP socket failure occurred while fetching statedump over HTTP from 142374575950937656S:10.50.XX.XXX:[XXXXX,XXXXX,-1,-1,-1,-1,-1]:soa:soa_server1.&lt;br /&gt; java.io.FileNotFoundException: Response: '403: Forbidden' for url: '&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;a href="http://10.50.XXX.XXX:16101/bea_wls_cluster_internal/psquare/p2?senderNum=3&amp;amp;lastSeqNum=0&amp;amp;PeerInfo=10,3,4&amp;amp;ServerName=soa_server1"&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;http://10.50.XXX.XXX:16101/bea_wls_cluster_internal/psquare/p2?senderNum=3&amp;amp;lastSeqNum=0&amp;amp;PeerInfo=10,3,4&amp;amp;ServerName=soa_server1&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;'&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:487)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at weblogic.cluster.HTTPExecuteRequest.connect(HTTPExecuteRequest.java:67)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at weblogic.cluster.HTTPExecuteRequest.run(HTTPExecuteRequest.java:83)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at weblogic.work.ExecuteThread.execute(ExecuteThread.java:207)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote style="display: inline !important;"&gt;&lt;div style="display: inline !important;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;strong&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;&lt;span style="font-family: Helvetica, Arial, sans-serif;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;at weblogic.work.ExecuteThread.run(ExecuteThread.java:176)&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;span style="letter-spacing: 0px;"&gt;So make sure that the Mutlicast address and port combination used for BAM cluster and SOA cluster is unique. There is a Multicast test utility that you can use to test communication between two instance. &lt;span style="font-size: small;"&gt;More information about the utility is available&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://download.oracle.com/docs/cd/E12840_01/wls/docs103/admin_ref/utils.html#wp1199798"&gt;here&lt;/a&gt;. Also refer&amp;nbsp;&lt;a href="http://download.oracle.com/docs/cd/E11035_01/wls100/cluster/multicast_configuration.html"&gt;this&lt;/a&gt;&amp;nbsp;to troubleshoot Multicast configuration.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div style="display: inline !important;"&gt;&lt;span style="font-weight: normal; font-family: 'andale mono', times; font-size: small;"&gt;&lt;strong&gt;&lt;span style="line-height: 13px;"&gt;&lt;span style="font-weight: normal;"&gt;export CLASSPATH=${CLASSPATH}:[bea_home]/server/lib/weblogic.jar&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="display: inline !important;"&gt;&lt;span style="line-height: 13px; font-family: 'andale mono', times; font-size: small;"&gt;&lt;span style="line-height: 13px;"&gt;&lt;span style="font-weight: normal;"&gt;On&amp;nbsp;&amp;nbsp;Machine A:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="display: inline !important;"&gt;&lt;span style="line-height: 13px; font-family: 'andale mono', times; font-size: small;"&gt;&lt;span style="line-height: 13px;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="line-height: 13px; font-family: 'andale mono', times; font-size: small;"&gt;java utils.MulticastTest -A [multicast address] -P [multicast port] -N TestServer1&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span style="line-height: 13px; font-family: 'andale mono', times; font-size: small;"&gt;On Machine B:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="line-height: 13px; font-family: 'andale mono', times; font-size: small;"&gt;&lt;span style="font-weight: normal;"&gt;java utils.MulticastTest -A [multicast address] -P [multicast port] -N TestServer2&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Andale Mono';"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="display: inline !important;"&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; display: inline !important; margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; display: inline !important; margin: 0px;"&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;span style="letter-spacing: 0px;"&gt;Hope this helps!.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="display: inline !important;"&gt;&lt;p style="font: normal normal normal 12px/normal Verdana; display: inline !important; margin: 0px;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;strong&gt;&lt;span style="font-family: verdana, geneva;"&gt;&lt;span style="letter-spacing: 0px;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&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/19518284-3398658744809993126?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/3398658744809993126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=3398658744809993126&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3398658744809993126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3398658744809993126'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2011/07/soa-composite-deployment-oracle-soa.html' title='SOA Composite deployment - Oracle SOA Suite'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-6405593460650783353</id><published>2011-04-20T13:13:00.001-05:00</published><updated>2011-04-20T14:33:09.595-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osb'/><category scheme='http://www.blogger.com/atom/ns#' term='service bus'/><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><category scheme='http://www.blogger.com/atom/ns#' term='oepe'/><title type='text'>OSB Project Structure</title><content type='html'>&lt;p&gt;I am doing some development with Oracle Service Bus (OSB). The primary goal is to mediate web services using OSB. Oracle does provide set of eclipse plugins to develop OSB configuration - OEPE suite. One of question that I wanted answer was what will be a good project structure to organize various components of OSB configuration. &lt;/p&gt;&lt;p&gt;Typically, OEPE plugins gives two eclipse project templates:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Oracle Service Bus Configuration Project&lt;/li&gt;&lt;li&gt;Oracle Service Bus Project&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;OSB Config project is the top level project which can include various OSB Project. A minimal OSB project includes components like business service, proxy service and WSDL. It is important to come up with a good project structure since the component shows up as is on sbconsole. You probably don't want to see all the components at same level. &lt;/p&gt;&lt;p&gt;After this exercise, I ended up with following structure of the project that I wanted to share. So here it is,&lt;/p&gt;&lt;p class=""&gt;&lt;a href="https://lh4.googleusercontent.com/_Ij0FyB8Wu5Q/Ta8fTrs-sdI/AAAAAAAAAV0/sUnx7TZiUXM/ScreenClip.png" target="_blank"&gt;&lt;img src="https:/lh4.googleusercontent.com/_Ij0FyB8Wu5Q/Ta8fTrs-sdI/AAAAAAAAAV0/sUnx7TZiUXM/s500/ScreenClip.png" id="blogsy-1303327874771.2546" class="aligncenter" alt="" width="323" height="388"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The top level project - OSB Config Project - represents a business domain. So OSB configuration of all services serving a particular domain goes under that umbrella. Individual OSB Project contains mediation component for a given physical service. I used folders to group business and proxy services to allow for multiple proxy services for a given business service. Using this structure it becomes easy to manage configuration using sbconsole.&lt;/p&gt;&lt;p&gt;I ended up using the ant build script and import/export WLST script by tweaking the ones given as part of this book - &lt;a href="http://www.amazon.com/Definitive-Guide-SOA-Service-Experts/dp/1430210575/ref=sr_1_2?ie=UTF8&amp;s=books&amp;qid=1303324076&amp;sr=8-2" target="_blank" title=""&gt;The definitive guide to SOA&lt;/a&gt;. The build script can export configuration from local server or workspace. Import deploys it to the target server. The import/export script also takes care of  variables that changes from environment to environment. OSB has a features to create customization XMLs. You can create customization XML per environment and run it post configuration package deployment. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-6405593460650783353?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/6405593460650783353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=6405593460650783353&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6405593460650783353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6405593460650783353'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2011/04/osb-project-structure.html' title='OSB Project Structure'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-5377468932606972946</id><published>2011-01-23T23:18:00.001-06:00</published><updated>2011-01-23T23:18:27.359-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><category scheme='http://www.blogger.com/atom/ns#' term='rss'/><title type='text'>Using Clojure to work with RSS feeds</title><content type='html'>As I mentioned in my last blog entry, I am trying to learn Clojure. I think it is an interesting challenge to internalize new thinking paradigm. So following entry/code is an attempt to learn the paradigms of the language. Drop a comment, if you have any suggestion.&lt;br /&gt;&lt;br /&gt;I found that, while trying to learn new language, one of the challenge is to find interesting practice problem to solve. The practice problem which helps you understand the strength of the language. I think one such problem space Clojure's application would be interesting is parsing and data crunching.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Problem&lt;/span&gt;&lt;br /&gt;So the problem I picked is a simple one. I heavily use google reader and for that matter most of my web reading happens as part subscribed RSS feeds. I find myself manually filtering the feed list to suite my interest at the time. This exercise creates parser for RSS feed. This parser creates Clojure records based data structure. Once you have all the feed represented in records structure you can write variety of functions to filter the feed or even apply intelligent web algorithms.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Organization of Code&lt;/span&gt;&lt;br /&gt;I am looking for a good way to organize code in clojure. Just like Java packages, clojure has namespaces. But I have still not found a good way to organize clojure functions into files/namespaces. For now, I chose to create namespace per domain.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;rss.data.clj - Define records data structure and parser&lt;/li&gt;&lt;li&gt;rss.feed.clj - Defines functions to get feeds&lt;/li&gt;&lt;li&gt;rss.stat.clj - Defines functions to filter feeds (and may be some statistical algorithms)&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;data.clj&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: clojure"&gt;&lt;br /&gt;(ns rss.data&lt;br /&gt;  (:require [clojure.xml :as xml])&lt;br /&gt;  (:import  [java.io ByteArrayInputStream]))&lt;br /&gt;&lt;br /&gt;(defrecord rss-channel [title description link lastbuilddate pubdate items])&lt;br /&gt;(defrecord rss-item [title description link guid pubdate])&lt;br /&gt;&lt;br /&gt;(defn create-rss-channel [map items]&lt;br /&gt;  (let [title (:title map)&lt;br /&gt;        pubDate (:pubDate map)&lt;br /&gt;        description (:description map)&lt;br /&gt;        link (:link map)&lt;br /&gt;        lastBuildDate (:lastBuildDate map)]&lt;br /&gt;    (rss-channel. title description link lastBuildDate pubDate items)))&lt;br /&gt;&lt;br /&gt;(defn create-item [item-data]&lt;br /&gt;  (let [description (:description item-data)&lt;br /&gt;        pubDate (:pubDate item-data)&lt;br /&gt;        guid (:guid item-data)&lt;br /&gt;        link (:link item-data)&lt;br /&gt;        title (:title item-data)&lt;br /&gt;        ]&lt;br /&gt;    (rss-item. title description link guid pubDate)))&lt;br /&gt;&lt;br /&gt;(defn parse-item [item-data]&lt;br /&gt;  (create-item (zipmap (map :tag item-data) (map :content item-data))))&lt;br /&gt;&lt;br /&gt;(defn parse-items [items-data]&lt;br /&gt;  (map parse-item items-data))&lt;br /&gt;&lt;br /&gt;(defn parse-channel [channel-content]&lt;br /&gt;  (loop [x (:content channel-content)]&lt;br /&gt;    (create-rss-channel&lt;br /&gt;      (into {} (filter #(not (= :item (key %))) (zipmap (map :tag x) (map :content x))))&lt;br /&gt;      (parse-items (map :content (into [] (filter #(= :item (:tag %)) x)))))&lt;br /&gt;      ))&lt;br /&gt;&lt;br /&gt;(defn parse-rss [rss]&lt;br /&gt;  (let [rss-data (ByteArrayInputStream. (.getBytes rss "UTF-8"))]&lt;br /&gt;  (for [x (xml-seq (xml/parse rss-data))&lt;br /&gt;        :when (= :rss (:tag x))]&lt;br /&gt;    (map parse-channel (:content x)))))&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;feed.clj&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: clojure"&gt;(ns rss.feed&lt;br /&gt;  (:require [clj-http.client :as client]))&lt;br /&gt;&lt;br /&gt;(defn get-feed [url]&lt;br /&gt;  (:body (client/get url)))&lt;br /&gt;&lt;br /&gt;(defn get-feeds [urllist]&lt;br /&gt;  (pmap get-feed urllist))&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;stat.clj&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: clojure"&gt;(ns rss.stat)&lt;br /&gt;&lt;br /&gt;(def keywords ["Clojure" "Groovy" "Python"])&lt;br /&gt;&lt;br /&gt;(defn find-items [rss-item-list keyword]&lt;br /&gt;  (filter #(.contains (first (:title %)) keyword) (flatten rss-item-list)))&lt;br /&gt;&lt;br /&gt;(defn find-items-keywords [rss-item-list keyword-list]&lt;br /&gt;  (flatten (map #(find-items rss-item-list %) keyword-list)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Trying Delicious RSS&lt;br /&gt;&lt;/span&gt;Let's use RSS feed published by delicious.com. All RSS feed can found here. Let's use the feed popular which got has tag "programming"&lt;span style="font-weight: bold;"&gt;. (&lt;/span&gt;http://feeds.delicious.com/v2/rss/popular/programming)&lt;br /&gt;&lt;pre class="brush: clojure"&gt;&lt;br /&gt;user=&amp;gt; (rss.stat/find-items-keywords (map :items (flatten (rss.data/parse-rss (rss.feed/get-feed "http://feeds.delicious.com/v2/rss/popular/programming")))) ["Clojure" "Python" "Groovy"])&lt;br /&gt;(#:rss.data.rss-item{:title ["Hidden features of Python - Stack Overflow"], :description nil, :link ["http://stackoverflow.com/questions/101268/hidden-features-of-python/102062"], :guid ["http://www.delicious.com/url/16bbee33bbf4f6a03448058c5fd9f461#thaiyoshi"], :pubdate ["Sun, 23 Jan 2011 16:53:58 +0000"]} &lt;br /&gt;#:rss.data.rss-item{:title ["Writing Forwards Compatible Python Code | Armin Ronacher's Thoughts and Writings"], :description nil, :link ["http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/"], :guid ["http://www.delicious.com/url/c6fb2679bca6c193a41d92513f7edca1#papaeye"], :pubdate ["Sat, 22 Jan 2011 16:09:10 +0000"]})&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;This one only had few links. Let's try one which has lots of items. (http://feeds.delicious.com/v2/rss/tag/programming?count=100)&lt;br /&gt;&lt;pre class="brush: clojure"&gt;&lt;br /&gt;user=&amp;gt; (rss.stat/find-items-keywords (map :items (flatten (rss.data/parse-rss (rss.feed/get-feed "http://feeds.delicious.com/v2/rss/tag/programming?count=100")))) ["Clojure" "Python" "Groovy"])&lt;br /&gt;&lt;br /&gt;(#:rss.data.rss-item{:title ["The Evolution of a Python Programmer : Aleks' Domain"], :description nil, :link ["http://metaleks.net/programming/the-evolution-of-a-python-programmer"], :guid ["http://www.delicious.com/url/15311aafa2207da0ffc770903091ccea#tsung"], :pubdate ["Mon, 24 Jan 2011 02:44:19 +0000"]} &lt;br /&gt;#:rss.data.rss-item{:title ["Hidden features of Python - Stack Overflow"], :description nil, :link ["http://stackoverflow.com/questions/101268/hidden-features-of-python/102062"], :guid ["http://www.delicious.com/url/16bbee33bbf4f6a03448058c5fd9f461#adharmad"], :pubdate ["Mon, 24 Jan 2011 02:43:07 +0000"]} &lt;br /&gt;#:rss.data.rss-item{:title ["PySCeS: the Python Simulator for Cellular Systems"], :description nil, :link ["http://pysces.sourceforge.net/index.html"], :guid ["http://www.delicious.com/url/40e012b894d62cd8cb9ba6b95855b868#tiguco"], :pubdate ["Mon, 24 Jan 2011 02:39:24 +0000"]} &lt;br /&gt;#:rss.data.rss-item{:title ["Hidden features of Python - Stack Overflow"], :description nil, :link ["http://stackoverflow.com/questions/101268/hidden-features-of-python/102062"], :guid ["http://www.delicious.com/url/16bbee33bbf4f6a03448058c5fd9f461#lonstile"], :pubdate ["Mon, 24 Jan 2011 02:24:25 +0000"]} &lt;br /&gt;&lt;/pre&gt;Source Code available at GitHub (&lt;a href="https://github.com/kartikshah/rss-feeder"&gt;https://github.com/kartikshah/rss-feeder&lt;/a&gt;)&lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-5377468932606972946?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/5377468932606972946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=5377468932606972946&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/5377468932606972946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/5377468932606972946'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2011/01/using-clojure-to-work-with-rss-feeds.html' title='Using Clojure to work with RSS feeds'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-1261262574066736582</id><published>2010-12-11T22:26:00.001-06:00</published><updated>2012-01-16T22:14:08.767-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compojure'/><category scheme='http://www.blogger.com/atom/ns#' term='leiningen'/><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>How-To - IntelliJ Idea for Clojure/Compojure on Google App Engine</title><content type='html'>&lt;a href="http://strangeloop2010.com/"&gt;StrangeLoop&lt;/a&gt; conference really spiked my interest in learning &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;. I wanted to find a way to do web development using &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;. So this entry is primarily a how-to on setup of IntelliJ Idea to do Clojure using Compojure web framework, Leiningen build tool and Google App Engine deployment environment. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 1: Download Leiningen&lt;/span&gt;&lt;br /&gt;Download &lt;a href="https://github.com/technomancy/leiningen#readme"&gt;Leiningen&lt;/a&gt; script file and follow instruction to put it in PATH. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 2: Install "La Clojure" and "Leiningen" plugin for IntelliJ Idea. &lt;/span&gt;&lt;br /&gt;To do this go to Preferences -&amp;gt; Plugins. Go to "Available" Tab&lt;br /&gt;&lt;img src="http://kartikshah.com/images/compojure-gae-1.png" style="width: 662px; height: 459px;" title="La Clojure and Leiningen Plugin" alt="compojure-gae-1.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 3: Setup Leiningen plugin properties&lt;/span&gt;&lt;br /&gt;To setup Leiningen plugin properties in IntelliJ click on Preferences -&amp;gt; Leiningen and give the path to the executable. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 4: Create project template&lt;/span&gt;&lt;br /&gt;Now with the installation complete, we are ready to create a new project. For now the project creation is done outside IntelliJ Idea using Lein on command line. This is the only step done outside the IntelliJ Idea. Choose the folder structure where your IntelliJ workspace is. &lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $ lein new gae-cmpjr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Created new project in: gae-cmpjr&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can see that Lein created project folder structure. In the project root it created a project.clj file used by Leiningen. Under src folder, it also created default namespace by the name of the project and created a core.clj file under it. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 5: Create project IntelliJ&lt;/span&gt;&lt;br /&gt;Let's create IntelliJ Project, even though project structure exists pick the same folder path that you selected in step 4. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;File -&amp;gt; Project New... and select project from scratch&lt;/li&gt;&lt;li&gt;Select both GAE and Clojure. Provide the path to the appengine sdk&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://kartikshah.com/images/compojure-gae-2.png" style="width: 618px; height: 518px;" title="IntelliJ Setup " alt="compojure-gae-2.png" /&gt;&lt;br /&gt;&lt;br /&gt;Now basic setup for the project is done. You can browse the project files using IntelliJ. (Biggest benefit of La Clojure is it auto-inserts and matches brackets for very "brackety language" :-)) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 6: Setup Leiningen to run from IntelliJ&lt;/span&gt;&lt;br /&gt;To setup Leiningen from IntelliJ, click on Leiningen tool window. (Window -&amp;gt; Tool Windows -&amp;gt; Leiningen) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 7: Setup web development libraries&lt;/span&gt;&lt;br /&gt;Setup the project to include Compojure and Ring libraries for development. &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;project.clj&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;(defproject gae-cmpjr "1.0.0-SNAPSHOT"&lt;br /&gt;&amp;nbsp; :description "Example for Compojure on GAE using IntelliJ"&lt;br /&gt;&amp;nbsp; :namespaces [gae-cmpjr.core] &lt;br /&gt;&amp;nbsp; :dependencies [[compojure "0.4.0-SNAPSHOT"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ring/ring-servlet "0.2.1"]]&lt;br /&gt;&amp;nbsp; :dev-dependencies [[leiningen/lein-swank "1.2.0-SNAPSHOT"]]&lt;br /&gt;&amp;nbsp; :compile-path "web/WEB-INF/classes"&lt;br /&gt;&amp;nbsp; :library-path "web/WEB-INF/lib")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;core.clj&lt;/span&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;(ns gae-cmpjr.core&lt;br /&gt;&amp;nbsp; (:gen-class :extends javax.servlet.http.HttpServlet)&lt;br /&gt;&amp;nbsp; (:use compojure.core&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ring.util.servlet)&lt;br /&gt;&amp;nbsp; (:require [compojure.route :as route]))&lt;br /&gt;&lt;br /&gt;(defroutes hello&lt;br /&gt;&amp;nbsp; (GET "/" [] "&amp;lt;h1&amp;gt;Hello World Wide Web!&amp;lt;/h1&amp;gt;")&lt;br /&gt;&amp;nbsp; (route/not-found "Page not found"))&lt;br /&gt;&lt;br /&gt;(defservice hello)&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Step 8:&amp;nbsp; GAE setup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;web.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;web-app xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xsi:schemaLocation="http://java.sun.com/xml/ns/javaee&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; version="2.5"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;display-name&amp;gt;Compojure on GAE using IntelliJ&amp;lt;/display-name&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;servlet&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;servlet-name&amp;gt;hello&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;servlet-class&amp;gt;gae_cmpjr.core&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;servlet-name&amp;gt;hello&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;/&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;appengine-web.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;appengine-web-app xmlns="http://appengine.google.com/ns/1.0"&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;application&amp;gt;compgae&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;version&amp;gt;v0-2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/appengine-web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Step 9: Compile and Build war &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;From the Leiningen Tool window in Idea run following commands.&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;pre name="code" class="xml"&gt;lein clean&lt;br /&gt;lein deps &lt;br /&gt;lein compile &lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 10: Run locally &lt;/span&gt;&lt;br /&gt;To locally run click on already create "Run Configuration" &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 11: To upload application to appengine&lt;/span&gt;&lt;br /&gt;Tools -&amp;gt; Upload Appengine application &lt;br /&gt;&lt;img src="http://kartikshah.com/images/compojure-gae-4.png" style="width: 349px; height: 245px;" title="Sample Run" alt="compojure-gae-4.png" /&gt;&lt;br /&gt;&lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-1261262574066736582?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/1261262574066736582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=1261262574066736582&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/1261262574066736582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/1261262574066736582'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/12/how-to-intellij-idea-for.html' title='How-To - IntelliJ Idea for Clojure/Compojure on Google App Engine'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-8950846180986694124</id><published>2010-09-25T23:11:00.001-05:00</published><updated>2010-09-25T23:11:32.258-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gep3'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='dsl'/><title type='text'>Revisiting JMX DSL with Groovy GEP3</title><content type='html'>In one of the &lt;a href="http://blog.kartikshah.info/2010/02/groovy-dsl-jmx-reporting.html"&gt;previous blog post&lt;/a&gt;, I experimented with a &lt;a href="http://blog.kartikshah.info/2010/02/groovy-dsl-jmx-reporting.html"&gt;sample DSL for JMX reporting using Jfree chart&lt;/a&gt;. Groovy 1.8.2 (Beta) has introduced command expression language. This &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GEP+3+-+Command+Expression+based+DSL"&gt;GEP-3&lt;/a&gt; essentially allows you to create command expression language which can further simplify language of DSL. The primary use of this is to aid in writing impromptu scripts to visually demo various MBean values. In this example we will see bar charts for module processing time for all web modules. &lt;br /&gt;&lt;br /&gt;Command expression language allows you to alternate method name and parameter for even number of argument&lt;br /&gt;e.g. &lt;br /&gt;foo a1 a2 a3 a4 a5. Foo(a1).a2(a3).a4(a5)&lt;br /&gt;You can find more example and explanation on &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GEP+3+-+Command+Expression+based+DSL"&gt;GEP-3 page&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Revisiting &lt;a href="http://blog.kartikshah.info/2010/02/groovy-dsl-jmx-reporting.html"&gt;JMX example&lt;/a&gt; so that I can simplify the language as &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;server.url "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/jmxconnector" query "jboss.web:*" filter "j2eeType=WebModule"&lt;br /&gt;def filteredModules = server.filteredModules&lt;br /&gt;&lt;br /&gt;chart.type "Bar" modules filteredModules title "Module Processing Time" width 1200 height 700 refresh 500 attributes params labels graphLabels&lt;br /&gt;chart.show()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let's look at the supporting code. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;import org.jfree.chart.ChartFactory&lt;br /&gt;import groovy.swing.SwingBuilder&lt;br /&gt;&lt;br /&gt;import org.jfree.data.category.DefaultCategoryDataset&lt;br /&gt;import org.jfree.chart.plot.PlotOrientation as Orientation&lt;br /&gt;import javax.swing.WindowConstants as WC&lt;br /&gt;import javax.management.ObjectName&lt;br /&gt;import javax.management.remote.JMXConnectorFactory&lt;br /&gt;import javax.management.remote.JMXServiceURL as JmxUrl&lt;br /&gt;import javax.naming.Context&lt;br /&gt;&lt;br /&gt;class Chart {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def chartModules&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def chartType&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def chartAttributes = {m -&amp;gt; [m.processingTime, m.path]}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def chartLabels =["Time per Webapp", "Webapp", "Time"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def chartOptions = [false, true, true]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def windowTitle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def w&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def h&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def refreshRate&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def orientation = "VERTICAL"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def dataset&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def modules(m) {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartModules = m&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def type(type) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartType = type&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def attributes(attr) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartAttributes = attr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def labels (lbls) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartLabels = lbls&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def options (opts) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartOptions = opts&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def title (title) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; windowTitle = title&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def width(width) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; w = width&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def height(height) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; h = height&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def refresh(r) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; refreshRate = r&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void show(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; switch(chartType){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; case "Bar": drawBarChart(); break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; default: break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void drawBarChart(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; calculateData()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def chart = ChartFactory.createBarChart(*chartLabels, dataset, Orientation."${orientation}", *chartOptions)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def swing = new SwingBuilder()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def frame = swing.frame(title:windowTitle, defaultCloseOperation:WC.EXIT_ON_CLOSE){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; panel(id:'canvas') {rigidArea(width:w, height:h)}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; while(true){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; calculateData()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chart.fireChartChanged()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; frame.pack()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; frame.show()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chart.draw(swing.canvas.graphics, swing.canvas.bounds)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sleep(refreshRate)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void calculateData(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def newDataset = new DefaultCategoryDataset()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; chartModules.each{ m -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; def dsCall = chartAttributes.call(m)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; newDataset.addValue dsCall[0], 0, dsCall[1]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.dataset = newDataset&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class Server {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def queryObjects&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def moduleFilter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def filteredModules&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def url(serverName){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; server = JMXConnectorFactory.connect(new JmxUrl(serverName)).MBeanServerConnection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def query (queryString) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; queryObjects = new ObjectName(queryString)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def filter (filterString) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; String[] allNames = server.queryNames(queryObjects, null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; filteredModules = allNames.findAll { name -&amp;gt; name.contains(filterString)}.collect { new GroovyMBean(server, it)}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;server = new Server()&lt;br /&gt;chart = new Chart()&lt;br /&gt;params = {m -&amp;gt; [m.processingTime, m.path]}&lt;br /&gt;graphLabels = ["Time per Webapp", "Webapp", "Time"]&lt;br /&gt;&lt;br /&gt;server.url "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/jmxconnector" query "jboss.web:*" filter "j2eeType=WebModule"&lt;br /&gt;def filteredModules = server.filteredModules&lt;br /&gt;&lt;br /&gt;chart.type "Bar" modules filteredModules title "Module Processing Time" width 1200 height 700 refresh 500 attributes params labels graphLabels&lt;br /&gt;chart.show()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Problems&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;faced&lt;/span&gt;&lt;br /&gt;For some reason with the current beta build I couldn't do arrays or closures inline. so I had to put them as separate variables. I do not think it is by design and as 1.8.X comes close to release these wrinkles will be worked out. &lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-8950846180986694124?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/8950846180986694124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=8950846180986694124&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8950846180986694124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8950846180986694124'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/09/revisiting-jmx-dsl-with-groovy-gep3.html' title='Revisiting JMX DSL with Groovy GEP3'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-800245131066444293</id><published>2010-03-31T23:46:00.001-05:00</published><updated>2012-01-16T21:35:27.729-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data-service'/><category scheme='http://www.blogger.com/atom/ns#' term='soa'/><title type='text'>Data as Service - Thoughts</title><content type='html'>I am exploring multiple ways to expose data as a service. Let's take a brief look at problem description. You have a central data repository which acts as source of truth for multiple supporting application. These supporting applications usually reads data and manipulate/transform it and do what it needs to do with it. &lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.kartikshah.com/images/data-as-a-service.png" style="margin: 0px auto 10px; display: block; text-align: center; width: 569px; height: 217px;" title="Typical Scenario" alt="data-as-a-service.png" /&gt;&lt;br /&gt;&lt;br /&gt;This is not very atypical scenario. In most of the organization you will have a central application - usually of the shelf product with specific customization. e.g. ERP systems, Billing systems, CRM systems etc. The data store supporting this application is not flexible to customization. You will also find supporting applications for custom needs of organization to use the central data store. In usual scenarios this application will be handling this via direct read from central data store - potentially giving way to duplication of effort to manage this objects. &lt;br /&gt;&lt;br /&gt;These problems have been solved in multiple ways. &lt;br /&gt;&lt;ol&gt;&lt;li&gt;Allow each individual supporting application to access data directly or indirectly through data warehouses &lt;/li&gt;&lt;li&gt;Expose the catalog of finely-tuned queries expose by the supporting application as web services. &lt;/li&gt;&lt;li&gt;Define organization wide data directory containing well defined business entities/objects and expose web services to retrieve defined entities. &lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;"&gt;Types of Services &lt;/span&gt;&lt;br style="font-weight: bold;" /&gt;We can classify this data services in multiple categories&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Data-Read Services&lt;/span&gt; - These are plain and simple data read or data lookup services. This services provide only minor transformation like column renames, etc&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Transformation Services&lt;/span&gt; - These services provide some transformation of data. It operates on the column performs operation like truncation, concatenation, etc. &lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Filtering Services&lt;/span&gt; - These services allows opportunity to filter data based on input conditions. e.g provide active accounts, provide prospect accounts, etc. &lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Aggregation Services&lt;/span&gt; - These services provides performs certain aggregation function. e.g. sales by region, accounts by regions, etc. Though this logic could have served better purpose if kept in application, there are some performance benefits to do this in the data store layer.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Define Business Entities data dictionary&lt;/span&gt;&lt;br /&gt;First and foremost identify organization wide data dictionary for the domain. This data dictionary is the definition of entities that applications needs to use. So there is not duplication. It also reduces confusion. For example, an entity named BillingAccount will mean the billing account for any application using it. This solves a larger problem, in the scenario where the supporting applications use the data directory it defines these central entities in multiple ways. So over time the definition of the same thing becomes convoluted. e.g. account number for application A is 10 digits and same for application b is first 8 digits of that. This results in duplication of data that can not inter operate. Defining a central data dictionary and allowing exchange of that in that contract helps avoid this problem. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Logical Representation&lt;/span&gt;&lt;br /&gt;In most scenario the data store that comes bundled with the product is really generic so that product can be customized to different business. eg. ACCTPF having fields like ACCTPFNO, ACCTPFHONO, etc. One side effect can be seen on naming convention of entities and its properties. They are wierdly named and does not make any sense without actually looking at product documentation. My take is that some naming transformation is required. This can be done by "select as" queries or actually overlaying a logical data model on top of the existing one. Of course after performance consideration. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Expose as Web Service&lt;/span&gt;&lt;br /&gt;Once you have the logical representation any of following two options can be followed &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Write Select queries and expose them as either SOAP/REST web services &lt;/li&gt;&lt;li&gt;If select queries does not provide necessary transformation/aggregation, write db procedures and expose them as a service.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;One of the sub variation of this scenario is to use DB specific data structures. (In case of Oracle, use oracle's user defined types). Performance consideration is essential because remember these services may very well be the most atomic activity overarching application will perform and it is essential that each data read is trivial and inexpensive. &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;Just some thoughts...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-800245131066444293?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/800245131066444293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=800245131066444293&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/800245131066444293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/800245131066444293'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/03/data-as-service-thoughts.html' title='Data as Service - Thoughts'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-4574972394943063954</id><published>2010-03-16T23:05:00.001-05:00</published><updated>2010-03-16T23:40:53.998-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='outlook'/><category scheme='http://www.blogger.com/atom/ns#' term='scriptom'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='activex'/><title type='text'>Using Groovy Scriptom to report on Outlook</title><content type='html'>As with most work places, I use MS Outlook Calendar at work for meetings, calendars, etc. With Outlook 2007 you have capability to categorize each meeting/time block that you have on your calendar. So you can classify each meeting as either design, architecture, learning, recurring, etc. Using &lt;a href="http://groovy.codehaus.org/COM+Scripting"&gt;Groovy Scriptom&lt;/a&gt; module you can do what you would usually do using VBScript. Scriptom allows you to use ActiveX windows components from Groovy. Needless to say this will only work on windows platform. &lt;br /&gt;&lt;br /&gt;I used the &lt;a href="http://groovy.codehaus.org/COM+Scripting"&gt;scriptom&lt;/a&gt; to report on how I am spending my time. (ah.. have to fill those time sheet) Using Swingbuilder and JFreeChart, I threw in this simple script. You will need to setup dependency exactly as described on the &lt;a href="http://groovy.codehaus.org/COM+Scripting#COMScripting-AddingScriptomtoaMavenProject"&gt;help page here&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;import org.codehaus.groovy.scriptom.ActiveXObject&lt;br /&gt;import org.jfree.chart.ChartFactory &lt;br /&gt;import javax.swing.WindowConstants as WC&lt;br /&gt;&lt;br /&gt;def outlook = new ActiveXObject("Outlook.Application")&lt;br /&gt;def namespace = outlook.GetNamespace("MAPI")&lt;br /&gt;def calFolder = namespace.GetDefaultFolder(9)&lt;br /&gt;def myItems = calFolder.Items&lt;br /&gt;&lt;br /&gt;def today = new Date()&lt;br /&gt;startWeek = today - 7 &lt;br /&gt;endWeek = today + 7&lt;br /&gt;def categoryMap = [:]&lt;br /&gt;&lt;br /&gt;for (i in 1..myItems.Count.value) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def currentMeeting = myItems.Item(i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (currentMeeting.Start &amp;gt;= startWeek &amp;amp;&amp;amp; currentMeeting.Start &amp;lt;= endWeek) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println "Subject: " + currentMeeting.Subject.value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println "Category: " + currentMeeting.Categories&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println "Duration: " + currentMeeting.Duration.value&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; category = currentMeeting.Categories&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; durationValue = currentMeeting.Duration.value&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def value = categoryMap.get(category)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value = value?value:0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def newValue = value + durationValue&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; categoryMap.put(category,newValue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def swing = new groovy.swing.SwingBuilder()&lt;br /&gt;def titleString = 'Time Outlook: ' + String.format('%tm/%&amp;lt;td/%&amp;lt;tY', startWeek) + "-" + String.format('%tm/%&amp;lt;td/%&amp;lt;tY', endWeek)&lt;br /&gt;def frame = swing.frame(title:titleString,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defaultCloseOperation:WC.EXIT_ON_CLOSE,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size:[800,600], locationRelativeTo: null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; borderLayout()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel(id:'canvas') { rigidArea(width:700, height:500) }&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;def bounds = new java.awt.Rectangle(0,0, 700,500).bounds&lt;br /&gt;def piedata = new org.jfree.data.general.DefaultPieDataset()&lt;br /&gt;for(entry in categoryMap)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; piedata.setValue entry.key + " = " + entry.value, entry.value&lt;br /&gt;}&lt;br /&gt;def options = [false, true, false]&lt;br /&gt;def chart = ChartFactory.createPieChart(titleString, piedata, *options)&lt;br /&gt;chart.backgroundPaint = java.awt.Color.white&lt;br /&gt;frame.pack()&lt;br /&gt;frame.show()&lt;br /&gt;chart.draw(swing.canvas.graphics, bounds)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simple enough script... It gets the ActiveXObject for Outlook application. Then from namespace it gets calendarFolder (constant 9). You can find out more about &lt;a href="http://msdn.microsoft.com/en-us/library/aa831898%28office.10%29.aspx"&gt;constant here&lt;/a&gt;. calFolder contains all the meeting appointmentItems. Once you get to the appointmentItem you can ask for the properties using groovy dot-notation. &lt;br /&gt;&lt;br /&gt;Here is the snapshot of the output&lt;br /&gt;&lt;br /&gt;&lt;img src="http://kartikshah.info/images/groovy-scriptom-outlook.png" style="width: 530px; height: 393px;" title="Groovy Scriptom " alt="groovy-scriptom-outlook.png" /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-4574972394943063954?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/4574972394943063954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=4574972394943063954&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4574972394943063954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4574972394943063954'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/03/using-groovy-scriptom-to-report-on.html' title='Using Groovy Scriptom to report on Outlook'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-1150295499101921974</id><published>2010-02-28T23:59:00.001-06:00</published><updated>2010-03-01T00:02:47.331-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ast-transformation'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='dsl'/><title type='text'>Revisit Jmx Groovy DSL - Using AstTransformation</title><content type='html'>In the &lt;a href="http://blog.kartikshah.info/2010/02/groovy-dsl-jmx-reporting.html"&gt;previous blog entry&lt;/a&gt;, we created Jmx Charting DSL. Let visit some aspects of creating DSL using groovy. &lt;br /&gt;&lt;br /&gt;In the previous blog example we created DSL using &lt;a href="http://groovy.codehaus.org/api/groovy/lang/ExpandoMetaClass.html"&gt;&lt;span style="font-style: italic;"&gt;ExpandoMetaClass&lt;/span&gt;&lt;/a&gt;. Users will define the script starting with node &lt;span style="font-style: italic;"&gt;jmx&lt;/span&gt; { }. With the use of ExpandoMetaClass we added the dynamic method which in turn delegated to class JmxClosureDelegate. Here is the snippet of the code. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;static void runEngine(File dsl){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Script dslScript = new GroovyShell().parse(dsl.text)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dslScript.metaClass = createExpandoMetaClass(dslScript.class, {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExpandoMetaClass emc -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; emc.jmx = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Closure cl -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxClosureDelegate()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dslScript.run()&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;What we essentially did here:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Using GroovyShell it parses the script file passed as input. &lt;/li&gt;&lt;li&gt;Defines the ExpandoMetaClass and adds method by name "jmx" having closure as parameter. &lt;/li&gt;&lt;/ul&gt; So the script file you wrote gets a dynamic method injected into it using ExpandoMetaClass. This happens at runtime. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Getting rid of the Commas&lt;br /&gt;&lt;/span&gt;The problem with creating methods with two arguments is that you have to specify commas between them. For example, &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server "nameofserver", {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;/pre&gt;Undoubtedly commas clutter the langauge grammer. To get rid of the commas we used trick provided on Groovy users list. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;//To avoid using "," between String and Closure argument&amp;nbsp; &lt;br /&gt;&amp;nbsp; def methodMissing(String name, args) {&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [name, args[0]]&amp;nbsp; &lt;br /&gt;&amp;nbsp; }&amp;nbsp; &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Using AstTransformation&lt;/span&gt;&lt;br /&gt;Now lets explore a different possibility. You can achieve similar result using AstTransformation at compile time. The goal remains the same and that is to add method with name "jmx" with closure parameter. &lt;br /&gt;&lt;br /&gt;First we will define the annotation.&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;//import statements skipped for brevity&lt;br /&gt;@Retention(RetentionPolicy.SOURCE)&lt;br /&gt;@Target([ElementType.METHOD])&lt;br /&gt;@GroovyASTTransformationClass(["info.kartikshah.jmx.ast.JmxDslTransformation"])&lt;br /&gt;public @interface UseJmxDsl {}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Transformation Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This transformation class needs to perform two activities:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add method &lt;span style="font-style: italic;"&gt;jmx(Closure cl) &lt;/span&gt;method&lt;/li&gt;&lt;li&gt;Invoke the script method being defined&lt;/li&gt;&lt;/ul&gt;We need to generate AST statements for following snippet of code. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jmx = {&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Closure cl -&amp;gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxClosureDelegate()&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br /&gt;&lt;/pre&gt;We will use AstBuilder's buildFromSpec option to generate it. (AstBuilders added with Groovy 1.7 definitely makes generating statement structure relatively easy and clutter free. Not to mention it is also an example of DSL added to the groovy language :-) ) &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)&lt;br /&gt;class JmxDslTransformation implements ASTTransformation {&lt;br /&gt;&amp;nbsp; static int PUBLIC = 1&lt;br /&gt;&amp;nbsp; static int STATIC = 8&lt;br /&gt;&lt;br /&gt;&amp;nbsp; void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Add method jmx(Closure cl)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClassNode declaringClass = astNodes[1].declaringClass&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MethodNode jmxMethod = makeMethod()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; declaringClass.addMethod(jmxMethod)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Insert method call inside run method of the script class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MethodNode annotatedMethod = astNodes[1]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;MethodNode&amp;gt; allMethods = sourceUnit.AST?.classes*.methods.flatten()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MethodNode runMethod = allMethods.find{ MethodNode method -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; method.name == "run"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; List existingStatements = runMethod.getCode().getStatements()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; existingStatements.add(0, createMethodCall(annotatedMethod))&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Statement createMethodCall(MethodNode methodNode){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def statementAst = new AstBuilder().buildFromSpec {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methodCall {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "this"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant methodNode.name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumentList {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Statement stmt = statementAst[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stmt&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; MethodNode makeMethod() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def ast = new AstBuilder().buildFromSpec {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; method('jmx', PUBLIC | STATIC, Void.TYPE) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameters {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameter 'cl': Closure.class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exceptions {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; block {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; binary {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; property {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "cl"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant "delegate"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token "="&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constructorCall(JmxClosureDelegate.class) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumentList()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; binary {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; property {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "cl"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant "resolveStrategy"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token "="&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; property {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; classExpression Closure&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant "DELEGATE_FIRST"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methodCall {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "cl"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant "call"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumentList {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MethodNode jmxMethod = ast[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; jmxMethod&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Why use AstTransformation?&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;The question is why one would want to use AstTransformation when you can add method during runtime. For the given scenario, it is correct that you want to stick with adding method runtime. But consider scenario where you want to &lt;span style="font-weight: bold;"&gt;"redefine" meaning of Groovy's syntax&lt;/span&gt;. For example like following &lt;span style="font-weight: bold;"&gt;imaginary script&lt;/span&gt; using Statement Labels to add more readability to your DSL syntax. &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;@info.kartikshah.jmx.ast.UseJmxDsl&lt;br /&gt;runDsl () {&lt;br /&gt;&amp;nbsp; jmx {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; setup:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/jmxconnector"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; query "jboss.web:*"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; findAll "j2eeType=Servlet"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; draw:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; chart {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chartType="Bar"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; attributes={m-&amp;gt; [m.loadTime, m.objectName.find("name=([^,]*)"){it[1]}]}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; labels=["Load Time per Servlet", "Servlet", "Time"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options=[false, true, true]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; windowTitle="JBoss Servlet Processing Time"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; width=1200&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; height=700&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; orientation="HORIZONTAL"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; refreshRate=5000&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; show()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Spock Framework does similar twist by redefining meaning of existing construct. &lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;With this type of language structure you will end up defining your own &lt;span style="font-weight: bold;"&gt;set of keywords&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;supporting parser&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;few AstTransformation&lt;/span&gt; to change the meaning of existing Groovy Syntax. &lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-1150295499101921974?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/1150295499101921974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=1150295499101921974&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/1150295499101921974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/1150295499101921974'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/02/revisit-jmx-groovy-dsl-using.html' title='Revisit Jmx Groovy DSL - Using AstTransformation'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-4378577077693774861</id><published>2010-02-16T22:30:00.001-06:00</published><updated>2010-12-05T16:47:41.559-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='swingbuilder'/><category scheme='http://www.blogger.com/atom/ns#' term='jfreechart'/><category scheme='http://www.blogger.com/atom/ns#' term='jmx'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='dsl'/><title type='text'>A Groovy DSL - JMX Reporting</title><content type='html'>In &lt;a href="http://blog.kartikshah.info/2009/06/jmx-groovy-jfreechart-and-swing.html"&gt;previous blog example&lt;/a&gt;, using JFreeChart, JMX and SwingBuilder we came up with dashboard type utility. With this post we will explore how to write small DSL which will allow to report on JMX using reporting charts. The DSL will using Groovy's SwingBuilder to draw JFree Chart to report on various MBeans. This type DSL can be used to write small scripts to monitor behavioral aspect of application server (or any JMX based application).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Simple DSL&lt;/span&gt;&lt;br /&gt;First we will chart out how we want our domain language to look like. DSL syntax can be done multiple ways. It is necessary that you play with the syntax to come up with one that works for the scenario. For our example, here is the first cut that we will use. &lt;br /&gt;&lt;br /&gt;Essentially, the script reports processing time of all web modules defined on (in this example - JBoss) application server using Bar Chart.&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;jmx {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; server "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/jmxconnector" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; query "jboss.web:*" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; findAll "j2eeType=WebModule" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chart{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chartType="Bar"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; attributes={m-&amp;gt; [m.processingTime, m.path]}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; labels=["Time per Webapp", "Webapp", "Time"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options=[false, true, true]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; windowTitle="JBoss Module Processing Time"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; width=1200&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; height=700&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; refreshRate=5000&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; show()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other Use cases&lt;/span&gt;&lt;br /&gt;Target users for this DSL are system administrators who can write simple scripts to monitor and/or report on various aspects of app server instances graphically. &lt;br /&gt;&lt;br /&gt;Some other use cases for this type of DSL&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Compare Processing Time of Web Application&lt;/li&gt;&lt;li&gt;Compare Load Time of Servlets&lt;/li&gt;&lt;li&gt;Compare Response Time&lt;/li&gt;&lt;li&gt;Compare memory usage &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Compare total requests&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;DSL Engine&lt;/span&gt;&lt;br /&gt;With Groovy there are multiple ways to write domain specific language as described in &lt;a href="http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages"&gt;groovy documentation here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We will use nested closure approach. More information about &lt;a href="http://www.martinfowler.com/dslwip/NestedClosure.html"&gt;nested closure here.&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Here we use ExpandoMetaClass and series of Delegate classes to handle each closure. In the sample script above read each node (eg. jmx, server, query) as a dynamic method call with one or two arguments. For example jmx has a string argument followed by closure argument. String argument is we just store in instance variable. For closure argument we delegate the handling to separate Delegate Class. We follow the same pattern for the rest of the nested nodes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;First up Engine&lt;/span&gt;&lt;br /&gt;This is the main class for the DSL. It gets the file passed as command args and pass it to GroovyShell to create Script object. It uses ExpandoMetaClass to dynamically add methods/closure. It add adds jmx closure and sets properties for handling closure. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class JmxReportingDslEngine {&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; static main(String[] args){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(args.length != 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println("Usage: JmxReportingDslEngine &amp;lt;ScriptFileName&amp;gt;")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; runEngine(new File(args[0]))&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; static void runEngine(File dsl){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Script dslScript = new GroovyShell().parse(dsl.text)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dslScript.metaClass = createExpandoMetaClass(dslScript.class, {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExpandoMetaClass emc -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; emc.jmx = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Closure cl -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxClosureDelegate()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dslScript.run()&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; static ExpandoMetaClass createExpandoMetaClass(Class clazz, Closure cl){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExpandoMetaClass emc = new ExpandoMetaClass(clazz, false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl(emc)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; emc.initialize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return emc&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Delegates &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next up we write series of Delegate Class responsible for handling each node of the language. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JMXClosureDelegate&lt;/span&gt;&lt;br /&gt;This handles closure passed to jmxtag. It instantiates MBeanServerConnection and passes the reference down to the delegate chain. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class JmxClosureDelegate {&lt;br /&gt;  //To avoid using "," between String and Closure argument&lt;br /&gt;&amp;nbsp; def methodMissing(String name, args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [name, args[0]]&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void server(param){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def (serverUrl, cl) = param&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def server = JMXConnectorFactory.connect(new JmxUrl(serverUrl),env).MBeanServerConnection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxServerClosureDelegate(server)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;JMXServerClosureDelegate&lt;/span&gt;&lt;br /&gt;This delegate handles closure passed to server tag. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class JmxServerClosureDelegate {&lt;br /&gt;&amp;nbsp; def server&lt;br /&gt;&amp;nbsp; JmxServerClosureDelegate(server){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.server = server&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; def methodMissing(String name, args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; return [name, args[0]]&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void query(param){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def (objectName, cl) = param&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def query = new ObjectName(objectName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String[] allNames = server.queryNames(query, null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxQueryClosureDelegate(allNames, server)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;JmxQueryClosureDelegate &lt;/span&gt;&lt;br /&gt;and so on...&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class JmxQueryClosureDelegate {&lt;br /&gt;&amp;nbsp; def allNames&lt;br /&gt;&amp;nbsp; def server&lt;br /&gt;&amp;nbsp; JmxQueryClosureDelegate(allNames, server){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.allNames = allNames&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.server = server&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; def methodMissing(String name, args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [name, args[0]]&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void findAll(param){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def (filter, cl) = param&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def modules = allNames.findAll{ name -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name.contains(filter)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }.collect{ new GroovyMBean(server, it) }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new JmxFindAllClosureDelegate(modules)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;JmxFindAllClosureDelegate &lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class JmxFindAllClosureDelegate {&lt;br /&gt;&amp;nbsp; def modules&lt;br /&gt;&amp;nbsp; JmxFindAllClosureDelegate(modules){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.modules = modules&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void chart(Closure cl){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.delegate = new ChartDelegate(modules)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl.resolveStrategy = Closure.DELEGATE_FIRST&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cl()&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;ChartDelegate &lt;/span&gt;&lt;br /&gt;This class &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Creates the dataset from the MBean values&lt;/li&gt;&lt;li&gt;Creates the chart with the dataset values&lt;/li&gt;&lt;li&gt;Creates the external frame using SwingBuilder&lt;/li&gt;&lt;/ul&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class ChartDelegate {&lt;br /&gt;&lt;br /&gt;&amp;nbsp; def modules&lt;br /&gt;&amp;nbsp; def chartType&lt;br /&gt;&amp;nbsp; def attributes&lt;br /&gt;&amp;nbsp; def labels&lt;br /&gt;&amp;nbsp; def options&lt;br /&gt;&amp;nbsp; def windowTitle&lt;br /&gt;&amp;nbsp; def width&lt;br /&gt;&amp;nbsp; def height&lt;br /&gt;&amp;nbsp; def refreshRate&lt;br /&gt;&amp;nbsp; def orientation = "VERTICAL"&lt;br /&gt;&amp;nbsp; def dataset&lt;br /&gt;&amp;nbsp; ChartDelegate(modules){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.modules = modules&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void show(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch(chartType){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case "Bar": drawBarChart(); break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //TODO:Add more chart types&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; default: break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void drawBarChart(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; calculateData()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def chart = ChartFactory.createBarChart(*labels, dataset, Orientation."${orientation}", *options)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def swing = new SwingBuilder()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def frame = swing.frame(title:windowTitle, defaultCloseOperation:WC.EXIT_ON_CLOSE){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel(id:'canvas') {rigidArea(width:width, height:height)}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while(true){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; calculateData()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chart.fireChartChanged()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; frame.pack()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; frame.show()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chart.draw(swing.canvas.graphics, swing.canvas.bounds)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sleep(refreshRate)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; void calculateData(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def newDataset = new DefaultCategoryDataset()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; modules.each{ m -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def dsCall = attributes.call(m)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newDataset.addValue dsCall[0], 0, dsCall[1]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.dataset = newDataset&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Output&lt;br /&gt;&lt;/span&gt;Let's run and look at sample output... &lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.kartikshah.info/images/jmx-web-app-processing-time.jpg" style="width: 553px; height: 333px;" title="Web App Processing Time" alt="web-app-processing-time" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.kartikshah.info/images/jmx-web-app-processing-time.jpg"&gt;Click here for bigger images&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;Here is another script for Servlet Load Time &lt;br /&gt;&lt;br /&gt;This one uses some intermediate groovy knowledge with attributes param taking a closure. It allows user to perform transformation on the MBean parameters. Below in the script it performs operates on long objectName attribute to get servlet name parameter. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;jmx {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; server "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/jmxconnector" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; query "jboss.web:*" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; findAll "j2eeType=Servlet" {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chart{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; chartType="Bar"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; attributes={m-&amp;gt; [m.loadTime, m.objectName.find("name=([^,]*)"){it[1]}]}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; labels=["Load Time per Servlet", "Servlet", "Time"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options=[false, true, true]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; windowTitle="JBoss Servlet Processing Time"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; width=1200&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; height=700&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; orientation="HORIZONTAL"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; refreshRate=5000&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; show()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;and here is the output...&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.kartikshah.info/images/jmx-servlet-load-time.png" style="width: 554px; height: 334px;" title="Servlet Load Time" alt="servlet-load-time" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.kartikshah.info/images/jmx-servlet-load-time.png"&gt;Click here for bigger image&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Further you can, &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add different type of chart support to the DSL - Bar, XY, trending, etc&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use/Extend to work with different application server and/or application&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Complete source code can be found at &lt;a href="http://github.com/kartikshah/jmx-dsl"&gt;http://github.com/kartikshah/jmx-dsl&lt;/a&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-4378577077693774861?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/4378577077693774861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=4378577077693774861&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4378577077693774861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4378577077693774861'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/02/groovy-dsl-jmx-reporting.html' title='A Groovy DSL - JMX Reporting'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-2544990562223228398</id><published>2010-02-05T21:35:00.001-06:00</published><updated>2010-12-05T16:48:38.948-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='google-collection'/><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='collections'/><title type='text'>Exploring Google Collections - Part 2</title><content type='html'>&lt;a href="http://blog.kartikshah.info/2010/01/exploring-google-collections-part-1.html"&gt;In Part 1&lt;/a&gt;, we focused on few classes of google collection. Here in part 2, we will expand on the simple scenario and work on DOM like tree structure scenario. &lt;br /&gt;&lt;br /&gt;Consider a scenario of an external API provided by vendor. The API had tree like data structure, described by diagram below. &lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.kartikshah.info/images/node-component.gif" style="margin: 0pt auto 10px; display: block; text-align: center; width: 742px; height: 267px;" title="NodeComponent" alt="Node Component Diagram" /&gt;&lt;br /&gt;Now the problem was that the main data structure part of external API was POJO. Though it was a tree structure it did not provide any operations for traversal or find operations. Here is the watered down version of the component. &lt;br /&gt;&lt;pre name="code" class="java"&gt;public class NodeComponent {&lt;br /&gt;    private String name;&lt;br /&gt;    private List&amp;lt;NodeComponent&amp;gt; children;&lt;br /&gt;    private Map&amp;lt;String, String&amp;gt; attributes;&lt;br /&gt;&lt;br /&gt;    public NodeComponent(String name)&lt;br /&gt;    {&lt;br /&gt;        this.name = name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Getters and Setters omitted for brevity&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Let's see how google collection can be used to provide nice searcher methods. Consider following use cases: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Find child nodes based on node name&lt;/li&gt;&lt;li&gt;Find child nodes based on attribute name and value&lt;/li&gt;&lt;li&gt;Find child nodes on composite criteria of node name and attribute name and value&lt;/li&gt;&lt;/ul&gt;Lets implement cases using google collections.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Case 1: Find child nodes based on node name&lt;/span&gt;&lt;br /&gt;First we will define &lt;span style="font-style: italic;"&gt;NodeNameCriteria&lt;/span&gt; implementing &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicate.html"&gt;Predicate&lt;/a&gt; interface&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class NodeNameCriteria implements Predicate&amp;lt;NodeComponent&amp;gt;&lt;br /&gt;{&lt;br /&gt;    private String nameCriteria;&lt;br /&gt;&lt;br /&gt;    public NodeNameCriteria(String nameCriteria)&lt;br /&gt;    {&lt;br /&gt;        this.nameCriteria = nameCriteria;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public boolean apply(NodeComponent node) &lt;br /&gt;    {&lt;br /&gt;        return node.getName().equals(nameCriteria);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Further, define &lt;span style="font-style: italic;"&gt;NodeSearcher&lt;/span&gt; class which will represent current node and will provide all these helper methods &lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class NodeSearcher&lt;br /&gt;{&lt;br /&gt;    private NodeComponent currentNode;&lt;br /&gt;&lt;br /&gt;    public NodeSearcher(NodeComponent currentNode)&lt;br /&gt;    {&lt;br /&gt;        this.currentNode = currentNode;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Collection&amp;lt;NodeComponent&amp;gt; findChildrenByNodeName(String name)&lt;br /&gt;    {&lt;br /&gt;        return Collections2.filter(currentNode.getChildren(),new NodeNameCriteria(name));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Case 2: Find child nodes based on attribute name and value&lt;/span&gt;&lt;br /&gt;Similar to first approach, this requires creating a Predicate implementation, let's name it &lt;span style="font-style: italic;"&gt;AttributeNameValueCriteria&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class AttributeNameValueCriteria implements Predicate&amp;lt;NodeComponent&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String nameCriteria;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String valueCriteria;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public AttributeNameValueCriteria(String nameCriteria, String valueCriteria)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.nameCriteria = nameCriteria;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.valueCriteria = valueCriteria;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean apply(NodeComponent component)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set&amp;lt;Map.Entry&amp;lt;String, String&amp;gt;&amp;gt; entrySet = component.getAttributes().entrySet();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set&amp;lt;Map.Entry&amp;lt;String, String&amp;gt;&amp;gt; matchedAttrSet = Sets.filter(entrySet, new Predicate&amp;lt;Map.Entry&amp;lt;String, String&amp;gt;&amp;gt;(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean apply(Map.Entry&amp;lt;String, String&amp;gt; entry) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return nameCriteria.equals(entry.getKey()) &amp;amp;&amp;amp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; valueCriteria.equals(entry.getValue());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return matchedAttrSet != null &amp;amp;&amp;amp; !matchedAttrSet.isEmpty();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Case 3: Find child nodes on composite criteria of node name and attribute name and value&lt;/span&gt;&lt;br /&gt;So far so good but the real benefit of defining the Predicate comes with the third case. In this case what is needed is to define a criteria which is composition of NodeNameCriteria and AttributeNameValueCriteria. We don't need to define third criteria implementation. Instead we will use Predicates compose method. Add following implmentation of findChildrenByNodeNameAndAttributeNameValue to NodeSearcher&lt;br /&gt;&lt;pre name="code" class="java"&gt;public Collection&amp;lt;NodeComponent&amp;gt; findChildrenByNodeNameAndAttributeNameValue(String nodeName, String attrName, String attrValue)&lt;br /&gt;{&lt;br /&gt;     Predicate&amp;lt;NodeComponent&amp;gt; compositePredicate = Predicates.and(new NodeNameCriteria(nodeName),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new AttributeNameValueCriteria(attrName, attrValue));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Collections2.filter(currentNode.getChildren(), compositePredicate);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In simpler approach, one would have defined filter criteria as condition of if loop. But with implementing them as &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicate.html"&gt;Predicate&lt;/a&gt; implementation, you can reuse criteria implementation and mix and match with help of following &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicates.html"&gt;Predicates&lt;/a&gt; function and and or methods.&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-2544990562223228398?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/2544990562223228398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=2544990562223228398&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/2544990562223228398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/2544990562223228398'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/02/exploring-google-collections-part-2_05.html' title='Exploring Google Collections - Part 2'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-6047792969692819091</id><published>2010-01-31T22:49:00.001-06:00</published><updated>2010-12-05T16:48:38.949-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='google-collection'/><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='collections'/><title type='text'>Exploring google collections - Part 1</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Google Collection 1.0 released&lt;/span&gt;&lt;br /&gt;Google collections finally hit version 1.0. API provides rich data structures building on JDKs collection API. It also provides utility classes for working with collections. With this post I want to focus on few google collections classes and demonstrate how they help in working with collections. In part 1 of the post, we will deal with very simple example. Later in part 2 of the post, we will work with more involved real life example. &lt;br /&gt;&lt;br /&gt;We will focus on these classes: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicate.html"&gt;Predicate&lt;/a&gt; and &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicates.html"&gt;Predicates&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Function.html"&gt;Function&lt;/a&gt; and &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Functions.html"&gt;Functions&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Collections2.html"&gt;Collections2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Scenarios&lt;/span&gt;&lt;br /&gt;While working with collections you may have noticed that code gets cluttered with for loops, nested for loops, or with for loops with embedded if loops. In most of these scenario what you are trying to do is to iterate through a given collection, either to search for specific elements or to operate on specific elements.&lt;br /&gt;&lt;br /&gt;Lets break down the typical cases:&lt;br /&gt;1. Iterating through a given collection and finding a specific element(s) based on criteria&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;for(Element element: elementsCollection){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(element.equals(something){ //Or any other test criteria based on state of element object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //either add to collection of elements&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //or return this element&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;2. Iterating though a given collection and if certain criteria matches perform operation on the collection &lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;for(Element element: elementCollection){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(element.equals(something){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //or operate on this element&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As an outcome of this, code ends up with &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code duplication of your iteration logic&lt;/li&gt;&lt;li&gt;Code duplication of your condition (matching criteria)&lt;/li&gt;&lt;li&gt;Code duplication of operation on the specific elements (This however can be avoided, if operation is re-factored into a method) &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Google Collections Approach&lt;/span&gt;&lt;br /&gt;Lets start with very simple example, here is how google collection can help:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Define you matching criteria using &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Predicate.html"&gt;Predicate&lt;/a&gt; like &lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Predicate&amp;lt;String&amp;gt; validEmailAddress = new Predicate&amp;lt;String&amp;gt;(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean apply(String emailAddress){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return emailAddress.contains("@");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&lt;/pre&gt;This can be used as &lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;List&amp;lt;String&amp;gt; emailList = Lists.newArrayList("abc@gmail.com", "xyz@gmail.com", "aaagmail.com");&lt;br /&gt;Collection&amp;lt;String&amp;gt; validEmailList = Collections2.filter(emailList, validEmailAddress);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Define your operation on element using &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Function.html"&gt;Function&lt;/a&gt; like&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function&amp;lt;String, String&amp;gt; extractUserName = new Function&amp;lt;String, String&amp;gt;(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String apply(String emailAddress)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String userName = emailAddress.substring(0, emailAddress.indexOf('@'));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return userName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&lt;/pre&gt;This can be used as &lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;String&amp;gt; emailList = Lists.newArrayList("abc@gmail.com", "xyz@gmail.com", "aaa@gmail.com");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;String&amp;gt; userNameList = Lists.transform(emailList,extractUserName);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We will take on more complex DOM-like tree based data structure in part 2 of the post...&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-6047792969692819091?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/6047792969692819091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=6047792969692819091&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6047792969692819091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6047792969692819091'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/01/exploring-google-collections-part-1.html' title='Exploring google collections - Part 1'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-4049982158266026561</id><published>2010-01-23T10:19:00.001-06:00</published><updated>2010-12-05T16:46:40.305-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ast-transformation'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Helpful tips - Working with AST Transformation</title><content type='html'>I have been playing with Groovy AST transformation for some time now. You can walk through some of the &lt;a href="http://blog.kartikshah.info/search/label/ast"&gt;earlier posts here&lt;/a&gt;. With this entry I want to capture some of the lessons learnt, tips, etc.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Using AstViewer Tool (Inspect Ast)&lt;/span&gt;&lt;br /&gt;With Groovy 1.6 AST transformation, one of the difficulty was to come up with tree structure for the code you want to inject or change. It involves calling complex set of Statement and Expression APIs. It is ridden with intricate details of language grammar. With groovy 1.7 AstBuilder, you can use buildFromString and buildFromCode which is lot more easier. But still if you have to use buildFromSpec you will need to have some understanding of Statement/Expression API.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;One of the tool I have found useful is Groovy Console's AST Browser or Eclipse's ASTViewer. Write code you want to generate language structure for and try to replicate using API or using AstBuilder's buildFromSpec. The tool has gotten better from 1.6 to 1.7.&lt;br /&gt;Open Groovy Console and type in following code&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def advice = new String("Hello AST")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println advice&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Go to &lt;span style="font-style: italic;"&gt;Script&lt;/span&gt; --&amp;gt;&lt;span style="font-style: italic;"&gt; Inspect Ast&lt;/span&gt; (or press Ctrl+T) and you will see the AST structure needed.&lt;br /&gt;&lt;img src="http://www.kartikshah.info/images/ast-viewer.png" style="" title="" alt="" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Educated Guess in Script&lt;/span&gt;&lt;br /&gt;With AstBuilder now you can just start building AST in main method or just as script. This has proven to be useful if you just want to compare what you are generating with what is displayed in AstBuilder.&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;def nodes = new AstBuilder().buildFromXXX{&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Working with Variables&lt;/span&gt;&lt;br /&gt;If you are using variables that gets replaced during runtime you may face problem generating AST. One of the method that I found useful was to replace the variable with static value and see if it works. If it does than the problem is possibly due to the type of the variable.&lt;br /&gt;For example, I wanted to generate&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def advice = new &amp;lt;&amp;lt;variableClassName&amp;gt;&amp;gt;()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;where &lt;span style="font-style: italic;"&gt;variableClassName&lt;/span&gt; will be passed in from annotation value. One option is to try generating it with static value like java.lang.String (or just String), if it works than there is some problem with the type of the variable you are passing.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Compile file individually (if using IDE)&lt;/span&gt;&lt;br /&gt;Sometimes the tools you are working with just does not seem to give different output even when you are changing things around in your code. Sometimes stale classes just gets called and you never see the output from the updated classes. You may want to compile both transformation class and the class where the transformation gets used.&amp;nbsp; &lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ByteCode Viewer&lt;/span&gt;&lt;br /&gt;Also using &lt;a href="http://www.ej-technologies.com/products/jclasslib/overview.html"&gt;Byte Code Viewer like this&lt;/a&gt; helps in looking at the classes that are getting generated. You can also write your class how it will look after AST transformation. Use byte code viewer to see the class and compare it with the class that is being generated through AST Transformation. See which statements are properly generated and which are not.&lt;br /&gt;&amp;nbsp;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testcases&lt;/span&gt;&lt;br /&gt;Another extremely resourceful source for AstBuilder is test cases found &lt;a href="http://subversion.assembla.com/svn/AstBuilderPrototype/src/test/org/codehaus/groovy/ast/builder"&gt;here&lt;/a&gt;. It contains rich example set of how to use each node in the builder specifically for buildFromSpec option. &lt;a href="http://subversion.assembla.com/svn/AstBuilderPrototype/src/test/org/codehaus/groovy/ast/builder/AstAssert.groovy"&gt;AstAssert&lt;/a&gt; is another excellent utility to compare and test expected and actually generated structure. Looks like AstAssert class is not packaged with groovy-1.7, so you may need to download and drop it in your project.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Divide and Conquer&lt;/span&gt;&lt;br /&gt;Treat each section of code for which AST is being generated as separate section. Comment out blocks of code and gradually uncomment them to see which section is actually failing and/or not giving desired output.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;Hope this helps! Drop in a line to share your tips or problems you face with Groovy's Ast transformation.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-4049982158266026561?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/4049982158266026561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=4049982158266026561&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4049982158266026561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/4049982158266026561'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/01/helpful-tips-working-with-ast.html' title='Helpful tips - Working with AST Transformation'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-3228288113843863647</id><published>2010-01-18T00:37:00.001-06:00</published><updated>2010-12-05T16:46:40.307-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groovy-1.7'/><category scheme='http://www.blogger.com/atom/ns#' term='ast-transformation'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Revisiting Groovy AST Transformation with AstBuilder</title><content type='html'>Groovy AST is powerful tool to inject changes into classes at various compile phases. It allows one to operate on AST (Abstract Syntax Tree) to manipulate class structure.&lt;br /&gt;&lt;br /&gt;With Groovy 1.7 AstBuilder there are easier ways to write AST transformation. One can build AST nodes using one of following three options&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Build From String&lt;/li&gt;&lt;li&gt;Build From Spec&lt;/li&gt;&lt;li&gt;Build from Code&lt;/li&gt;&lt;/ul&gt;Previously on this blog, we experimented with &lt;a href="http://blog.kartikshah.info/2009/03/groovy-16-ast-transformation-example_5323.html"&gt;Groovy 1.6 AST Transformation Example&lt;/a&gt; and also AOP style usage&amp;nbsp; at &lt;a href="http://blog.kartikshah.info/2009/07/groovy-ast-transformation-aop-style.html"&gt;Groovy AST Transformation - AOP Style&lt;/a&gt;. Lets revisit this transformation from earlier post. &lt;br /&gt;&lt;br /&gt;Lets see how we can generate the AST tree using these new methods from &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GEP+2+-+AST+Builder+Support"&gt;AstBuilder&lt;/a&gt;. Recap&lt;a href="http://blog.kartikshah.info/2009/07/groovy-ast-transformation-aop-style.html"&gt; this previous post before proceeding ahead&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Looks like we need to rewrite &lt;a href="http://blog.kartikshah.info/2009/07/groovy-ast-transformation-aop-style.html"&gt;&lt;span style="font-style: italic;"&gt;initAdviceCall&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://blog.kartikshah.info/2009/07/groovy-ast-transformation-aop-style.html"&gt;&lt;span style="font-style: italic;"&gt;createMethodCall&lt;/span&gt;&lt;/a&gt; to experiment with new methods of AstBuilder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Build From String&lt;/span&gt;&lt;br /&gt;Using buildFromString the task would become very easy. With this options, it is not required to build complicated statement and expression structure. All you need to do is embed code within string and pass it in to buildFromString method. If code you generate is not completely static in nature, you may have to parameterize the value. Here in this example, the declaration of "advice" instantiation depends on the Class value defined in the annotation.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp; def initAdviceCall(classNodeType) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def codeString = "def advice = new " + classNodeType.type.typeClass.canonicalName + "()"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def buildNodes = new AstBuilder().buildFromString(CompilePhase.SEMANTIC_ANALYSIS, true, codeString)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Statement stmt = buildNodes[0].statements[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stmt&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; def createMethodCall(method, Parameter[] parameters) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def codeString = "advice.before (" + "'$method.name'" +", [" + parameters.collect {it.name}.join(',') + "])"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def buildNodes = new AstBuilder().buildFromString(CompilePhase.SEMANTIC_ANALYSIS, true, codeString)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Statement stmt = buildNodes[0].statements[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stmt&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Build From Spec&lt;/span&gt;&lt;br /&gt;buildFromSpec option is more verbose. It also requires you to understand internal structure that is required to be build. With use of GroovyConsole's Inspect Ast option, it is not difficult to come up with the AST structure. &lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp; def initAdviceCall (classNodeType) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def buildNodes = new AstBuilder().buildFromSpec {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; declaration {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "advice"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token "="&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constructorCall(classNodeType.getType().getTypeClass()){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumentList()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Statement stmt = buildNodes[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stmt&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; def createMethodCall(method, Parameter[] parameters) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def buildNodes = new AstBuilder().buildFromSpec {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methodCall {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variable "advice"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant "before"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumentList {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; constant method.name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; list {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameters.each {variable it.name}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Statement stmt = buildNodes[0]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stmt&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are some differences between using API directly and using spec builder option. One thing specifically that threw me off was that ConstructorCallExpression takes in ClassNode as parameter, however the constructorCall in builder takes Class. It wouldn't have been much of an annoyance, if I had read &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GEP+2+-+AST+Builder+Support"&gt;GEP-2&lt;/a&gt; which states that any expression taking ClassNode, for builder you just need to pass class instance. Well in this example, value provided by annotation was ClassNode, so I had to get Class and pass it on to constructorCall.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Build From Code&lt;/span&gt;&lt;br /&gt;Unlike above two options buildFromCode option did not work for me in above scenario. The problem I faced was I couldn't do def advice = &amp;lt;VariableClassName&amp;gt;() without using reflection. Method would have looked something like this&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;def initAdviceCall(classNodeType){&lt;br /&gt;new AstBuilder().buildFromCode {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def advice = classNodeType.getType().getTypeClass().newInstance()&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Similarly, for createMethodCall, I would have to use reflection for passing in parameters. &lt;br /&gt;&lt;br /&gt;More later...&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-3228288113843863647?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/3228288113843863647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=3228288113843863647&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3228288113843863647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3228288113843863647'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/01/revisiting-groovy-ast-transformation.html' title='Revisiting Groovy AST Transformation with AstBuilder'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-7959704721995015964</id><published>2010-01-05T07:48:00.001-06:00</published><updated>2010-12-05T16:48:03.292-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groovy-1.7'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Groovy Truth</title><content type='html'>Groovy had its truth. Groovy expanded on what Java allows to use in various control structures. While Java allows only boolean expression in if and while control structures, Groovy relaxed the requirement. In Groovy you can use objects in if and while expressions. Only a non-null and non-empty string will evaluate to true. A non-empty collection will evaluate to true. Non zero numbers will evaluate to true. &lt;br /&gt;&lt;br /&gt;With Groovy 1.7, Groovy Truth got better. You can now customize the Truth based on your requirement. This can be done by implementing boolean asBoolean() method. Implement the method on any object and logic defined in the method will be used to evaluate. Look at the following example&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class Account {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String status&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; boolean asBoolean(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(status != 'active') &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;assert new Account(status:'active')&lt;br /&gt;assert !new Account(status:'prospect')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can also expand (or change) existing classes like String, Integer, etc using metaClass. Let's &lt;span style="text-decoration: underline;"&gt;expand&lt;/span&gt; the groovy truth to return null if the string value is 'null'&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.metaClass.asBoolean = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(delegate&amp;nbsp; == null || delegate == '' || delegate == 'null') false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String nullString = null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String nullLiteralString = "null"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String validString = "JohnDoe" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String emptyString = ''&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert !nullString&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert !nullLiteralString &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert validString&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert !emptyString&amp;nbsp; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Asserts are one place where the overridden logic will be applied. It works with if,while, and ternary operator as well. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;//continued from previous script&lt;br /&gt;println "null"?"FALSE":"TRUE"&lt;br /&gt;&lt;br /&gt;str1 = "null"&lt;br /&gt;if(str1) println "Valid String" &lt;br /&gt;else println 'Null, empty or "null" literal string'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you do not want to override the way an object evaluates to boolean globally. You can use categories.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class StringNullTruthCategory{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; boolean asBoolean(String str){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(str || str == 'null')&amp;nbsp; false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;use(StringNullTruthCategory){&lt;br /&gt;&amp;nbsp;&amp;nbsp; String parameterValue = "null"&lt;br /&gt;&amp;nbsp;&amp;nbsp; if(parameterValue)&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println 'Should not be printed'&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; println 'Should print'&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def httpRequestParmValue = "null"&lt;br /&gt;print 'Valid Value: '&lt;br /&gt;println httpRequestParmValue?'YES':'NO'&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Similarly, you can expand Integer's truth value if value is either zero or negative value. you can expand truth value of Map based on specific key-value. You have to be careful in doing so though, completely overriding the evaluation criteria can lead to confusion. You can apply on customize builder object. Let's say you have customized builder parsing order.xml into OrderEntity who has multiple OrderItems. OrderEntity truth can be derived from all of its OrderItem. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;class OrderEntity{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OrderItem[] orderItems&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String status&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; boolean asBoolean(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Define based on status or status of orderItems or presense/absence of orderItems&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if(currentOrder) { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //do time consuming process&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can define asBoolean objects in your Java class and use that definition to determine boolean value. However, you have to be careful of legacy Java Objects which has method asBoolean already defined for different purpose. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-7959704721995015964?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/7959704721995015964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=7959704721995015964&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/7959704721995015964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/7959704721995015964'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2010/01/groovy-truth_05.html' title='Groovy Truth'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-7554519035746502328</id><published>2009-12-30T21:43:00.001-06:00</published><updated>2010-12-05T16:49:00.484-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='middleware'/><category scheme='http://www.blogger.com/atom/ns#' term='mule'/><category scheme='http://www.blogger.com/atom/ns#' term='mind-map'/><title type='text'>Mule Notes</title><content type='html'>Mule Mind Map&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.kartikshah.info/images/mule-1.jpeg" style="margin: 0pt auto 10px; display: block; text-align: center; width: 918px; height: 570px;" title="Mule Mind Map" alt="" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.kartikshah.info/images/mule-1.jpeg"&gt;Click Here&lt;/a&gt; for full size image&lt;br /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-7554519035746502328?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/7554519035746502328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=7554519035746502328&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/7554519035746502328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/7554519035746502328'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/12/mule-notes.html' title='Mule Notes'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-8082682942149575258</id><published>2009-11-19T23:24:00.001-06:00</published><updated>2010-12-05T16:46:54.101-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Grails: belongsTo</title><content type='html'>&lt;span style="font-family: Verdana;"&gt;&lt;br /&gt;In Grails &lt;span style="font-style: italic;"&gt;hasMany&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;belongsTo&lt;/span&gt; are used to define relationship between objects. There are various other uses of &lt;span style="font-style: italic;"&gt;belongsTo&lt;/span&gt;.&amp;nbsp; Trying to capture them here in this short post.&lt;br /&gt;&amp;nbsp;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;Let's take an example, say you have domain class &lt;span style="font-style: italic; font-weight: bold;"&gt;TaskList&lt;/span&gt; which had many &lt;span style="font-style: italic; font-weight: bold;"&gt;Task&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Direction of Access&lt;/span&gt;&lt;br /&gt;In class Task if you define belongsTo as&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; belongsTo = TaskList&lt;br /&gt;it means that Task object can not access its associated instance of TaskList&lt;br /&gt;If it is defined as&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; belongsTo = [taskList: TaskList]&lt;br /&gt;it means that Task object can access its associated instance of TaskList by doing task.taskList&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cascading Deletes&lt;/span&gt;&lt;br /&gt;Only if belongsTo is defined cascading delete will happen. If TaskList is deleted all Tasks part of that TaskList will be deleted.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;addTo* method access&lt;/span&gt;&lt;br /&gt;For many-to-many relationship, defining belongsTo enables dynamic addTo* method&lt;br /&gt;Extending previous example, say each &lt;span style="font-weight: bold; font-style: italic;"&gt;Task&lt;/span&gt; can have multiple &lt;span style="font-weight: bold; font-style: italic;"&gt;Tag&lt;/span&gt; and a &lt;span style="font-weight: bold; font-style: italic;"&gt;Tag&lt;/span&gt; can be given to multiple &lt;span style="font-weight: bold; font-style: italic;"&gt;Task&lt;/span&gt;s. Defining belongsTo enables addTo* dynamic methods. e.g. task.addToTags(tag)&lt;br /&gt;&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-8082682942149575258?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/8082682942149575258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=8082682942149575258&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8082682942149575258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8082682942149575258'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/11/grails-belongsto.html' title='Grails: belongsTo'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-9033276149481013550</id><published>2009-07-10T00:25:00.001-05:00</published><updated>2010-12-05T16:46:16.584-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ast-transformation'/><category scheme='http://www.blogger.com/atom/ns#' term='aop'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Groovy AST Transformation - AOP Style</title><content type='html'>In my last &lt;a href="http://kartik-shah.blogspot.com/2009/03/groovy-16-ast-transformation-example_5323.html"&gt;blog about AST Transformation&lt;/a&gt; I followed a sample example and created AssertParamsNotNull local transformation. Further, I wanted to create AST Transformation which is generic enough and performs any check before method is executed. In process, goal is to learn about AST Transformation. &lt;br /&gt;&lt;br /&gt;&lt;font size="3"&gt;&lt;span style="font-weight: bold;"&gt;BeforeAdvisor AST Transformation&lt;/span&gt;&lt;/font&gt;&lt;br /&gt;Use case for BeforeAdvisor AST involves: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Authorization Checking - Security by checking role from context&lt;/li&gt;&lt;li&gt;Print Parameter values with which the method is called&lt;/li&gt;&lt;li&gt;Asserts Parameters are not null&lt;/li&gt;&lt;li&gt;Check various entry-conditions/Pre-Conditions of the method&lt;/li&gt;&lt;/ul&gt;To make transform generic enough, idea is to inject a method call to &lt;span style="font-style: italic;"&gt;before method&lt;/span&gt; of advice for each method annotated with @BeforeAdvisor(MyPreConditionAdvice). Advice method can choose to implement any checks/conditions to be performed before actual methods gets executed. &lt;br /&gt;&lt;br /&gt;Few of the subtle characteristics of this type of solution are &lt;br /&gt;&lt;ul&gt;&lt;li&gt;It does not allow changing the method parameters.&amp;nbsp; &lt;br /&gt;&lt;/li&gt;&lt;li&gt;It does not allow to stop execution of method. However, you can throw runtime exception.&lt;/li&gt;&lt;li&gt;Advice needs no arg constructor and must implement method &lt;span style="font-style: italic;"&gt;before &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Usage and Client&lt;/span&gt;&lt;br /&gt;Starting with class that will use this transform. Following defines script-level method with annotation having advice information.&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;package com.learn.sts.groovy.ast&lt;br /&gt;&lt;br /&gt;@com.learn.sts.groovy.ast.BeforeAdvisor(value= com.learn.sts.groovy.MyAdvice)&lt;br /&gt;def sayHello(name, name2)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; println "Hello " + name + name2&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sayHello("World", "Groovy") &lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Sample Advice&lt;/span&gt;&lt;br /&gt;The advice that we will try to invoke will be something like this. This advice just prints parameter value that method is being invoked with. But you can implement any of the use cases described above.&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;package com.learn.sts.groovy&lt;br /&gt;&lt;br /&gt;public class MyAdvice&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def before(String methodName, List listArg)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; println 'Entering Method ' + methodName + ' with params ' + listArg&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Annotation&lt;/span&gt;&lt;br /&gt;Now lets create the Annotation&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;package com.learn.sts.groovy.ast;&lt;br /&gt;&lt;br /&gt;import java.lang.annotation.Retention&lt;br /&gt;import java.lang.annotation.RetentionPolicy&lt;br /&gt;import java.lang.annotation.Target&lt;br /&gt;import java.lang.annotation.ElementType&lt;br /&gt;import org.codehaus.groovy.transform.GroovyASTTransformationClass&lt;br /&gt;@Retention(RetentionPolicy.SOURCE)&lt;br /&gt;@Target([ElementType.METHOD])&lt;br /&gt;@GroovyASTTransformationClass(["com.learn.sts.groovy.ast.BeforeAdvisorASTTransformation"])&lt;br /&gt;public @interface BeforeAdvisor {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Class value ();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;One difference to this annotation is that it declares a method value(). This allows us to get value being passed during annotation declaration on method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;AST Transformation&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="groovy"&gt;&lt;br /&gt;package com.learn.sts.groovy.ast&lt;br /&gt;&lt;br /&gt;//Imports section skipped for brevity&lt;br /&gt;&lt;br /&gt;@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)&lt;br /&gt;public class BeforeAdvisorASTTransformation implements ASTTransformation &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void visit(ASTNode[] nodes, SourceUnit source)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AnnotationNode node = (AnnotationNode) nodes[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; final Expression classNode = node.getMember("value")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;MethodNode&amp;gt; allMethods = source.AST?.classes*.methods.flatten()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; List annotatedMethods = allMethods.findAll{ MethodNode method -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; method.getAnnotations(new ClassNode(BeforeAdvisor))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; annotatedMethods.each{MethodNode method -&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; List existingStatements = method.getCode().getStatements()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Parameter[] parameters = method.getParameters()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; int i = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; existingStatements.add(i++, initAdviceCall(classNode))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; existingStatements.add(i++, createMethodCall(method, parameters))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Statement initAdviceCall(classNode)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; return new ExpressionStatement(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; new DeclarationExpression(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; new VariableExpression("advice"),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; new Token(Types.ASSIGNMENT_OPERATOR, "=", -1, -1),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; new ConstructorCallExpression(classNode.getType(), new ArgumentListExpression())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; public Statement createMethodCall(method, Parameter[] parameters){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; List parameterExpressionList = new ArrayList()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; parameters.each{ parameter -&amp;gt; parameterExpressionList.add(new VariableExpression(parameter))}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; return new ExpressionStatement(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; new MethodCallExpression(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; new VariableExpression("advice"),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "before",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; new ArgumentListExpression(new ConstantExpression(method.getName()),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; new ListExpression(parameterExpressionList)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Couple of things to notice here: &lt;br /&gt;&lt;br /&gt;First, creation of the AST tree involves &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Creating instance of Advice Class - This is done through method &lt;span style="font-style: italic;"&gt;initAdviceCall&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Invocation of the method before with methodName and Parameter List - This is done through method &lt;span style="font-style: italic;"&gt;createMethodCall&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Creating AST structure is not the easiest task. One approach that has worked for me is the write the sample code that you are trying to generate AST for and then use Groovy AST viewer in eclipse. &lt;br /&gt;&lt;br /&gt;Second, inspecting the value on ASTNode and getting Advice class value. First node contains information about the annotation and second node is the annotated node. &lt;br /&gt;&lt;br /&gt;&lt;font size="3"&gt;&lt;span style="font-weight: bold;"&gt;Lessons Learned&lt;/span&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font size="2"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-weight: bold;"&gt;Compilation&lt;/span&gt;&lt;br /&gt;It was required to compile Transformations files first and then compile the classes that use AST Transformation. If I compiled all three of them together the AST Transformation did not kick in. I used Eclipse IDE and it forced me to use Compile Groovy File explicitly each time I made change. "Build Automatically" or "Clean" option did not work. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Script Level Methods vs all Class Methods&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;In &lt;a href="http://kartik-shah.blogspot.com/2009/03/groovy-16-ast-transformation-example_5323.html"&gt;AssertParamsNotNull&lt;/a&gt; AST Transformation in previous blog, I used &lt;span style="font-style: italic;"&gt;source.getAST()?.getMethods()&lt;/span&gt;&amp;nbsp; what it did is that it only found top level (Script Level) methods. So AST Transformation did not apply to Class Methods, it only got applied to Script Level Method. For this one I changed to source.ast?.classes*.methods.flatten() (Line 12 in &lt;span style="font-style: italic;"&gt;BeforeAdvisorASTTransformation&lt;/span&gt;). This also become apparent once you see AST structure for a given class using Groovy AST View in eclipse. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Retrive value from annotations&lt;/span&gt;&lt;br /&gt;ASTNode being passed to &lt;span style="font-style: italic;"&gt;visit&lt;/span&gt; method carries information about the annotation. First element (node[0]) contains information about annotation. You can get the values passed in to annotation during the visit method and use it during the transformation. In case above we get class passed in as value and it gets instantiated and before method gets invoked.&lt;br /&gt;&lt;br /&gt;&lt;font size="2"&gt;&lt;span style="font-weight: bold;"&gt;Groovy Compilation&lt;/span&gt;&lt;/font&gt;&lt;br /&gt;When groovy compiler is invoked, any sourcefile.groovy goes under series of transformations. &lt;br /&gt;From Source --&amp;gt; ANTLR Tokens --&amp;gt; ANTLR AST --&amp;gt; Groovy AST --&amp;gt; Bytecode&lt;br /&gt;&lt;br /&gt;Using AST Transformation, we manipulate the way groovy AST gets generated. It allows to insert additonal statements. &lt;br /&gt;&lt;br /&gt;There are various CompilerPhase that goes along with this process. I couldn't find much documentation on the process. Best information is found on &lt;a href="http://blackdragsview.blogspot.com/2006/11/chitchat-with-groovy-compiler.html"&gt;Jochen Theodorou's blog post&lt;/a&gt;&lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-9033276149481013550?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/9033276149481013550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=9033276149481013550&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/9033276149481013550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/9033276149481013550'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/07/groovy-ast-transformation-aop-style.html' title='Groovy AST Transformation - AOP Style'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-6920448346239865337</id><published>2009-06-20T23:35:00.001-05:00</published><updated>2010-12-05T16:47:04.106-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='swingbuilder'/><category scheme='http://www.blogger.com/atom/ns#' term='jfreechart'/><category scheme='http://www.blogger.com/atom/ns#' term='jmx'/><category scheme='http://www.blogger.com/atom/ns#' term='administration'/><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>JMX, Groovy, JFreeChart and Swing</title><content type='html'>&lt;span style="font-weight: bold; font-family: Verdana;"&gt;&lt;/span&gt;&lt;span style="font-family: Verdana;"&gt;Recently, I worked on creating JMX based dashboard application showing Weblogic instances' information. During the exercise I came across &lt;/span&gt;&lt;a style="font-family: Verdana;" href="http://groovy.codehaus.org/Groovy+and+JMX"&gt;JMX and Groovy examples &lt;/a&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;span style="font-family: Verdana;"&gt;Using JMX, Groovy, Swing and JFreeChart, I came up with a dashboard application which looks like this. &lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;a style="font-family: Verdana;" href="http://www.flickr.com/photos/shahkartikr/3645249363/" title="Memory-Usage by shahkartikr, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2431/3645249363_1fb8dacf03.jpg" alt="Memory-Usage" height="202" width="500" /&gt;&lt;/a&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;span style="font-family: Verdana;"&gt;It show memory usage on two instances. It automatically updates every 10 seconds and redraws chart. &lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;br style="font-family: Verdana;" /&gt;&lt;span style="font-family: Verdana;"&gt;Surprisingly (or not so surprisingly), code required to be written to perform this activity is minimal. Specifically thanks to Groovy's SwingBuilder and JMX libraries.&lt;/span&gt; Groovy makes the task of using 4 different technologies really easy and fun.&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;import org.jfree.chart.ChartFactory&lt;br /&gt;import javax.swing.WindowConstants as WC&lt;br /&gt;import javax.management.remote.*&lt;br /&gt;import javax.naming.Context;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * WeblogicJMXReporter monitors Memory value for given node&lt;br /&gt; * @author kartik.shah&lt;br /&gt; */&lt;br /&gt;public class WeblogicJMXReporter&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    static void main(String[] args)&lt;br /&gt;    {&lt;br /&gt;    	def env = [:]&lt;br /&gt;    	env["java.naming.factory.initial"] = "weblogic.jndi.WLInitialContextFactory"&lt;br /&gt;    	env[Context.SECURITY_PRINCIPAL] = "system"&lt;br /&gt;    	env[Context.SECURITY_CREDENTIALS] = "*******" //Password is always stars&lt;br /&gt;    	env[JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES] = "weblogic.management.remote"&lt;br /&gt;    	def jmxServiceURL = new JMXServiceURL("http", "10.50.120.110", 19400,"/jndi/weblogic.management.mbeanservers.domainruntime")&lt;br /&gt;    	def server = JMXConnectorFactory.connect(jmxServiceURL, env).MBeanServerConnection&lt;br /&gt;&lt;br /&gt;    	def chart1Map = getChart("node1_svr", server);&lt;br /&gt;    	def piedata1 = chart1Map."pieData"&lt;br /&gt;    	def chart1 = chart1Map."Chart"&lt;br /&gt;    	def jvmInfo1 = chart1Map."MBean"&lt;br /&gt;    	&lt;br /&gt;    	def chart2Map = getChart("node2_svr", server);&lt;br /&gt;    	def piedata2 = chart2Map."pieData"&lt;br /&gt;    	def chart2 = chart2Map."Chart"&lt;br /&gt;    	def jvmInfo2 = chart2Map."MBean"&lt;br /&gt;    	&lt;br /&gt;    	def swing = new groovy.swing.SwingBuilder()&lt;br /&gt;&lt;br /&gt;    	def frame = swing.frame(title:'Weblogic INT Memory Usage', defaultCloseOperation:WC.EXIT_ON_CLOSE, &lt;br /&gt;    	                        size:[800,600], locationRelativeTo: null) {&lt;br /&gt;    	    borderLayout()&lt;br /&gt;    	    panel(id:'canvas') { rigidArea(width:700, height:250) }&lt;br /&gt;    	}&lt;br /&gt;&lt;br /&gt;    	def bounds1 = new java.awt.Rectangle(0,0, 350,250).bounds&lt;br /&gt;    	def bounds2 = new java.awt.Rectangle(351,0, 350, 250).bounds&lt;br /&gt;    	while(true)&lt;br /&gt;    	{&lt;br /&gt;    	    recalculatePieData(piedata1, jvmInfo1)&lt;br /&gt;    	    recalculatePieData(piedata2, jvmInfo2)&lt;br /&gt;        &lt;br /&gt;        	chart1.fireChartChanged()&lt;br /&gt;        	chart2.fireChartChanged()&lt;br /&gt;        	&lt;br /&gt;        	frame.pack()&lt;br /&gt;        	frame.show()&lt;br /&gt;        	chart1.draw(swing.canvas.graphics, bounds1)&lt;br /&gt;        	chart2.draw(swing.canvas.graphics, bounds2)&lt;br /&gt;        	sleep(10000)&lt;br /&gt;    	}&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    static getChart(nodeName, server)&lt;br /&gt;    {&lt;br /&gt;    	def jvmInfo = new GroovyMBean(server, 'com.bea:Location='+nodeName+',Name='+nodeName+',ServerRuntime='+nodeName+',Type=JVMRuntime')&lt;br /&gt;    	def piedata = new org.jfree.data.general.DefaultPieDataset()&lt;br /&gt;    	piedata.setValue "Free", jvmInfo.HeapFreeCurrent&lt;br /&gt;    	piedata.setValue "Used", jvmInfo.HeapSizeMax - jvmInfo.HeapFreeCurrent&lt;br /&gt;    	def options = [true, true, true]&lt;br /&gt;    	def chart = ChartFactory.createPieChart(nodeName, piedata, *options)&lt;br /&gt;    	chart.backgroundPaint = java.awt.Color.white&lt;br /&gt;        &lt;br /&gt;        ["MBean":jvmInfo, "pieData":piedata, "Chart":chart]&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    static recalculatePieData(piedata, jvmInfo)&lt;br /&gt;    {&lt;br /&gt;    	piedata.setValue "Free", jvmInfo.HeapFreeCurrent&lt;br /&gt;    	piedata.setValue "Used", jvmInfo.HeapSizeMax - jvmInfo.HeapFreeCurrent&lt;br /&gt;    	println piedata.getValue("Free")&lt;br /&gt;    	println piedata.getValue("Used")&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;For purpose of this blog and keeping it simple, I kept it all in one groovy class. &lt;br /&gt;  &lt;div class="flockcredit" style="text-align: right; color: #CCC; font-size: x-small;"&gt;Blogged with the &lt;a href="http://www.flock.com/blogged-with-flock" style="color: #999; font-weight: bold;" target="_new" title="Flock Browser"&gt;Flock Browser&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-6920448346239865337?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/6920448346239865337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=6920448346239865337&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6920448346239865337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/6920448346239865337'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/06/jmx-groovy-jfreechart-and-swing.html' title='JMX, Groovy, JFreeChart and Swing'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2431/3645249363_1fb8dacf03_t.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-3306965452601264220</id><published>2009-03-26T16:02:00.001-05:00</published><updated>2009-04-02T17:07:05.876-05:00</updated><title type='text'>Groovy 1.6 AST Transformation Example</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;font face='verdana'&gt;With Groovy 1.6 released and &lt;a target='_blank' href='http://www.infoq.com/articles/groovy-1-6'&gt;this article on InfoQ&lt;/a&gt; got me to try some new features. &lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;b&gt;AST Transformation&lt;/b&gt;&lt;br/&gt;With Groovy 1.6 you can define local and global transformation using annotations. &lt;/font&gt;&lt;font face='verdana'&gt;So let's define @AssertParamsNotNull annotation for method which would perform AST Transformation at compile time. It simply asserts parameters of method are not null. I am following &lt;a target='_blank' href='http://groovy.codehaus.org/Local+AST+Transformations'&gt;groovy documentation here&lt;/a&gt; and &lt;a target='_blank' href='http://hamletdarcy.blogspot.com/2009/03/local-ast-transformations-in-groovy-16.html'&gt;blog entry here by Hamlet D'Arcy&lt;/a&gt;&lt;/font&gt;.&lt;br/&gt;&lt;font face='verdana'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;There are three components to defining local AST Transformation&lt;br/&gt;&lt;br/&gt;Step 1: Define Annotation&lt;br/&gt;Step 2: Define GroovyASTTransformation &lt;br/&gt;Step 3: Test and Usage&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;b&gt;Pre-requisites&lt;/b&gt;&lt;br/&gt;Download Groovy 1.6&lt;br/&gt;Download Groovy Eclipse plugin for 1.6, available from this update URL. &lt;/font&gt; &lt;blockquote&gt;&lt;a href='http://dist.groovy.codehaus.org/distributions/updateDev_1.6/'&gt; http://dist.groovy.codehaus.org/distributions/updateDev_1.6/&lt;/a&gt;&lt;font face='verdana'&gt; &lt;/font&gt;&lt;br/&gt;&lt;/blockquote&gt; &lt;font face='verdana'&gt;This url is different from their usual update url. I believe they will update their distributions update url (&lt;/font&gt;&lt;small&gt;&lt;a href='http://dist.codehaus.org/groovy/distributions/update/'&gt;http://dist.codehaus.org/groovy/distributions/update/&lt;/a&gt;&lt;/small&gt;&lt;font face='verdana'&gt;)&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;b&gt;Step 1: Define Annotation @AssertParamsNotNull&lt;/b&gt;&lt;br/&gt;&lt;/font&gt;&lt;pre class='groovy' name='code'&gt;&lt;br /&gt;package com.learn.groovy16.ast.local&lt;br /&gt;import java.lang.annotation.Retention&lt;br /&gt;import java.lang.annotation.RetentionPolicy&lt;br /&gt;import java.lang.annotation.Target&lt;br /&gt;import java.lang.annotation.ElementType&lt;br /&gt;import org.codehaus.groovy.transform.GroovyASTTransformationClass&lt;br /&gt;@Retention(RetentionPolicy.SOURCE)&lt;br /&gt;@Target([ElementType.METHOD])&lt;br /&gt;@GroovyASTTransformationClass(["com.learn.groovy16.ast.local.AssertParamsNotNullASTTransformation"])&lt;br /&gt;public @interface AssertParamsNotNull{&lt;br /&gt;&lt;/pre&gt;&lt;font face='verdana'&gt;One thing to notice is here defining the ASTTransformation class. It requires complete qualified class name. Rest of the things are standard annotation declaration.&lt;br/&gt;&lt;br/&gt;While working on getting this running in my environment I faced following errors/issues.&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;b&gt;&lt;i&gt;Unknown Type: ANNOTATION_DEF at line ... &lt;/i&gt;&lt;/b&gt;&lt;/small&gt;&lt;br/&gt;This error comes if for some reason eclipse environment is still using older groovy installation. Check your GROOVY_HOME points to Groovy 1.6. If you are able to run this through command line, but eclipse is giving your errors. Update your Groovy Eclipse plugin from dev update URL. You may have to wipe it clean for eclipse to understand it. &lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;small&gt;Expected '{' but &lt;newline&gt; was found...&lt;br/&gt;&lt;/newline&gt;&lt;/small&gt;&lt;/b&gt;&lt;/font&gt;&lt;font face='verdana'&gt;This error comes if for some reason there funny newline characters. I think I got this error if right after "public @interface AssertParamsNotNull&lt;/font&gt;" if { is in the next line. I believe I got funny character in between those two. I changed the text file encoding to UTF-8 and the error went away. It allowed me to have braces on the next line.&lt;br/&gt;&lt;font face='verdana'&gt;&lt;br/&gt;&lt;b&gt;Step 2: Define GroovyASTTransformation&lt;/b&gt;&lt;br/&gt;&lt;/font&gt;&lt;br /&gt;&lt;pre class='groovy' name='code'&gt;&lt;br /&gt;package com.learn.groovy16.ast.local&lt;br /&gt;import org.codehaus.groovy.transform.GroovyASTTransformation&lt;br /&gt;import org.codehaus.groovy.ast.ASTNode&lt;br /&gt;import org.codehaus.groovy.control.SourceUnit&lt;br /&gt;import org.codehaus.groovy.transform.ASTTransformation&lt;br /&gt;import org.codehaus.groovy.control.CompilePhase&lt;br /&gt;import org.codehaus.groovy.ast.MethodNode&lt;br /&gt;import org.codehaus.groovy.ast.ClassNode&lt;br /&gt;import org.codehaus.groovy.ast.Parameter&lt;br /&gt;import org.codehaus.groovy.ast.stmt.Statement&lt;br /&gt;import org.codehaus.groovy.ast.stmt.AssertStatement&lt;br /&gt;import org.codehaus.groovy.ast.expr.BooleanExpression&lt;br /&gt;import org.codehaus.groovy.ast.expr.NotExpression&lt;br /&gt;import org.codehaus.groovy.ast.expr.VariableExpression&lt;br /&gt;@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)&lt;br /&gt;public class AssertParamsNotNullASTTransformation implements ASTTransformation &lt;br /&gt;{&lt;br /&gt; public void visit(ASTNode[] nodes, SourceUnit source)&lt;br /&gt;  {&lt;br /&gt;   List methods = source.getAST()?.getMethods()&lt;br /&gt;    methods.findAll{MethodNode method -&gt;&lt;br /&gt;     method.getAnnotations(new ClassNode(AssertParamsNotNull))&lt;br /&gt;    }.each{MethodNode method -&gt; &lt;br /&gt;      List existingStatements = method.getCode().getStatements()&lt;br /&gt;      Parameter[] parameters = method.getParameters()&lt;br /&gt;      parameters.eachWithIndex(){ parameter, i -&gt;&lt;br /&gt;       existingStatements.add(i, createAssertStatement(parameter))&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public Statement createAssertStatement(Parameter parameter){&lt;br /&gt;   return new AssertStatement(&lt;br /&gt;    new BooleanExpression(&lt;br /&gt;     new VariableExpression(parameter))&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;font face='verdana'&gt;&lt;font face='verdana'&gt;This is where most of the trick is happening. This class implements &lt;i&gt;ASTTransformation&lt;/i&gt; interface implementing &lt;i&gt;visit(ASTNode[], SourceUnit source)&lt;/i&gt; method. This method gets all methods marked with AssertParamsNotNull annotation, iterates over all method, iterates over all method parameters and calls createAssertStatement(parameter). createAssertStatement(parameter) creates Statements equivalent to assert parameter and inserts it into the AST tree. All this happens at compile time. So notice line&lt;br/&gt;&lt;/font&gt; &lt;/font&gt;&lt;blockquote&gt;&lt;font face='verdana'&gt;&lt;big&gt;&lt;font face='Courier New'&gt;&lt;small&gt;@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;br/&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;font face='verdana'&gt; &lt;font face='verdana'&gt;Creating Statement and Expression using API is really cumbersome. It is good they are working on builder support for the same. &lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;small&gt;&lt;font face='Courier New'&gt; &lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;br/&gt;&lt;font face='verdana'&gt;&lt;b&gt;Step 3: Test and Run &lt;/b&gt;&lt;br/&gt;&lt;/font&gt;&lt;/font&gt;&lt;br /&gt;&lt;pre class="groovy" name="code"&gt;&lt;br /&gt;package com.learn.groovy16.ast.local  &lt;br /&gt;&lt;br /&gt;@com.learn.groovy16.ast.local.AssertParamsNotNull&lt;br/&gt;  &lt;br /&gt;def foo(String var)&lt;br /&gt;{&lt;br /&gt;  println var&lt;br /&gt;}&lt;br /&gt;foo("Hello")&lt;br /&gt;foo(null)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;font face='verdana'&gt; &lt;font face='verdana'&gt;&lt;br/&gt;Note the annotation with fully qualified name. &lt;br/&gt;&lt;br/&gt;Interesting thing is that all transformation happens at compile time. It does not stop &lt;br/&gt;&lt;br/&gt;&lt;b&gt;Other interesting AST Transformations...&lt;br/&gt;&lt;big&gt;&lt;br/&gt;&lt;/big&gt;&lt;/b&gt;&lt;i&gt;&lt;b&gt;@CatchExceptions(list=[exception1, exception2, ..],rethrow=AppException)&lt;/b&gt;&lt;/i&gt;&lt;br/&gt;Define AST transformation to remove clutterred exception handling logic and rethrow ApplicationException as noted by parameters of annotation. I think the challenge here will be to build AST Statement and Expression.&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;b&gt;&lt;i&gt;&lt;big&gt;@&lt;/big&gt;&lt;small&gt;&lt;big&gt;SecureAccess(Role=Manager)&lt;/big&gt;&lt;br/&gt;&lt;/small&gt;&lt;/i&gt;&lt;/b&gt;&lt;small&gt;&lt;big&gt;Allows to define security over method execution.&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;i&gt;&lt;b&gt;&lt;big&gt;@Trace(isTraceEnabled=$GlobalTraceParameter)&lt;/big&gt;&lt;br/&gt;&lt;/b&gt;&lt;/i&gt;&lt;big&gt;Emits out trace of method. Entered, parameter values, exit, return type. This only gets emitted if GlobalTraceParameter is set to Y&lt;br/&gt;&lt;/big&gt;&lt;/small&gt;&lt;/big&gt;&lt;/small&gt;&lt;/font&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-3306965452601264220?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/3306965452601264220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=3306965452601264220&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3306965452601264220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/3306965452601264220'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/03/groovy-16-ast-transformation-example_5323.html' title='Groovy 1.6 AST Transformation Example'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-8584213247971948689</id><published>2009-03-11T11:46:00.001-05:00</published><updated>2009-03-11T11:47:29.276-05:00</updated><title type='text'>Grails, Flex and MyEclipse</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;font face='verdana'&gt;This is a small exercise that I undertook following documentation I found on &lt;a href='http://www.grails.org/Flex+Plugin'&gt;grails website&lt;/a&gt;. Let's create small calculator application which adds two operands. The idea is to setup the flex plugin and see how it works.&lt;br/&gt;&lt;br/&gt;I used following tools&lt;br/&gt;&lt;/font&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;MyEclipse with flex builder&lt;/li&gt;&lt;li&gt;Grails&lt;/li&gt;&lt;li&gt;Groovy Eclipse plugin&lt;/li&gt;&lt;li&gt;&lt;font face='verdana'&gt;Grails Fex Plugin&lt;/font&gt;&lt;/li&gt;&lt;/ul&gt;&lt;font face='verdana'&gt;	&lt;/font&gt;&lt;font face='verdana'&gt;&lt;b&gt;Step 1: Install Groovy Eclipse plugin&lt;/b&gt;&lt;br/&gt;MyEclipse 6.5 installation that I had did not came with groovy/grails plugin. One of the nice thing about MyEclipse is that it is eclipse with additional tools. Use the following plugin update URL to get groovy plugin. &lt;br/&gt;&lt;br/&gt;Here is eclipse software update URL: &lt;a href='http://dist.codehaus.org/groovy/distributions/update/'&gt;http://dist.codehaus.org/groovy/distributions/update/&lt;/a&gt;. &lt;br/&gt;&lt;br/&gt;This plugin is optional. You can use grails command line commands and that will work as well.&lt;br/&gt;&lt;br/&gt;	&lt;b&gt;Step 2: Create Grails Project and Install Grails Flex Plugin&lt;/b&gt;&lt;br/&gt;Next thing is to install Grails Flex plugin. This is still under development. The one I used is version 0.2.&lt;br/&gt;&lt;br/&gt;Create Grails application using New --&amp;gt; Other... --&amp;gt; New Grails Project. This will create grails project. &lt;br/&gt; &lt;br/&gt;Alternatively you an use grails command line to create app. Go to command line, change directory to project root folder in your workspace and type command: &lt;br/&gt;              &lt;font face='Courier New'&gt;grails install-plugin flex.&lt;/font&gt; &lt;br/&gt;&lt;br/&gt;This will install flex plugin for grails. &lt;br/&gt;&lt;br/&gt;I was using MyEclipse with Flex Builder, it was easy to add flex nature to my project. To do that right click and add flex nature&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Step 3: Create Calc UI&lt;/b&gt;&lt;br/&gt;Now project is setup, we are ready to create calc.mxml. I created this under webapp folder so that it is visible.&lt;br/&gt;&lt;br/&gt;Use following calc.mxml&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br/&gt;&amp;lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"&amp;gt;&lt;br/&gt;    &amp;lt;mx:RemoteObject id="ro" destination="calcService"/&amp;gt;&lt;br/&gt;    &amp;lt;mx:Model id="myCalcData"&amp;gt;&lt;br/&gt;        &amp;lt;calc&amp;gt;&lt;br/&gt;            &amp;lt;operand1&amp;gt;{number1.text}&amp;lt;/operand1&amp;gt;&lt;br/&gt;            &amp;lt;operand2&amp;gt;{number2.text}&amp;lt;/operand2&amp;gt;&lt;br/&gt;        &amp;lt;/calc&amp;gt;&lt;br/&gt;    &amp;lt;/mx:Model&amp;gt;&lt;br/&gt;    &amp;lt;mx:Panel&amp;gt;&lt;br/&gt;        &amp;lt;mx:Form&amp;gt;&lt;br/&gt;            &amp;lt;mx:FormItem label="Operand 1:"&amp;gt;&lt;br/&gt;                &amp;lt;mx:TextInput id="number1"/&amp;gt;&lt;br/&gt;            &amp;lt;/mx:FormItem&amp;gt;&lt;br/&gt;            &amp;lt;mx:FormItem label="Operand 2:"&amp;gt;&lt;br/&gt;                &amp;lt;mx:TextInput id="number2"/&amp;gt;&lt;br/&gt;            &amp;lt;/mx:FormItem&amp;gt;&lt;br/&gt;            &amp;lt;mx:Button label="Calculate" click="ro.calc(myCalcData.operand1,myCalcData.operand2)"/&amp;gt;&lt;br/&gt;             &amp;lt;mx:Label text="Result: {ro.calc.lastResult} "  fontWeight="bold"/&amp;gt;&lt;br/&gt;        &amp;lt;/mx:Form&amp;gt;    &lt;br/&gt;    &amp;lt;/mx:Panel&amp;gt;        &lt;br/&gt;&amp;lt;/mx:Application&amp;gt;&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;font face='verdana'&gt;Step 4: Create Grails HelloWorldService&lt;/font&gt;&lt;/b&gt; &lt;br/&gt;Create grails new service from IDE. You can also create service by typing command &lt;br/&gt;&lt;font face='Courier New'&gt;grails create-service HelloService&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;public class CalcService&lt;br/&gt;{&lt;br/&gt;  static expose = ['flex-remoting']&lt;br/&gt;  def calc(int number1, int number2) { return number1 + number2 }&lt;br/&gt;}&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;font face='verdana'&gt;&lt;b&gt;Step 5: Update configuration &lt;/b&gt;&lt;br/&gt;Next step is to update configuration file, Config.groovy to enables web tier compiler for flex. Again, I am using similar file as in the example provided on grails website.&lt;br/&gt;&lt;font face='Courier New'&gt;&lt;br/&gt;// enables the webtier compiler for all environments&lt;br/&gt;&lt;/font&gt;&lt;font face='verdana'&gt;&lt;br/&gt;&lt;b&gt;Step 6: Run using command line&lt;/b&gt;&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;font face='verdana'&gt;We are almost done, type in command line at project root to run the projectgrails run-app&lt;br/&gt;&lt;br/&gt;Type in browser: http://localhost:8080/MyGrails/calc.mxml&lt;br/&gt;&lt;br/&gt;&lt;img src='http://lh3.ggpht.com/_Ij0FyB8Wu5Q/Sbfqn0U8m-I/AAAAAAAAAKM/1YP2AoCyeko/%5BUNSET%5D.jpg?imgmax=800' style='max-width: 800px;'/&gt;&lt;br/&gt;You may need to change port, application context if you are using different configuration.&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=fdf72649-52e9-42dc-b212-9ec0817f4e22' class='zemanta-pixie-img'/&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/19518284-8584213247971948689?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/8584213247971948689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=8584213247971948689&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8584213247971948689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/8584213247971948689'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2009/03/grails-flex-and-myeclipse_2766.html' title='Grails, Flex and MyEclipse'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_Ij0FyB8Wu5Q/Sbfqn0U8m-I/AAAAAAAAAKM/1YP2AoCyeko/s72-c/%5BUNSET%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-216168348211293680</id><published>2008-05-25T12:05:00.000-05:00</published><updated>2008-05-25T22:25:11.865-05:00</updated><title type='text'>Webservices with return type List&lt;T&gt;</title><content type='html'>&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;I had written few web service which were returning List&lt;t&gt;. Following are my findings when working with that.&lt;br /&gt;&lt;br /&gt;Axis2 did not generate definition of T in wsdl. So to over come that problem I created a dummy method setT(T t) in order to get type definition of T generated in wsdl. Even though this is work around and it did not highlight or resolve the actual problem.&lt;br /&gt;&lt;br /&gt;Axis2 generated List&lt;t&gt; return type as anyType Object. Which created problem during client side code generation. The wsdl published the return type as anyType, Client had no way of determining what type of return object to be generated. So to be type safe I changed the implementation from List&lt;t&gt; to T[]. Now while I believe type List will always be generated as anyType, I do think that List&lt;t&gt; should not be generated as anyType. Tools should be smart enough to generate List&lt;t&gt; as ArrayOfSpecificType in wsdl.&lt;br /&gt;I think that is either due to two reasons,&lt;br /&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;Tools have not caught upto the JDK5 &lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;The specific way Java implements Generics, by using erasure, List&lt;t&gt; becomes List which creates problem for the tool as tools have no way of identifying what type of list was that.&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;t&gt;&lt;br /&gt;There are some other minor problems I faced while using array. I used method toArray(T[] t) to convert my List&lt;t&gt; to Array. The method required me to pass a type T[] t. I created T[] t = new T[?]. I put number 3 - just randomly- to see if it all works. Service worked it generated response and it also appended two more elements named item1 and item2. I was clueless for a while where this sub elements are getting generated. Then it occurred to me the creation of array with three elements is putting it there. Finally, I settled with T[0]. But the problem with that is when result set was 0, client threw error stating unexpected element of type XXXXResponse. I believe this is a bug.&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-216168348211293680?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/216168348211293680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=216168348211293680&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/216168348211293680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/216168348211293680'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2008/05/webservices-with-return-type-list.html' title='Webservices with return type List&amp;lt;T&amp;gt;'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-5522788212508841255</id><published>2007-07-02T11:36:00.000-05:00</published><updated>2007-07-02T13:54:04.582-05:00</updated><title type='text'>Struts: Creating Custom Validator</title><content type='html'>&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;b&gt;Creating Custom Validator&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Idea was to create custom password validator which will not allow certain words to be password. This included common words like password, companyname, abc, 123 etc. Also this requirement will be extended in future to disallow password being same as first name, last name, phone numbers, email address etc.&lt;br /&gt;&lt;br /&gt;As direct implementation one can always override validate method in the Action Form class for the form. But since password field existed in multiple forms it made more sense to make generic validator which can be added to validation-rules.xml file for the application.&lt;br /&gt;&lt;br /&gt;Add following section in validation-rules.xml file. This describes validation rule.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-family:courier new,monospace;"&gt;&lt;span style="font-size:85%;"&gt;  &lt;blockquote&gt; &amp;lt;validator name="custompassword" classname="com.web.helper.CustomValidationUtility" method="validatePassword" methodparams="java.lang.Object,                             org.apache.commons.validator.ValidatorAction,                             org.apache.commons.validator.Field,                             org.apache.struts.action.ActionMessages,                             org.apache.commons.validator.Validator,                             javax.servlet.http.HttpServletRequest" depends="" msg="errors.password"&amp;gt;&amp;lt;/validator&amp;gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new,monospace;"&gt;&lt;span style="font-size:85%;"&gt;&lt;validator name="custompassword" classname="com.web.helper.CustomValidationUtility" method="validatePassword" methodparams="java.lang.Object,                            org.apache.commons.validator.ValidatorAction,                            org.apache.commons.validator.Field,                            org.apache.struts.action.ActionMessages,                            org.apache.commons.validator.Validator,                            javax.servlet.http.HttpServletRequest" depends="" msg="errors.password"&gt;&lt;/validator&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Add the rule for the form that we need to validate.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new,monospace;"&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&amp;lt;!-- change password --&amp;gt;&lt;br /&gt;&amp;lt;form name="/change-password"&amp;gt;&lt;br /&gt; ...&lt;br /&gt;&amp;lt;field property="newPassword" depends="&lt;b&gt;custompassword&lt;/b&gt;"&amp;gt;&lt;br /&gt; ...&lt;br /&gt;&amp;lt;/field&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;br /&gt;&lt;br /&gt;Create custom validator classes as&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new,monospace;"&gt;&lt;span style="font-size:85%;"&gt;package com.web.helper;&lt;br /&gt;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;&lt;br /&gt;import org.apache.commons.validator.Field;&lt;br /&gt;import org.apache.commons.validator.GenericValidator;&lt;br /&gt;import org.apache.commons.validator.Validator;&lt;br /&gt;import org.apache.commons.validator.ValidatorAction;&lt;br /&gt;import org.apache.commons.validator.util.ValidatorUtils;&lt;br /&gt;import org.apache.struts.action.ActionErrors;&lt;br /&gt;import org.apache.struts.action.ActionMessages;&lt;br /&gt;import org.apache.struts.validator.Resources;&lt;br /&gt;&lt;br /&gt;public class CustomValidationUtility implements Serializable&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public static boolean validatePassword(&lt;br /&gt;Object bean,&lt;br /&gt;ValidatorAction va,&lt;br /&gt;Field field,&lt;br /&gt;ActionMessages messages,&lt;br /&gt;Validator validator,&lt;br /&gt;HttpServletRequest request) {&lt;br /&gt;&lt;br /&gt;System.out.println("Here now");&lt;br /&gt;String value = ValidatorUtils.getValueAsString(bean,                                                   field.getProperty());&lt;br /&gt;List invalidPasswordList = new ArrayList();&lt;br /&gt;invalidPasswordList.add("password");&lt;br /&gt;invalidPasswordList.add("companyname");&lt;br /&gt;invalidPasswordList.add("abc");&lt;br /&gt;invalidPasswordList.add("123");&lt;br /&gt;&lt;br /&gt;if (!GenericValidator.isBlankOrNull(value)) {&lt;br /&gt;   try {&lt;br /&gt;       if (invalidPasswordList.contains(value)) {&lt;br /&gt;           messages.add(field.getKey(),&lt;br /&gt;           Resources.getActionError(&lt;br /&gt;                           request,&lt;br /&gt;                           va,&lt;br /&gt;                           field));&lt;br /&gt;&lt;br /&gt;           return false;&lt;br /&gt;       }&lt;br /&gt;   } catch (Exception e) {&lt;br /&gt;       messages.add(field.getKey(),&lt;br /&gt;       Resources.getActionError(&lt;br /&gt;       request,&lt;br /&gt;       va,&lt;br /&gt;       field));&lt;br /&gt;       return false;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return true;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;That's it.&lt;br /&gt;&lt;b&gt;Roadblocks:&lt;/b&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;One of the problem I faced while working on this in eclipse + wtp that the class was not included in class path automatically. I have to stop server + Compile Clean + Publish + Restart the server for each change I made. I struggled with following exceptions. First was loadValidationActionClass method threw ValidatorException. This is because the my ValidationAction class i.e. CustomValidationUtility was not in classpath. I hoped that WTP will take care of this dynamically, but for some reason it didn't&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Second exception was regarding the parameter of my validation method, they have to exactly match as given in validation-rules.xml.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Third problem faced was whether to use ActionErrors or ActionMessages as parameter. There are numerous example out on the web for custom validator to use ActionErrors. It gave me NullPointerException. On debugging I found out that errors parameter in the method was null. I switched it to ActionMessages (which is parent class of ActionError) and it worked. (Of course, WTP made me do entire trip of stopping, cleaning, compiling, publishing, and starting)&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Some other problems other people faced working on this (which I found out while google-ing): You have to be absolutely sure which version of Struts and commons validator you are using. Struts 1.1 goes with commons-validator 1.1 and Struts 1.2 goes with Commons-validator 1.3. People spent frustrating amount of effort to resolve error only to find out they have mismatched library.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Usage and/or Extension of above idea&lt;/b&gt;&lt;br /&gt;If developing commons validator based validation mechanism, above methods can be used to come up with specific validation for those fields which are going to used at multiple places. Advantages of such mechanism is it will save you from writing and debugging java script, can come up with architecture where you can validate it with databases - though approach needs to be well thought out and used sparingly.  (e.g. list of password could have been stored in database tables), comparison with other fields on the page. In such case, I believe that validate method in form should be put to use rather than generic validations. Also above mechanism for validation can be used when your validation is interdependent on multiple fields on the same form.&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-5522788212508841255?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/5522788212508841255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=5522788212508841255&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/5522788212508841255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/5522788212508841255'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2007/07/struts-creating-custom-validator.html' title='Struts: Creating Custom Validator'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-115325260431370650</id><published>2006-07-18T14:56:00.000-05:00</published><updated>2006-07-23T19:14:09.060-05:00</updated><title type='text'>Problem with mapping Nested Objects using Struts</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;I was working on designing a specific requirement where UI was a four step wizard. User will provide information in this four pages and submit the information to be stored in database. The way information was organized on UI (jsp) was different than the way it needed to be represented in DTO (or domain objects).&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;However, a good review pointed out that use of series of request.getParameter is not good idea. There must be good way to get the data map to Domain objects by using struts. If the data elements were linear ( not mapped and not indexed) Struts does map it quite well with ActionForm. You can use commons beanutils' BeanProperties.copyProperties(Object dest, Object source). But normally the object representation is not linear. Objects have association and multiplicity. (See simple example below)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;It seems there is a problem with struts, when it comes to populating action form when jsp contains nested beans (or for that matter indexed beans). It simply does not work. Howerver, using nested tag library, i was able to get the JSP displayed properly with correct parameter name. The problem occurs when i try to submit the JSP page. It throws IllegalArgumentException: No Bean specified. I think I am not doing anything wrong. But, not sure.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Here is what I am trying to do. I have a JSP page with customer information(name, phone, email and address) where address contains(addres1, address2, city, state and zipcode). For purpose of simplicity I have kept all parameters as String. (Couldn't figure out easy way to link files, so I just pasted here.)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;Address.java&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:trebuchet ms;"&gt;package com.learning.struts.action;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;public class Address {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String address1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String address2;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String city;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String state;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String zipcode;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getAddress1() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return address1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setAddress1(String address1) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.address1 = address1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getAddress2() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return address2;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setAddress2(String address2) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.address2 = address2;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getCity() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return city;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setCity(String city) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.city = city;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getState() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return state;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setState(String state) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.state = state;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getZipcode() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return zipcode;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setZipcode(String zipcode) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.zipcode = zipcode;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;CustomerDTO.java&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:trebuchet ms;"&gt;package com.learning.struts.action;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;public class CustomerDTO implements java.io.Serializable{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String phone;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String email;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private Address address;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public Address getAddress() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return address;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setAddress(Address address) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.address = address;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getEmail() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return email;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setEmail(String email) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.email = email;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getName() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setName(String name) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.name = name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getPhone() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return phone;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setPhone(String phone) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.phone = phone;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;code&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;blockquote&gt;&lt;code&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;strust-config.xml&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1" ?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE struts-config PUBLIC&lt;br /&gt;"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"&lt;br /&gt;"http://struts.apache.org/dtds/struts-config_1_2.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;struts-config&amp;gt;&lt;br /&gt;&amp;lt;form-beans&amp;gt;&lt;br /&gt;&amp;lt;form-bean name="customerForm" type="org.apache.struts.action.DynaActionForm"&amp;gt;&lt;br /&gt;&amp;lt;form-property name="page" type="java.lang.String"/&amp;gt;&lt;br /&gt;&amp;lt;form-property name="customer" type="com.learning.struts.action.CustomerDTO"/&amp;gt;&lt;br /&gt;&amp;lt;/form-bean&amp;gt;&lt;br /&gt;&amp;lt;form-bean name="customerForm1" type="com.learning.struts.action.PageActionForm"&amp;gt;&lt;br /&gt;&amp;lt;form-property name="page" type="java.lang.String"/&amp;gt;&lt;br /&gt;&amp;lt;form-property name="customer" type="com.learning.struts.action.CustomerDTO"/&amp;gt;&lt;br /&gt;&amp;lt;/form-bean&amp;gt;&lt;br /&gt;&amp;lt;/form-beans&amp;gt;&lt;br /&gt;&amp;lt;global-forwards&amp;gt;&lt;br /&gt;&amp;lt;/global-forwards&amp;gt;&lt;br /&gt;&amp;lt;action-mappings&amp;gt;&lt;br /&gt;&amp;lt;action path="/submit"&lt;br /&gt;type="com.learning.struts.action.IndexedNestedFormStrutsAction"&lt;br /&gt;validate="false"&lt;br /&gt;input="customer-address1.jsp"&lt;br /&gt;name="customerForm1"&amp;gt;&lt;br /&gt;&amp;lt;forward name="success" path="/jsp/index.jsp"/&amp;gt;&lt;br /&gt;&amp;lt;/action&amp;gt;&lt;br /&gt;&amp;lt;/action-mappings&amp;gt;&lt;br /&gt;&amp;lt;/struts-config&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;customer-address.jsp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&amp;lt;%@ page language="java" contentType="text/html; charset=ISO-8859-1"&lt;br /&gt;pageEncoding="ISO-8859-1"%&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&amp;gt;&lt;br /&gt;&amp;lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&amp;gt;&lt;br /&gt;&amp;lt;%@ taglib uri="/WEB-INF/struts-nested.tld" prefix="nested" %&amp;gt;&lt;br /&gt;&amp;lt;html:html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;html:form action="submit.do" method="post"&amp;gt;&lt;br /&gt;&amp;lt;html:hidden property="page" value="page-1"/&amp;gt;&lt;br /&gt;customer.name :&amp;lt;html:text property="customer.name" value="k"/&amp;gt;&lt;br /&gt;customer.phone: &amp;lt;/p&amp;gt;&amp;lt;html:text property="customer.phone" value="k"/&amp;gt;&lt;br /&gt;customer.email: &amp;lt;/p&amp;gt;&amp;lt;html:text property="customer.email" value="k"/&amp;gt;&lt;br /&gt;&amp;lt;nested:nest property="customer.address"&amp;gt;&lt;br /&gt;customer.address.address1: &amp;lt;/p&amp;gt;&amp;lt;nested:text property="address1" value="k" /&amp;gt;&lt;br /&gt;customer.address.address2: &amp;lt;/p&amp;gt;&amp;lt;nested:text property="address2"  value="k"/&amp;gt;&lt;br /&gt;customer.address.city: &amp;lt;/p&amp;gt;&amp;lt;nested:text  property="city" value="k" /&amp;gt;&lt;br /&gt;customer.address.state: &amp;lt;/p&amp;gt;&amp;lt;nested:text property="state" value="k" /&amp;gt;&lt;br /&gt;customer.address.zipcode: &amp;lt;/p&amp;gt;&amp;lt;nested:text property="zipcode" value="k" /&amp;gt;&lt;br /&gt;&amp;lt;/nested:nest&amp;gt;&lt;br /&gt;&amp;lt;html:submit&amp;gt;&amp;lt;/html:submit&amp;gt;&lt;br /&gt;&amp;lt;/html:form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html:html&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;action path="/submit"&gt;&lt;/action&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;font-size:85%;"  &gt;IndexedNestedFormStrutsAction.java&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;public class IndexedNestedFormStrutsAction extends Action {&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;&lt;br /&gt;public ActionForward execute(ActionMapping map, ActionForm form, HttpServletRequest req, HttpServletResponse res) throws Exception {&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;        DynaActionForm daForm = (DynaActionForm)form;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;        CustomerDTO customer = (CustomerDTO)daForm.get("customer");&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;        System.out.println("Customer : " + customer);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;        return map.findForward("success");&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;    }&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;font-size:85%;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;On debugging this, it throws up folloing exception :&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;java.lang.IllegalArgumentException: No bean specified&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.commons.beanutils.PropertyUtilsBean.getPropertyDescriptor(PropertyUtilsBean.java:751)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:937)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:493)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:816)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:203)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;    at java.lang.Thread.run(Thread.java:595)&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=";font-family:trebuchet ms;font-size:85%;"  &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;But I thought that it may be problem with DynaActionForm so I created ActionForm derivative and try if it properly maps the nested bean. Here is the code for that:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;font-size:100%;"  &gt;PageActionFrom.java &lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:trebuchet ms;"&gt;package com.learning.struts.action;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;import org.apache.struts.action.ActionForm;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;public class PageActionForm extends ActionForm {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private String page;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    private CustomerDTO customer;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public CustomerDTO getCustomer() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return customer;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setCustomer(CustomerDTO customer) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.customer = customer;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public String getPage() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        return page;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    public void setPage(String page) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;        this.page = page;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;But it does not work and though it generated the JSP correctly. When you do view source on generated html it will create proper dot notaion name for each input element. However, submitting and getting the values even inside ActionForm parameter of Action does not work. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;I did find out some open source project in works which are working to deal with this problem. But they are in still 0.x version. I think this is something struts should do automatically rather than any plugin framework. Please correct me if I am wrong.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-115325260431370650?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/115325260431370650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=115325260431370650&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115325260431370650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115325260431370650'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2006/07/problem-with-mapping-nested-objects.html' title='Problem with mapping Nested Objects using Struts'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-115266375686522317</id><published>2006-07-11T19:16:00.000-05:00</published><updated>2006-10-12T02:35:42.696-05:00</updated><title type='text'>Random Thoughts: EJB3 Vs Spring</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-size:100%;"&gt;Following are just my random thoughts. I am not trying to determine which one is better. I think it is pretty much decided that both are going co-exists.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Spring: IoC Container and Framework Library&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;I think it is good idea to understand Spring in two aspects. &lt;a&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul  style="font-family:trebuchet ms;"&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;First &lt;/span&gt;it is IoC container. This container is its core concepts. EJB as the SPEC is in direct competition. Question is: Do you want to use Spring IoC container or EJB Container?&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Second &lt;/span&gt;aspects of the Spring Framework is all the helper classes which makes the development so easy. Like JdbcTemplate, Hibernate helper classes, etc. EJB does not provide such classes. Those gaps are filled up by the JBoss Seam Framework and the like. You can use EJB Container and still use Spring Framework Libraries.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family:trebuchet ms;"&gt;So along with Spring Vs EJB, it is also Spring vs JBoss Seam and the like. &lt;a&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Spring Not a Spec&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Spring, though opensource, is controlled by Interface 21, a commercial company. Interface 21 controls (atleast decides) what needs to be in next phase and hires programmer to do it. Don't get me wrong, I really like Spring. As a developer, it is really nice experience. How simple it makes to develop application and test it. But the fact remains that in the long run, we have to "wish" (or influence) that Interface 21 makes correct choices. Also remember that once we use spring we are using "tool specific classes and libraries" so we cannot decide to change it to different platform overnight.&lt;br /&gt;Even though it uses its own library. It is based on very sound design principle. Design by Interface. Framework actually builds on top of it to provide re-usable code. For example, never worrying about handling connections. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;With EJB, if you dont like a vendor you can still move to different vendor. If you dont like EJB at all depending upon your design you can still convert it to different technologies as there is not dependance on specific libraries. (Meaning dependency is there but on little higher level)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;EJBs dont provide that kind of framework. It does not provide you reusable classes library. It does not provide helper classes for sending email for different implemenations.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Will Spring remain light?&lt;a&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;But with all these introduction in Spring, how light is spring or how light will spring remain. But the answer lies in its core design. Since the core concepts behind it is Design by Interface and Inversion of Control. It allows to selectively use areas which we require. You dont want to use MVC dont incldue that jar. If you only want to use with regards to JDBC operations, only use spring-jdbc.jar. It will stay light as much your requirements demand it to remain light.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;EJB: Market Availability&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Though it is too early to say how light is JEE. It is just out and there are really few implementations available. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;EJB still implements "Remote-ness"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;One difference between these two choices still exists, that EJB3 will still do remoting. Spring on the other hand does not do remoting by default. So decision has to be made what kind of architecture is required keeping in mind business application scenario. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Thoughts about RPC&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Also one thing to notice here is that RPC eventually will go out of fashion (IMHO). Ultimately, architectures like SOA where core concept is to exchange data rather than invoking behavior remotely. It is more loosely coupled, more reusable, and it also has advantage of platform independance.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Separating JPA out of EJB&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;One good things EJB Spec3 has done has separated JPA out of EJB Spec.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:trebuchet ms;font-size:100%;"  &gt;Again Hibernate will be JPA compliant in coming days. There are already articles floating around how to use Spring with JPA.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;What are the other benefits of EJB3? &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;Container Managed Persistence&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;If you are using Container Managed Persistence, it manages the state of entities. Meaning it calls update insert methods on its own. It has container managed persistence. Meaning you dont have to call your insert update delete. Container will manage that for you. This is a really good advantage. With Spring Framework, you still need to call specific  classes, SimpleJDBCTemplate.update, or session.update if you are using Hibernate. With EJB once configured with CMP, you dont do anything. You save that one method call. Calls will be made for you before and after business methods. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;Message Driven Beans&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;With EJB Container you will have MessageDrivenBeans. i.e. you will have mechanisms to write consumers of Messages. With Spring you have to choose a separate provider for the same. Which gives you more flexibility. Spring delegates that work. Again principle on which spring is based: Do not re-write it if somebody is already doing it in good way. Rather than that just provide the loose interface and bunch of classes with re-usable code. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;Clustering&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Benefits of clustering and are anyways provided by application server. Even for that matter Tomcat provides clustering now. You can still develop Spring application and deploy it in different clusters in Tomcat. You dont need EJB Container to have component level clustering.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Spring is already a winner it. It has made EJB people change the spec. EJB3 now looks less similar to EJB2 and more similar to Spring. They have almost every aspect which spring got it correct. Aspects are now Interceptors. (Though this was any ways used by EJB container provider in their implementations, no programmatic mechanisms were provided for Bean Developer though)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:trebuchet ms;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;XML vs Annotations&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:trebuchet ms;" &gt;&lt;span style="font-weight: bold;"&gt;Transactions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;With regards to Transaction declaration as Annotations. I must say, I like XML. No matter how much verbose. It is still good. Rather than my transaction strategy littered over code, i would like to have it one place/area. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:trebuchet ms;" &gt;&lt;span style="font-weight: bold;"&gt;Security&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Dont let me wander in code to find out what security rules are implemented. Anyways, Spring has also come us with Annotations specific declarations allowing you to do quick and dirty work though. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Do we need IoC Container Spec?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Do we need a spec so other providers can come up with their own implementations of IoC container? Or have we already convoluted J2EE area with so many specifications and implementation? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;span style="font-weight: bold;"&gt;Preference&lt;a&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Spring will work inside container and outside container. Spring is really great for small application because it is really easy to develop. With Spring 2.0's goal being easier XML Config files and allowing Annotations and its integration with AspectJ. Spring does have capability of using it in bits and pieces, meaning you may just use it in Middel Tier, you choose to use JMS features.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;JEE spec will need a container. Also the choice depend upon the business case for which the application is getting developed. If the application is big in terms of scope or it is expected that it live long time while going multiple phase changes then I think it is better to stick with Standard Spec. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-115266375686522317?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/115266375686522317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=115266375686522317&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115266375686522317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115266375686522317'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2006/07/random-thoughts-ejb3-vs-spring.html' title='Random Thoughts: EJB3 Vs Spring'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-115113029031974805</id><published>2006-06-24T01:13:00.000-05:00</published><updated>2006-12-13T11:57:23.146-06:00</updated><title type='text'>Thoughts: Open-Closed Principle</title><content type='html'>&lt;p&gt;&lt;span style="font-family:trebuchet ms;"&gt;Just read an article about &lt;/span&gt;&lt;a href="http://www.objectmentor.com/resources/articles/ocp.pdf"&gt;&lt;span style="font-family:trebuchet ms;"&gt;Open Closed Principle&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;[pdf]. It is good revision and insight into object oriented principles.&lt;br /&gt;&lt;br /&gt;Very briefly, &lt;strong&gt;&lt;em&gt;Open Closed Principle says to design your class which are close for modification and open for extension. &lt;/em&gt;&lt;/strong&gt;As author suggests one way of doing this is to program to interfaces. So that the classes in design are closed for modification and open for extension.&lt;br /&gt;How to ensure that the class designed is closed for modification? Though author points out that you can't close the class entirely. What is the generic questions checklist that we need to go through to verify that the class is closed for modification.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Is the class close for modification due to change in business requirements? &lt;/strong&gt;&lt;br /&gt;Business requirements change over time. The question we need to ask while reviewing the design is that have we designed the class in manner that it is able to display some flexibility of handling the changed requirement by extending it and not by modifying it. Are the safeguards in place which prevents changing the classes?&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Will the changes in classes on which this class depends bring change in this class?&lt;/strong&gt;&lt;br /&gt;List down all classes which are used by the class under review. All the objects which are part of pre-condition for this class to operate.&lt;br /&gt;Determine that how close is the current class' design in order to accomodate changes in these classes.&lt;br /&gt;Key question: Are the contract between these classes defined by interfaces? (This leads to another principle of &lt;/span&gt;&lt;a href="http://www.objectmentor.com/resources/articles/dip.pdf"&gt;&lt;span style="font-family:trebuchet ms;"&gt;Dependancy Inversion Principle&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;[pdf])&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Will the changes in the classes which depends on this class bring change in this class?&lt;/strong&gt;&lt;br /&gt;List down all the classes which will use the current class.&lt;br /&gt;Determine that how close is the current class' design in order to service the changing demands of these classes/objects.&lt;br /&gt;Key question: Is Contract between these classes defined by interfaces?&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Has design considered multiplicity requirements?&lt;/strong&gt;&lt;br /&gt;Lets say that sound contract exists between the classes on which the class depends and the classes which depends on this particular class.&lt;br /&gt;Determine the impact of change in cardinality requirement of contract. A class may play different role. Does this class play role of "creator" of objects, "worker" on objects and/or "delegator" to objects. The contract defined in interface does it cover scenarios like: what if this class needs to "create" more than one objects in future. Is this class close enough for modification and open enough for extension to allow to "work" on multiple objects.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Again I think all this questions needs to be asked keeping in mind the domain for which it is getting designed. This questions are subjective to functional area application is trying to solve.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-115113029031974805?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/115113029031974805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=115113029031974805&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115113029031974805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/115113029031974805'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2006/06/thoughts-open-closed-principle.html' title='Thoughts: Open-Closed Principle'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-114069171217351831</id><published>2006-02-23T04:32:00.000-06:00</published><updated>2006-02-23T05:16:25.453-06:00</updated><title type='text'>Configuring Subversion with Netbeans</title><content type='html'>&lt;strong&gt;Configure Subversion with Netbeans&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Step 1: Download Subversion profile from site &lt;a href="http://vcsgeneric.netbeans.org/profiles/index.html"&gt;http://vcsgeneric.netbeans.org/profiles/index.html&lt;/a&gt;&lt;br /&gt;I configured it with Netbeans 4.1. The site also have profiles for other version of netbeans.&lt;br /&gt;&lt;br /&gt;Step 2: Open Netbeans&lt;br /&gt;&lt;br /&gt;Step 3: Click on Tools --&gt; Update Center&lt;br /&gt;&lt;br /&gt;Step 4: Select Install Manually downloaded Modules (.nbm Files)&lt;br /&gt;&lt;br /&gt;Step 5: Click on Add and select the file that you downloaded. Finish the Wizard&lt;br /&gt;&lt;br /&gt;Step 6: Click on Versioning --&gt; Versioning Manager. In this popup add the working directory of the project and repository URL for Subversion. For instance I added c:\projects\projectname\src and repository as &lt;a href="file:////svn"&gt;file:////svn&lt;/a&gt; ( mapped to c:\svn, if working on windows environment)&lt;br /&gt;&lt;br /&gt;Step 7: Done. Now you can right click the project and view the files and status for the same.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-114069171217351831?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/114069171217351831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=114069171217351831&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/114069171217351831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/114069171217351831'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2006/02/configuring-subversion-with-netbeans.html' title='Configuring Subversion with Netbeans'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-114051887528220835</id><published>2006-02-21T04:37:00.000-06:00</published><updated>2006-07-05T02:01:09.200-05:00</updated><title type='text'>Properties file or XML File</title><content type='html'>While working on Java Projects we usually come to question whether to use properties file or to use XML files for reading configuration information.&lt;br /&gt;&lt;br /&gt;Before we consider what solution should be used, first let's see what kind of the configuration data is involved.&lt;br /&gt;&lt;br /&gt;Configuration data are range from simpler items like server urls, schema name, database environment, mailing servers, etc. This kind of data can be classified as name=value pair. No relationship or hierarchy exist between them.&lt;br /&gt;&lt;br /&gt;The other cases of configuration data that might be used within project contains relationship within data elements. One of the example of such data is struts-config.xml. For this kind of data they will be more or less stored as Java Objects.&lt;br /&gt;&lt;br /&gt;Once we made the classification decision is simple.&lt;br /&gt;&lt;br /&gt;Use properties file for configuration data which is flat in nature. Data elements does not contain any relationship or hierarchy. Using XML file to store will involve parsing overhead without any significant advantage.&lt;br /&gt;&lt;br /&gt;XML file usage is justified only when we are going to create Java Objects out of config data elements having relationship between them.&lt;br /&gt;&lt;br /&gt;One of the pitfalls using XML file to store config file is to go on overkill and start integrating logic in XML tags. Make sure that it is only config data and you are not actually programming in XML.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-114051887528220835?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/114051887528220835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=114051887528220835&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/114051887528220835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/114051887528220835'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2006/02/properties-file-or-xml-file.html' title='Properties file or XML File'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19518284.post-113353910714941947</id><published>2005-12-02T09:56:00.001-06:00</published><updated>2010-01-07T22:09:45.958-06:00</updated><title type='text'>Sun Open sourcing JES</title><content type='html'>Sun has open sourced JES (Java Enterprise System) including Java application server platform and identity manager suite. CPCR7WHNFVTX&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19518284-113353910714941947?l=blog.kartikshah.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kartikshah.com/feeds/113353910714941947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19518284&amp;postID=113353910714941947&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/113353910714941947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19518284/posts/default/113353910714941947'/><link rel='alternate' type='text/html' href='http://blog.kartikshah.com/2005/12/sun-open-sourcing-jes.html' title='Sun Open sourcing JES'/><author><name>Kartik Shah</name><uri>https://profiles.google.com/102621938763577509009</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-n1Md9r0lKUE/AAAAAAAAAAI/AAAAAAAAAXg/3pF1tA5IcEI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
