<?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-7910126</id><updated>2012-01-25T12:59:42.864+07:00</updated><category term='Hotspot'/><category term='AOP'/><category term='Fortress'/><category term='Twitter'/><category term='distro'/><category term='JVMIT'/><category term='Map-Reduce'/><category term='OpenLaszlo'/><category term='debugging'/><category term='type system'/><category term='BarCamp'/><category term='XUL'/><category term='Qdg'/><category term='RIA'/><category term='Interview'/><category term='bytecode'/><category term='Productivity'/><category term='GORM'/><category term='SAP'/><category term='Scala'/><category term='Election'/><category term='Hangman'/><category term='BDD'/><category term='Language'/><category term='Hadoop'/><category term='ECO'/><category term='HBase'/><category term='Grails'/><category term='thought'/><category term='Geogia'/><category term='GJIT'/><category term='ZK'/><category term='Mobile'/><category term='Morph'/><category term='Callsite'/><category term='jQuery'/><category term='Thai'/><category term='Optimisation'/><category term='HPC'/><category term='Bazaar'/><category term='Java'/><category term='Summer of Code'/><category term='Groovy'/><category term='AspectJ'/><category term='SPLAT'/><category term='Linux'/><category term='NHibernate'/><category term='JavaScript'/><category term='Bangkok'/><category term='.NET'/><title type='text'>CK's Blog</title><subtitle type='html'>About anything interests me ...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default?start-index=101&amp;max-results=100'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>110</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7910126.post-5269371082282233585</id><published>2011-12-24T21:41:00.001+07:00</published><updated>2011-12-24T21:41:21.178+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='type system'/><title type='text'>Learning to know Featherweight Java - An Easy Way</title><content type='html'>&lt;p&gt;It's very long time since last my last post and I am still learning how to properly prove type soundness of a programming language. Here's a list of &lt;a href="http://www.cs.cornell.edu/Courses/cs4110/2010fa/schedule.php"&gt;lectures&lt;/a&gt; from Cornell that I've been reading and they're quite good to understand.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5269371082282233585?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5269371082282233585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5269371082282233585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5269371082282233585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5269371082282233585'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2011/12/learning-to-know-featherweight-java.html' title='Learning to know Featherweight Java - An Easy Way'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2295669119327530579</id><published>2010-02-09T20:45:00.001+07:00</published><updated>2010-02-09T20:48:19.381+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='type system'/><title type='text'>Type system primer</title><content type='html'>Given an expression e, a type T and a dictionary TT&lt;br /&gt;that maps variables to type, the notation&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;TT |- e : T&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;roughly means&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;T = typecheck(TT, e)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and the horizontal bar notation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;P1     P2     P3&lt;br /&gt;----------------&lt;br /&gt;      Q&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;means&lt;br /&gt;&lt;br /&gt;Q if P1 and P2 and P3&lt;br /&gt;&lt;br /&gt;from: &lt;a href="http://wiki.jvmlangsummit.com/pdf/28_Siek_gradual.pdf"&gt;http://wiki.jvmlangsummit.com/pdf/28_Siek_gradual.pdf&lt;/a&gt; (slide 6)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-2295669119327530579?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2295669119327530579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2295669119327530579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2295669119327530579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2295669119327530579'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2010/02/type-system-primer.html' title='Type system primer'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5494668668733484493</id><published>2009-12-07T18:55:00.001+07:00</published><updated>2009-12-07T18:57:50.263+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='GJIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Groovy Performance Update - Long running programs are as fast as Java</title><content type='html'>It's been almost one and a half year that I have not updated anything related to Groovy performance in general. As I posted previously that I have been still doing on this topic, now it's time for updating a bit.&lt;br /&gt;&lt;br /&gt;The technique is to hook the callsite caching process. Each callsite-to-be-called is profiling, its runtime information is analysed, and the faster code for it is then generated. The callsite is replaced by its equivalent direct call. Replacement is done, anyway, through JVMTI similar to the trick implemented in the previous version of GJIT. However, the concept used in this version of GJIT has been changed from &lt;i&gt;totally automatic&lt;/i&gt; to &lt;i&gt;manually controlled&lt;/i&gt;. This means that only selected callsites will be optimised, and you, as a developer, can control this optimisation via the mechanism provided. This concept is not that new, I have &lt;a title="posted" href="http://chanwit.blogspot.com/2008/01/application-specific-performance-tuning.html" id="cfeh"&gt;posted&lt;/a&gt; about it a while ago.&lt;br /&gt;&lt;br /&gt;Latest results I came up with are micro-benchmarks. All of them in the long run, after related call sites are optimised, are running at the same speed as Java programs.&lt;br /&gt;&lt;br /&gt;Let's examining the graph of the Fibonacci benchmark:&lt;br /&gt;&lt;div id="nafk" style="text-align: left;"&gt;&lt;img src="http://docs.google.com/File?id=dhddrfh9_6297zqxt2dr_b" height="310" width="660" /&gt;&lt;/div&gt;&lt;br /&gt;You can see that there are 2 interesting regions of graphs before the Groovy program getting the same speed as Java.&lt;br /&gt;1. At the beginning, there is an overhead of profiling the callsite instantiation system of Groovy.&lt;br /&gt;2. For background optimisation, an optimiser thread requires times for analysis and code generation. (I also make a note on the overhead of HotSpot VM, just for referencing).&lt;br /&gt;&lt;br /&gt;After the optimisation phase is completed, the speed of Groovy program goes overlapping with Java. This approach would be working fine for a long running program, but &lt;i&gt;not&lt;/i&gt; for scripting. Why? I left this as an exercise for the readers ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5494668668733484493?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5494668668733484493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5494668668733484493' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5494668668733484493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5494668668733484493'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/12/groovy-performance-update-long-running.html' title='Groovy Performance Update - Long running programs are as fast as Java'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6200999015123484353</id><published>2009-11-14T15:52:00.001+07:00</published><updated>2009-11-14T15:53:51.786+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='thought'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Analysis of static Groovy claims</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Continued from my &lt;a href='http://chanwit.blogspot.com/2009/11/static-groovy-is-it-feasible.html'&gt;last post&lt;/a&gt;, I think I will be in the &lt;a href='http://en.wikipedia.org/wiki/NPOV'&gt;neutral point of view&lt;/a&gt; enough to do the analysis for these &lt;a href='http://groovy.dzone.com/articles/groovy-and-static-compilation'&gt;claims&lt;/a&gt;. All of this analysis are solely based on my opinion, so discussion is always welcome.&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is possible to write a statically typed compiler for Groovy keeping all goodies of the beautiful language.&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is partially true. I do not think I can create a static compiler to cover all Groovy features at once.&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is possible to implement very powerful type inference of local variable and closures, so we don't need to provide verbose type information more than necessary and/or useful for documentation purposes.&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is partially true. A language cannot fully support type inference. Type inference itself has its own limits, and it is a known P-complete or NP-complete problem depending on its implementation) [see &lt;a href='http://portal.acm.org/citation.cfm?id=640132'&gt;this&lt;/a&gt;].&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is possibly to have compile-time metagrogramming (properies, categories, default groovy methods, mixins, ast transformations - all but runtime meta-programmings).&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is also true. But adding more phases to the compiler will make it slow. When the compilation time is slow + startup time of the JVM, you might not be happy using the language as a scripting tool. &lt;a href='http://bracha.org/pluggable-types.pdf'&gt;Pluggable type systems&lt;/a&gt; would be possible to help this issue.&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is possible to support Scala-like traits (also knows as interfaces with default implementation), which is extremly strong meta-programming tool.&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is true. No doubt.&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is even possibly to compile piece of code in so called mixed mode (resolve and call statically what we can and call the rest dynamically). This mode is great for example for mixing computation with building markup or populating UI elements with results of computation.&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is true. There is also something called &lt;a href='http://portal.acm.org/citation.cfm?id=113469'&gt;Soft typing&lt;/a&gt; and &lt;a href='http://ece-www.colorado.edu/%7Esiek/gradual-obj.pdf'&gt;Gradual typing&lt;/a&gt; which could help one archieve both static and dynamic call in the same language. However, the way of building markup can be just a simpler trick. I have it in my last &lt;a href='http://chanwit.blogspot.com/2009/11/static-groovy-is-it-feasible.html'&gt;post&lt;/a&gt;.&lt;br/&gt;&lt;blockquote&gt;&lt;i&gt;It is even possibly that because of type inference staticly compiled code can be a little bit less verbose compare to Groovy (almost no need in 'as' conversion for example).&lt;/i&gt;&lt;br/&gt;&lt;/blockquote&gt;This is probably false. In general, I do not think there will be a better way than a dynamic language to do so.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=60718c76-2cf8-829c-94cc-b60d4cf90404' alt='' 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/7910126-6200999015123484353?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6200999015123484353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6200999015123484353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6200999015123484353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6200999015123484353'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/11/analysis-of-static-groovy-claims.html' title='Analysis of static Groovy claims'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6018750383569367090</id><published>2009-11-12T01:07:00.001+07:00</published><updated>2009-11-12T19:05:11.257+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='thought'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Static Groovy, is it feasible?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Static Groovy seems to be a hot topic. There have been debates about it in the past. And recently, Alex's call for implementation has been &lt;a href='http://groovy.dzone.com/articles/groovy-and-static-compilation'&gt;posted&lt;/a&gt; on Groovy's DZone. Yesterday, Jochen's got his view about it &lt;a href='http://blackdragsview.blogspot.com/2009/11/static-groovy-about-calling-methods.html'&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;To me, I have been (and still) doing somethings to boost Groovy performance. Actually, it is based on the current call site implementation of Groovy 1.6. But that's another approach (As people said, performance is not only concern for static Groovy, early detection of errors is also what they want).&lt;br/&gt;&lt;br/&gt;One of the biggest challenge of implementing static Groovy is that how could we implement a framework like &lt;a href='http://grails.org'&gt;Grails&lt;/a&gt; using it. This is really an interesting question to me, as Grails requires a lot of dynamic features of Groovy. So, I try to summarise what static Groovy should be capable of for making a Grails-like framework happen.&lt;br/&gt;&lt;br/&gt;Firstly, GORM dynamic finders:&lt;br/&gt;This kind of finders mainly uses missingMethod to perform their actions.&lt;br/&gt;&lt;br/&gt;Considering this (posted as a &lt;a href='http://blackdragsview.blogspot.com/2009/11/static-groovy-about-calling-methods.html?showComment=1257928097582#c4777230856299083855'&gt;comment&lt;/a&gt; in Jochen's blog):&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;class C {&lt;br/&gt;  def findBy/s/(Object ...) { .. }&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;You may notice "s" in the method name. It is of type String and can be referenced in the method body.&lt;br/&gt;So this is basically, findBy* of Grails. Missing method could be modelled in the same way. For example,&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;class C2 {&lt;br/&gt;  def /s/(Object ...) { /* doing something with s */ }&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;Secondly, Adding dynamic methods:&lt;br/&gt;This mainly uses in Grails plugins to extend capability of the framework.&lt;br/&gt;The idea of category would be working perfectly for it.&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;main() {&lt;br/&gt;  A.test()&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;class A {&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;class Plugin {&lt;br/&gt;  static test(A self) { .. }&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;Resolving the &lt;b&gt;test&lt;/b&gt; method would be a bit problem as it's not only through the class hierarchy of A, but also other classes that contain methods that &lt;i&gt;crosscut&lt;/i&gt; A. It would be a bit easier for a compiler to resolve them, if we have a marker like &lt;font face='Courier New'&gt;@extension static test(A self) { ... }&lt;/font&gt; to help it.&lt;br/&gt;&lt;br/&gt;Thirdly, interception for implementing invokeMethod:&lt;br/&gt;This may probably involves the concept of AOP. But I will note use its terms here. Actually, the example is came from a work in the AOP area.&lt;br/&gt;&lt;br/&gt;When you are going to intercept call of existing methods, this could be working:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;class C {&lt;br/&gt;  intercept *(X x) {&lt;br/&gt;    proceed(x); // intercepting methodForX only&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;  intercept *(Y y) {&lt;br/&gt;    proceed(y); // intercepting methodForY only&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;  intercept *(Object ...) { ... }&lt;br/&gt;&lt;br/&gt;  def methodForX(X x) { .. }&lt;br/&gt;  &lt;br/&gt;  def methodForY(Y y) { .. }&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;This concept would be called local interception, where an interceptor is capable of only intercepting methods in the same class. System-wide interception would be doing the same. Anyway, it will be something like AspectJ, in eventually.&lt;br/&gt;&lt;br/&gt;To sum up, there are really challenges to implement a static counterpart of Groovy. However as you might see, having enough features to implement a Grails-like framework using such language is not that easy. A lot of things need to be proper implemented. Anyway, this is really an interesting thing to do.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=5286c2c2-6ef5-8ffc-b512-9cee2f2806ae' alt='' 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/7910126-6018750383569367090?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6018750383569367090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6018750383569367090' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6018750383569367090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6018750383569367090'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/11/static-groovy-is-it-feasible.html' title='Static Groovy, is it feasible?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2999115095404508256</id><published>2009-09-04T22:50:00.001+07:00</published><updated>2009-09-04T22:50:55.902+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Using AsmNodeBuilder to Test Bytecodes with Pleasure</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;DSL of Groovy never made me bored. I am working on some bytecode transformation and having a number of tests to run.&lt;br/&gt;Testing low-level transformation means dealing with JVM instructions. For example,&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;ILOAD 0&lt;br/&gt;INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;&lt;br/&gt;LDC 0&lt;br/&gt;INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;&lt;br/&gt;INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter&lt;br/&gt;             .compareLessThan(Ljava/lang/Object;Ljava/lang/Object;)Z&lt;br/&gt;IFEQ L2&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;There is class MethodNode in the tree package of ASM. The class has the field instructions of class InsnList, which contains its method body. In the following, I have &lt;font face='Courier New'&gt;InsnList insn = methodNode.instructions;&lt;/font&gt; to perform some optimisation over it.&lt;br/&gt;&lt;br/&gt;Before making AsmNodeBuilder, I had to create&lt;br/&gt;a test data using Asm's Tree Nodes. Something looks like:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;insn.add(new VarInsnNode(ILOAD, 0))&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;With Groovy and AsmNodeBuilder, now I can write:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;insn.append {&lt;br/&gt;  iload 0&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;When comparing results, I had to do:&lt;br/&gt;&lt;font face='Courier New'&gt;&lt;br/&gt;assert insn.get(0).opcode == ILOAD&lt;br/&gt;assert insn.get(0).var    == 0&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;Now, it becomes:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;assertEquals asm { iload 0 }, insn[0]&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;Of course, I can also do:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;assertEquals asm {&lt;br/&gt;  iload 0&lt;br/&gt;  invokestatic Integer,"valueOf",[int],Integer&lt;br/&gt;}, insn&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;to assert all instructions in the list.&lt;br/&gt;&lt;br/&gt;Look fun? Convinced? There are two classes you may use:&lt;br/&gt;&lt;br/&gt;- &lt;a href='%20http://github.com/chanwit/groovy-aop/blob/c189dcbea716ba871fbb3f0e6ac25e9f9b5a9ff0/src/main/groovy/org/codehaus/groovy/gjit/asm/InsnListHelper.groovy'&gt;InsnListHelper.groovy&lt;/a&gt;&lt;br/&gt;- &lt;a href='http://github.com/chanwit/groovy-aop/blob/c189dcbea716ba871fbb3f0e6ac25e9f9b5a9ff0/src/main/java/org/codehaus/groovy/gjit/asm/AsmNodeBuilder.java'&gt;AsmNodeBuilder.java&lt;/a&gt; (generated from gen_asm_builder.groovy)&lt;br/&gt;&lt;br/&gt;Here's how to&lt;br/&gt;&lt;ol&gt;&lt;li&gt;call InsnListHelper.install() in the very beginning of your Groovy test case.&lt;/li&gt;&lt;li&gt;Write a test case.&lt;/li&gt;&lt;li&gt;use &amp;lt;InsnList&amp;gt;.append { ... } to create a method body.&lt;/li&gt;&lt;li&gt;do your transformation.&lt;/li&gt;&lt;li&gt;assert the result against an asm { ... } block. Note that Groovy's power assertion won't work with the block for some reasons, use assertEquals instead.&lt;/li&gt;&lt;/ol&gt;You can also look at an example &lt;a href='http://github.com/chanwit/groovy-aop/blob/c189dcbea716ba871fbb3f0e6ac25e9f9b5a9ff0/src/test/groovy/org/codehaus/groovy/gjit/asm/transformer/AutoBoxEliminatorTxTests.groovy'&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=ce8ef127-b8ee-8236-989b-c6fc1712e42e' alt='' 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/7910126-2999115095404508256?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2999115095404508256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2999115095404508256' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2999115095404508256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2999115095404508256'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/09/using-asmnodebuilder-to-test-bytecodes.html' title='Using AsmNodeBuilder to Test Bytecodes with Pleasure'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3569200688870287302</id><published>2009-07-26T20:47:00.001+07:00</published><updated>2009-07-26T20:47:47.072+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Improved Complex Number in Groovy</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Thank you for last comment in &lt;a href='http://chanwit.blogspot.com/2009/06/complex-number-in-groovy.html'&gt;the previous blog&lt;/a&gt;. Here's the improved version of Complex Number.&lt;br/&gt;&lt;font face='Courier New'&gt;&lt;br/&gt;Number.metaClass.plus = { n -&amp;gt;&lt;br/&gt;  if(n instanceof Imaginary) {&lt;br/&gt;    new Complex(r:delegate, i:n.v)&lt;br/&gt;  }&lt;br/&gt;}&lt;br/&gt;Number.metaClass.getI = { -&amp;gt;&lt;br/&gt;  new Imaginary(v: delegate)&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;class Complex {&lt;br/&gt;  def r&lt;br/&gt;  def i&lt;br/&gt;  String toString() {&lt;br/&gt;    "$r + ${i}i"&lt;br/&gt;  }&lt;br/&gt;}&lt;br/&gt;class Imaginary {&lt;br/&gt;  def v&lt;br/&gt;  def plus(n) {&lt;br/&gt;    if(n instanceof Number) new Complex(r:n, i:this.v)&lt;br/&gt;  }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;def b = 2 + 2.4.i&lt;br/&gt;def c = 4.2.i + 2&lt;br/&gt;println b&lt;br/&gt;println b.class&lt;br/&gt;println c&lt;br/&gt;println c.class&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=b80e4f4a-bb73-8b86-8857-44f4f2b0671d' alt='' 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/7910126-3569200688870287302?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3569200688870287302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3569200688870287302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3569200688870287302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3569200688870287302'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/07/improved-complex-number-in-groovy.html' title='Improved Complex Number in Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5127783977668891285</id><published>2009-06-11T03:49:00.002+07:00</published><updated>2009-06-11T04:41:20.541+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Complex Number in Groovy</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Here's a quick note of making Groovy to support complex numbers:&lt;br /&gt;&lt;br /&gt;1. override number operations via metaclass:&lt;br /&gt;&lt;font face='Courier New'&gt;Number.metaClass.plus = { n -&amp;gt;&lt;br /&gt;  if(n instanceof Imaginary) {&lt;br /&gt;    return new Complex(r:delegate, i:n.v)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;2. define class Complex to hold real, r, and imaginary, i, parts&lt;br /&gt;&lt;font face='Courier New'&gt;class Complex {&lt;br /&gt;  def r&lt;br /&gt;  def i&lt;br /&gt;  String toString() {&lt;br /&gt;    "$r + ${i}i"&lt;br /&gt;  }&lt;br /&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;3. create class Imaginary to be a wrapper class (I borrow this idea from Scala's implicit converter).&lt;br /&gt;&lt;font face='Courier New'&gt;class Imaginary {&lt;br /&gt;  def v&lt;br /&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;4. define i as a global closure. It would be in DefaultGroovyMethods, actually.&lt;br /&gt;&lt;font face='Courier New'&gt;def i = { v -&amp;gt;&lt;br /&gt;  new Imaginary(v:v)&lt;br /&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Then when you write:&lt;br /&gt;&lt;font face='Courier New'&gt;def b = 2 + i(2.4)&lt;br /&gt;println b&lt;br /&gt;println b.class&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;This prints "2 + 2.4i" and the type of b is class Complex.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5127783977668891285?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5127783977668891285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5127783977668891285' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5127783977668891285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5127783977668891285'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/06/complex-number-in-groovy.html' title='Complex Number in Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-843762462092880153</id><published>2009-06-06T22:43:00.001+07:00</published><updated>2009-06-06T22:43:53.527+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='Fortress'/><title type='text'>Fortress - Hello World</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Here's my early experiment of running Fortress Hello world program, which is listed below (taken from the &lt;a href='http://projectfortress.sun.com/Projects/Community/wiki/MITTutorialApril2009'&gt;tutorial&lt;/a&gt; at MIT by the Fortress team):&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;component hello&lt;br/&gt;export Executable&lt;br/&gt;&lt;br/&gt;run() = println("Hello, World !")&lt;br/&gt;&lt;br/&gt;end&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;I'm a bit surprised that its compilation time is "really" slow. I may be guessing that it's caused by type inference in the Fortress compiler. JVM 1.6.0_12 was used in the experiment. One of my quick conclusion is that Fortress is not suitable for scripting. But I think its compiled program will not be slow (as I mentioned that I am suspecting its type inference engine that makes scripting slow).&lt;br/&gt;&lt;br/&gt;Here's 5 times of running:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;chanwit@lb /cygdrive/c/fortress/fortress_3625&lt;br/&gt;$ time `bin/fortress chanwit/hello.fss`&lt;br/&gt;bash: Hello,: command not found&lt;br/&gt;&lt;br/&gt;real    0m11.393s&lt;br/&gt;user    0m0.244s&lt;br/&gt;sys     0m0.199s&lt;br/&gt;&lt;br/&gt;chanwit@lb /cygdrive/c/fortress/fortress_3625&lt;br/&gt;$ time `bin/fortress chanwit/hello.fss`&lt;br/&gt;bash: Hello,: command not found&lt;br/&gt;&lt;br/&gt;real    0m11.486s&lt;br/&gt;user    0m0.181s&lt;br/&gt;sys     0m0.214s&lt;br/&gt;&lt;br/&gt;chanwit@lb /cygdrive/c/fortress/fortress_3625&lt;br/&gt;$ time `bin/fortress chanwit/hello.fss`&lt;br/&gt;bash: Hello,: command not found&lt;br/&gt;&lt;br/&gt;real    0m11.412s&lt;br/&gt;user    0m0.213s&lt;br/&gt;sys     0m0.215s&lt;br/&gt;&lt;br/&gt;chanwit@lb /cygdrive/c/fortress/fortress_3625&lt;br/&gt;$ time `bin/fortress chanwit/hello.fss`&lt;br/&gt;bash: Hello,: command not found&lt;br/&gt;&lt;br/&gt;real    0m11.377s&lt;br/&gt;user    0m0.197s&lt;br/&gt;sys     0m0.198s&lt;br/&gt;&lt;br/&gt;chanwit@lb /cygdrive/c/fortress/fortress_3625&lt;br/&gt;$ time `bin/fortress chanwit/hello.fss`&lt;br/&gt;bash: Hello,: command not found&lt;br/&gt;&lt;br/&gt;real    0m11.432s&lt;br/&gt;user    0m0.229s&lt;br/&gt;sys     0m0.198s&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=c56206ac-52f2-8511-ba6d-c97f07aeaa0a' 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/7910126-843762462092880153?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/843762462092880153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=843762462092880153' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/843762462092880153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/843762462092880153'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/06/fortress-hello-world.html' title='Fortress - Hello World'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-751727141745801848</id><published>2009-02-27T14:01:00.001+07:00</published><updated>2009-02-27T14:01:36.948+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Callsite'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Hybrid call site model based on Groovy</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I'm trying to model a class structure that support the following features:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;callsite; separating call and execution semantics to&lt;/li&gt;&lt;ul&gt;&lt;li&gt;support before/after advice of AspectJ's pointcut-advice model (possible support around advice)&lt;/li&gt;&lt;li&gt;further support my typing concerns.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;support statically resolved callsite (resolving is done at compile-time, but also changeable at runtime)&lt;/li&gt;&lt;li&gt;support dynamically resolved callsite (as done in Groovy, JRuby, etc.)&lt;/li&gt;&lt;li&gt;must be compatible with Java. i.e., Generated classes can be used as normal Java classes.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;  My below POC is based on Alex T. implementation. But instead of showing all kind of callsite, I show you here only statically resolved callsite. This callsite is surely fast (I hope it's gonna be at the same level of Java) because it's compile-time thing. The interesting point is that, I have a special class loader for these callsites, namely StaticCallSiteClassLoader. What does it do?  This class loader allows re-definition of these callsites. &lt;br/&gt;&lt;br/&gt;What I have observed so far is that All of my callsite classes (&lt;font face='Courier New'&gt;_0_println, _1_ctor, _2_render and _3_index&lt;/font&gt;) have not been loaded when there is no "direct" reference to them. So they can be fully lazy loading using the StaticCallSiteClassLoader. (I've checked this with &lt;font face='Courier New'&gt;java --verbose&lt;/font&gt;)&lt;br/&gt;&lt;br/&gt;How could these callsites are changed at runtime?&lt;br/&gt;You may see the acallsite, an CallSite array that hold all callsites in the example class. It's intended to be public and can be accessed by, for example, a virtual meta-class. &lt;br/&gt;So what's a virtual meta-class? It's kind of meta-class, but in this case, it's not for controlling behaviour of the class (because all dispatch are static). It's for changing behaviour of callsite by reassigning new callsites object to the callsite array.&lt;br/&gt;&lt;br/&gt;Notic that I use WeakReference to hold a callsite class loader. This will be making the class loader GC-able. That's it, after deferenceing all old callsites out of the callsite array, the class loader can be unloaded. Therefore, all callsite class definition are gone as well. Then, we can create a new set of callsites for the current class. This technique would be flexible enough for:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;changing a static call to be a dynamic call&lt;/li&gt;&lt;li&gt;changing a dynamic call back to a static call&lt;/li&gt;&lt;li&gt;installing a woven callsite with before, after advice (it features &lt;b&gt;dynamic&lt;/b&gt; AOP)&lt;/li&gt;&lt;li&gt;inserting type advice, which can lead to bytecode inlining&lt;/li&gt;&lt;li&gt;design a hybrid type system to support both static and dynamic typing in the same system.&lt;/li&gt;&lt;/ul&gt;&lt;font face='Courier New'&gt;import java.lang.ref.WeakReference;&lt;br/&gt;&lt;br/&gt;import runtime.CallSite;&lt;br/&gt;import classloader.StaticCallSiteClassLoader;&lt;br/&gt;import dm.Render;&lt;br/&gt;&lt;br/&gt;public class TestController {&lt;br/&gt;&lt;br/&gt;    /* synthetic */&lt;br/&gt;    private static WeakReference&amp;lt;StaticCallSiteClassLoader&amp;gt; cl;&lt;br/&gt;&lt;br/&gt;    /* synthetic normal callsite */&lt;br/&gt;    public static class _0_println extends CallSite {...}&lt;br/&gt;&lt;br/&gt;    /* synthetic constructor */&lt;br/&gt;    public static class _1_ctor extends CallSite {...}&lt;br/&gt;&lt;br/&gt;    /* synthetic inter-type declaration callsite. statically resolved */&lt;br/&gt;    public static class _2_render extends CallSite {...}&lt;br/&gt;&lt;br/&gt;    /* synthetic property callsite */&lt;br/&gt;    public static class _3_index extends CallSite {...}&lt;br/&gt;&lt;br/&gt;    /* synthetic */&lt;br/&gt;    public static CallSite[] acallsite;&lt;br/&gt;&lt;br/&gt;    static {&lt;br/&gt;        cl = new WeakReference&amp;lt;StaticCallSiteClassLoader&amp;gt;(&lt;br/&gt;                    new StaticCallSiteClassLoader(TestController.class)&lt;br/&gt;        );&lt;br/&gt;        acallsite = new CallSite[4];&lt;br/&gt;        acallsite[0] = cl.get().get("_0_println");&lt;br/&gt;        acallsite[1] = cl.get().get("_1_ctor");&lt;br/&gt;        acallsite[2] = cl.get().get("_2_render");&lt;br/&gt;        acallsite[3] = cl.get().get("_3_index");&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public TestController(){&lt;br/&gt;        super();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public int getIndex() {&lt;br/&gt;        return 10;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public static void main(String[] args) {&lt;br/&gt;        acallsite[0].callStatic("hello world");&lt;br/&gt;        TestController t = (TestController)(acallsite[1].callConstructor());&lt;br/&gt;        acallsite[2].call(t, "hello world");&lt;br/&gt;        acallsite[0].callStatic(acallsite[3].callGetProperty(t, "index"));&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=dd818309-b083-42bc-9665-7dbb76632d3a' 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/7910126-751727141745801848?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/751727141745801848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=751727141745801848' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/751727141745801848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/751727141745801848'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/hybrid-call-site-model-based-on-groovy.html' title='Hybrid call site model based on Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-284682355455751441</id><published>2009-02-25T00:27:00.001+07:00</published><updated>2009-02-25T00:27:10.982+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Using AspectJ to find a Grails' bug</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;It's because I've got a constraint resource (also time). I've found a Grails bug (4060) that is really hard to spot. There is no exception was thrown and I have no idea how to trace this bug because my knowledge about Spring is really limited. I also do not have any good IDE to help debug Grails well. (calling grails-debug and attaching it remotely to Eclipse won't help much in this situation).&lt;br/&gt;&lt;br/&gt;After I enabled Grails log to understand some behaviour of Grails' spring package, I saw some point in the log that it's likely a bug, but the log message is inside Spring, not Grails. (Yep, I need a stack trace).&lt;br/&gt;&lt;br/&gt;I then got an idea of using AspectJ to help inserting a conditional code to "dump" stack from that point. What I've used is an &lt;font face='Courier New'&gt;execution&lt;/font&gt; PCD and a call to &lt;font face='Courier New'&gt;Thread.dumpStack();&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;Here's steps:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Enable trace log in grails-app/Config.groovy&lt;/li&gt;&lt;li&gt;Find a message&lt;/li&gt;&lt;li&gt;Grep to locate the point that emits the message. I found it in Spring code, not Grails.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Instead of rebuild Spring, I wrote this AspectJ code:&lt;/li&gt;&lt;/ul&gt;&lt;font face='Courier New'&gt;    pointcut pc(): &lt;br/&gt;        execution(&lt;br/&gt;           public Object DefaultSingletonBeanRegistry&lt;br/&gt;               .getSingleton(String,ObjectFactory)&lt;br/&gt;        );&lt;br/&gt;        &lt;br/&gt;    before(String name): pc() &amp;amp;&amp;amp; args(name,..) {&lt;br/&gt;        if(name.equals("localeResolver")) {&lt;br/&gt;            Thread.dumpStack();&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;Note that my target Spring bean is localeResolver, so I put a condition here to dump the current stack to find which part of Grails code is doing with this bean at that time.&lt;br/&gt;&lt;ul&gt;&lt;li&gt;I then wove the above aspect into spring.jar&lt;/li&gt;&lt;/ul&gt;&lt;font face='Courier New'&gt;$ ajc -cp .:aspectjrt.jar:spring.jar &lt;br/&gt;   -inpath spring.jar\ // I was going to weave spring.jar&lt;br/&gt;   -outjar spring-2.5.6.jar\ // output would be spring-2.5.6.jar&lt;br/&gt;   -showWeaveInfo\ // I wanted to see some weaving info&lt;br/&gt;   -Xlint:ignore\ // ignore error when resolving some missing classes&lt;br/&gt;   Dump.aj // the above aspect&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;And gotcha, I could really see the context around when this Spring bean is loaded, and reported to Grails JIRA (And Graeme, you did fix it really quickly - you're super cool!).&lt;br/&gt;&lt;br/&gt;Thus, using AspectJ code + Thread.dumpStack() is kind of a conditional break point that can help you debugging Grails without an IDE.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=ab87b8dc-228a-482a-b8ef-66334652ef24' 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/7910126-284682355455751441?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/284682355455751441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=284682355455751441' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/284682355455751441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/284682355455751441'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/using-aspectj-to-find-grails-bug.html' title='Using AspectJ to find a Grails&amp;#39; bug'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-1271460025951129304</id><published>2009-02-20T07:54:00.001+07:00</published><updated>2009-02-20T07:54:35.059+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Simulate Object with Groovy's Closures and Map</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;After reading Chapter 18 of &lt;a href='http://www.amazon.com/Types-Programming-Languages-Benjamin-Pierce/dp/0262162091'&gt;Types and Programming  Languages&lt;/a&gt; by &lt;a href='http://www.cis.upenn.edu/%7Ebcpierce/'&gt;Benjamin C. Pierce&lt;/a&gt;, I've got an idea to simulate how OOP is working with closures and map in Groovy. Just for fun anyway :)&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;def func_01 = { self, props -&amp;gt;&lt;br/&gt;  self.name = props["name"]&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;def func_02 = { self -&amp;gt;&lt;br/&gt;  println "${self.name} is running"&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;def a = [init: func_01, run: func_02]&lt;br/&gt;a.self = a&lt;br/&gt;&lt;br/&gt;a.init(a.self, [name:"mr. a"])&lt;br/&gt;a.run(a.self)&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=3df6073c-34dd-4be8-a036-9485ce1e56e9' 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/7910126-1271460025951129304?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/1271460025951129304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=1271460025951129304' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1271460025951129304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1271460025951129304'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/simulate-object-with-groovy-closures.html' title='Simulate Object with Groovy&amp;#39;s Closures and Map'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4679761698134255739</id><published>2009-02-17T02:01:00.001+07:00</published><updated>2009-02-17T02:20:27.005+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='GJIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Explaining Typesheet</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I've been designing a language for typesheet, a technique to speeding up Groovy by enforcing type for specific calls.&lt;br/&gt;&lt;br/&gt;Current I can enforce type of a call by writing:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;&lt;b&gt;method&lt;/b&gt;(my.package.MyClass#main(String[])) {&lt;br/&gt;  &lt;b&gt;call&lt;/b&gt;(println(*)) &amp;amp;&amp;amp; &lt;b&gt;args&lt;/b&gt;(s) {&lt;br/&gt;    &lt;font color='#3366ff'&gt;s ~&amp;gt; String;&lt;/font&gt;&lt;br/&gt;  }&lt;br/&gt;}&lt;/font&gt;&lt;br/&gt;&lt;br/&gt;This typesheet reads: With in the main method of class MyClass, match &lt;i&gt;every&lt;/i&gt; call to meta-method "println" (&lt;b&gt;regardless input args&lt;/b&gt;). For matched calls, &lt;br/&gt;&lt;ol&gt;&lt;li&gt;let MOP &lt;b&gt;select real methods&lt;/b&gt; by assuming the type of input argument to be "String", and&lt;/li&gt;&lt;li&gt;convert values of those arguments to be "String" before passing them to the calls.&lt;/li&gt;&lt;/ol&gt;You may notice that I emphasis 2 places. There are 2 different phases of the above code to be working. Firstly, in dynamically typed languages, like Groovy, method binding is performed at runtime. So matched call messages are not the real methods. Calls to "println" there may be anything depending on the MOP engine to select.&lt;br/&gt;&lt;br/&gt;Secondly, declaration in { &lt;font color='#3366ff'&gt;s ~&amp;gt; String;&lt;/font&gt; } (I call it a &lt;i&gt;type intervention&lt;/i&gt; block) enforces MOP to select the method according to the type of "s", which is bound to the only argument of the method. ("s" has been binding using an &lt;b&gt;args&lt;/b&gt; predicate).&lt;br/&gt;&lt;br/&gt;So, what's happening next? You might be guessing correctly :)&lt;br/&gt;MOP will be fully by-passed for those matched calls (because related types are enforced). Therefore, speed will be increased to the level of normal Java calls.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4679761698134255739?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4679761698134255739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4679761698134255739' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4679761698134255739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4679761698134255739'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/explaining-typesheet.html' title='Explaining Typesheet'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-9123699058168004034</id><published>2009-02-09T09:06:00.001+07:00</published><updated>2009-02-09T09:06:14.796+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='XUL'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Playing around XUL, JavaScript and jQuery</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;small&gt;&lt;font face='Courier New'&gt;&amp;lt;?xml version="1.0"?&amp;gt; &lt;br/&gt;&amp;lt;?xml-stylesheet href="chrome://global/skin/" type="text/css"?&amp;gt; &lt;br/&gt;&amp;lt;x:window &lt;br/&gt;    xmlns:x="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" &lt;br/&gt;    xmlns="http://www.w3.org/1999/xhtml" &lt;br/&gt;&amp;gt; &lt;br/&gt;    &amp;lt;x:script type="application/x-javascript" &lt;br/&gt;        src="file:///c:/xul/jquery-1.2.6.js"&lt;br/&gt;    /&amp;gt; &lt;br/&gt;  &lt;br/&gt;&amp;lt;x:script type="application/x-javascript; e4x=1"&amp;gt;&lt;br/&gt;&amp;lt;![CDATA[ &lt;br/&gt;  function test(){ &lt;br/&gt;    $('#b').attr("label", "3");&lt;br/&gt;    var frag = &lt;br/&gt;        &amp;lt;listitem value="4" &lt;br/&gt;            label="new item" &lt;br/&gt;            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&lt;br/&gt;        /&amp;gt;;&lt;br/&gt;    $('#l').get(0)&lt;br/&gt;        .appendChild(&lt;br/&gt;            (new DOMParser()).parseFromString(&lt;br/&gt;                frag.toXMLString(), 'text/xml'&lt;br/&gt;            ).documentElement&lt;br/&gt;        );&lt;br/&gt;  } &lt;br/&gt;]]&amp;gt;&amp;lt;/x:script&amp;gt; &lt;br/&gt;     &lt;br/&gt;    &amp;lt;x:button label="click me" oncommand="test();"/&amp;gt; &lt;br/&gt;    &amp;lt;x:button id="b" label="2"/&amp;gt;&lt;br/&gt;    &amp;lt;x:listbox id="l"&amp;gt;&lt;br/&gt;        &amp;lt;x:listitem value="1" label="item label"/&amp;gt;&lt;br/&gt;        &amp;lt;x:listitem value="2" label="item label"/&amp;gt;&lt;br/&gt;        &amp;lt;x:listitem value="3" label="item label"/&amp;gt;&lt;br/&gt;    &amp;lt;/x:listbox&amp;gt;&lt;br/&gt;  &lt;br/&gt;&amp;lt;/x:window&amp;gt; &lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;The above code is to dynamically adding a new &amp;lt;listitem/&amp;gt; into listbox #l. It will be working fine when we get some XUL fragment remotely from the server-side as well. This is Gecko 1.9.0.5.&lt;br/&gt;&lt;br/&gt;What I've learned:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;$("#id").get(0) returns a single element, while .get() returns a list.&lt;/li&gt;&lt;li&gt;e4x=1 tells the JavaScript parser to use the newer language spec.&lt;/li&gt;&lt;li&gt;jQuery works fine with XUL, but XML namespace is needed to avoid some gotcha because it's been designed to work with HTML, not actually XUL.&lt;/li&gt;&lt;li&gt;DOMParser works as expected&lt;/li&gt;&lt;li&gt;Gecko 1.9 solved a lot of bugs I was encountering in 1.8.&lt;/li&gt;&lt;li&gt;With Grails as a back-end, we can now create a dynamically half-Web/half-desktop app.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-9123699058168004034?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/9123699058168004034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=9123699058168004034' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9123699058168004034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9123699058168004034'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/playing-around-xul-javascript-and.html' title='Playing around XUL, JavaScript and jQuery'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4130082466030913195</id><published>2009-02-02T16:14:00.001+07:00</published><updated>2009-02-02T16:16:59.497+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='thought'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>What if Groovy has got Structural Typing</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Here's a quick mock class after I've been reading this &lt;a href='http://www.jroller.com/aalmiray/entry/griffon_groovy_scala_working_together'&gt;entry&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font face='Courier New'&gt;&lt;big&gt;class G7Greeter {&lt;br/&gt;&lt;br/&gt;  def greet(String who, {def setOutput(String text)} model) {&lt;br/&gt;    println "Hello from G7 ${who}"&lt;br/&gt;    model.output = "Hello from G7 ${who}"&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;}&lt;/big&gt;&lt;br/&gt;&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;It would be great if Groovy has Scala's structural typing feature. Structural typing is good for statically "duck typing"-like behaviour. But it seems we need a fork as Groovy dynamic typing allows multi-dispatch already. &lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4130082466030913195?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4130082466030913195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4130082466030913195' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4130082466030913195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4130082466030913195'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/02/what-if-groovy-has-got-structural.html' title='What if Groovy has got Structural Typing'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7323395653744809551</id><published>2009-01-12T13:52:00.003+07:00</published><updated>2009-01-12T14:00:14.032+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fortress'/><title type='text'>Fortress Summary</title><content type='html'>This is a summary from &lt;a title="Fortress Language Specification 1.0" href="http://research.sun.com/projects/plrg/fortress.pdf" id="hqst"&gt;Fortress Language Specification 1.0&lt;/a&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;Fortress "secure Fortran" in a nutshell.&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;General-purpose&lt;/li&gt;&lt;li&gt;Statically typed&lt;/li&gt;&lt;li&gt;Component-based&lt;/li&gt;&lt;li&gt;Designed for producing robust high-performance software with "high programmability"&lt;/li&gt;&lt;li&gt;Intended to be a "growable language"&lt;/li&gt;&lt;ul&gt;&lt;li&gt;be gracefully extended&lt;/li&gt;&lt;li&gt;be scaling to "unprecedented" levels of parallelism and of addressable memory&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Supports modular and extensible parsing&lt;/li&gt;&lt;ul&gt;&lt;li&gt;allow new notations and static analyses to be added&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;High-performance computation with abstraction and type safety&lt;/li&gt;&lt;li&gt;Support type inference&lt;/li&gt;&lt;ul&gt;&lt;li&gt;although it's statically and nominally typed&lt;/li&gt;&lt;li&gt;types can be omit if they are clear in the context&lt;/li&gt;&lt;li&gt;types can be parametric&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Functions are first-class values&lt;/li&gt;&lt;li&gt;Components in Fortress are defined as entities with export and import APIs (not in general compared with the same term of Scala)&lt;/li&gt;&lt;li&gt;Built-in parallel computation support for large scale data structures, e.g. for loop is parallel by default&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Modular Concerns&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Object and Trait&lt;/li&gt;&lt;ul&gt;&lt;li&gt;an object consists of fields and methods&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;traits are named constructs that declare sets of methods. This concept is from Self.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;method in traits may be abstract or concrete&lt;/li&gt;&lt;li&gt;trait may extend other traits&lt;/li&gt;&lt;li&gt;trait provides inherited methods as well as those declared in its declaration.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7323395653744809551?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7323395653744809551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7323395653744809551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7323395653744809551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7323395653744809551'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/01/fortress-summary.html' title='Fortress Summary'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4280446845151644301</id><published>2009-01-11T14:48:00.002+07:00</published><updated>2009-01-11T14:52:02.126+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><title type='text'>Scala Summary</title><content type='html'>I have been reading Scala papers for a couple of days. Here's a quick summary from the first section of "&lt;a title="An overview of the Scala programming language" href="http://www.scala-lang.org/docu/files/ScalaOverview.pdf" id="rkip"&gt;An overview of the Scala programming language&lt;/a&gt;":&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;Scala fuses OOP and functional programming together.&lt;/li&gt;&lt;li&gt;Scala has been designed for construction of components and component system, which is a goal of software industry.&lt;/li&gt;&lt;li&gt;Components can be in any form, any size. Classes, libraries, frameworks, or processes can be considered as components.&lt;/li&gt;&lt;li&gt;Most existing languages offer only limited level of abstraction and composition.&lt;/li&gt;&lt;li&gt;The same concept of programming should be &lt;i&gt;scalable&lt;/i&gt; to use for small as well as large programs.&lt;/li&gt;&lt;li&gt;Scala aims to be scalable by fusing OO and functional features into it.&lt;/li&gt;&lt;li&gt;Every value is an object, and every operation is a method call in Scala (uniform object model).&lt;/li&gt;&lt;li&gt;Functions are first-class values in Scala.&lt;/li&gt;&lt;li&gt;Scala has a unified abstraction for both types and values.&lt;/li&gt;&lt;li&gt;Scala provides constructs for composing classes and traits.&lt;/li&gt;&lt;li&gt;Scala provides object decomposition using pattern matching.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4280446845151644301?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4280446845151644301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4280446845151644301' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4280446845151644301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4280446845151644301'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2009/01/scala-summary.html' title='Scala Summary'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2450801319661935644</id><published>2008-12-11T07:42:00.001+07:00</published><updated>2008-12-11T07:42:30.953+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='GJIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Syntax of Type Sheet</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;It's beautiful, isn't it?&lt;p class='code'&gt;class(C) =&amp;gt; {	field(f) =&amp;gt; f: String;	method(m) &amp;amp;&amp;amp; args(a) =&amp;gt; { // bound a		local(v) =&amp;gt; v: int;		// order of binding -&amp;gt; is left to right		local(n) &amp;amp;&amp;amp; call(Integer.minus(_)) &amp;amp;&amp;amp; this(n) =&amp;gt; return: int;		call(print(n)) &amp;amp;&amp;amp; match(n) {			case call(Integer.plus(_)) =&amp;gt; n: int;			default =&amp;gt; n: String;		}	}}&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-2450801319661935644?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2450801319661935644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2450801319661935644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2450801319661935644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2450801319661935644'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/12/syntax-of-type-sheet.html' title='Syntax of Type Sheet'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5148231517643223013</id><published>2008-10-02T11:11:00.003+07:00</published><updated>2008-10-02T11:19:45.677+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Election'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><category scheme='http://www.blogger.com/atom/ns#' term='Bangkok'/><title type='text'>Online Twitter App written in Grails</title><content type='html'>It is very exciting to tell you that we has now successfully used Grails to clone &lt;a href="http://election.twitter.com"&gt;Twitter's Election&lt;/a&gt;. It seems to be a very first online Twitter application written in &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt;. The most important thing is that the prototype has been done in just &lt;span style="font-weight:bold;"&gt;2 days&lt;/span&gt; and we can have 2 Grails applications (a crawler with Quartz plugin to collect tweets, and a front to serve users) working together. Now it serves for the coming Bangkok Governor Election.&lt;br /&gt;&lt;br /&gt;It is currently hosted by our lovely cloud, &lt;a href="http://mor.ph"&gt;Morph Appspace&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Try it here: &lt;a href="http://bangkok51.morphexchange.com"&gt;http://bangkok51.morphexchange.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5148231517643223013?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5148231517643223013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5148231517643223013' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5148231517643223013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5148231517643223013'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/10/online-twitter-app-written-in-grails.html' title='Online Twitter App written in Grails'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-1656114550157285783</id><published>2008-09-20T15:35:00.003+07:00</published><updated>2008-09-20T15:48:57.700+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Thai'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>A non-English BDD framework</title><content type='html'>I am a big fan of &lt;a href="http://easyb.org"&gt;easyb&lt;/a&gt;, a BDD framework for Groovy and, of course you can use it to validate spec of your Java programs as it's running on JVM.&lt;br /&gt;&lt;br /&gt;But what I really want to have is a support of my native, Thai, language. Recently found out that Groovy can compile UTF-8 code, and I have no problem to make it invoke some method with Thai characters. So, I have been porting the idea from easyb into my own, non-English BDD framework, &lt;a href="http://github.com/chanwit/tspec/tree/master"&gt;TSpec&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Now you can tell a story of software specification in &lt;a href="http://en.wikipedia.org/wiki/Thai_language"&gt;Thai&lt;/a&gt;, wanna learn it ? &lt;br /&gt;&lt;br /&gt;Here's at &lt;a href="http://github.com/chanwit/tspec/tree/master"&gt;Github&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-1656114550157285783?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/1656114550157285783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=1656114550157285783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1656114550157285783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1656114550157285783'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/09/non-english-bdd-framework.html' title='A non-English BDD framework'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-426588867225889305</id><published>2008-09-19T19:16:00.004+07:00</published><updated>2008-09-19T20:23:02.250+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Morph'/><category scheme='http://www.blogger.com/atom/ns#' term='ZK'/><category scheme='http://www.blogger.com/atom/ns#' term='Hangman'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Hangman in ZKGrails</title><content type='html'>Actually, it's not for your eyes, but Robert Lee has found my hangman source code via &lt;a href="http://pastebin.com/f3eea6d28"&gt;Pastbin&lt;/a&gt;. Then he posted it on &lt;a href="http://www.dzone.com/links/hangman_build_with_groovy_on_zk_instead_of_grails.html"&gt;DZone&lt;/a&gt;, but what he mentioned is not 100% correct. This hangman app is built on &lt;a href="http://code.google.com/p/zkgrails/"&gt;ZKGrails&lt;/a&gt;, which is a ZK plugin for Grails (not only Groovy - check the language tag there in the source code it's 'GroovyGrails', not 'Groovy'). &lt;br /&gt;&lt;br /&gt;Hangman is the first challenge among us, a group of PAW66 developer sites in Thailand.(&lt;a href="http://rails66.com"&gt;rails66&lt;/a&gt;, &lt;a href="http://grails66.com"&gt;grails66&lt;/a&gt;, &lt;a href="http://django66.com"&gt;django66&lt;/a&gt;, &lt;a href="http://seam66.com"&gt;seam66&lt;/a&gt; etc.) We set this program up to show the power of each Web framework we love. I have blogged about this &lt;a href="http://www.grails66.com/blog/?p=309"&gt;hangman&lt;/a&gt; in Thai on Grails66.com, if you can read. That's why I said it's not intended for your eyes.&lt;br /&gt;&lt;br /&gt;One more thing I'd like to mention is that I host &lt;a href="http://hangman.morphexchange.com/index.zul"&gt;this app&lt;/a&gt; with &lt;a href="http://mor.ph/"&gt;Morph AppSpace&lt;/a&gt;. It's really cool that not only you can host Rails apps, all kind of my Java apps including &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt; and even &lt;a href="http://zkoss.org"&gt;ZK&lt;/a&gt; just work there. You did the great job, guys !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-426588867225889305?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/426588867225889305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=426588867225889305' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/426588867225889305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/426588867225889305'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/09/hangman-in-zkgrails.html' title='Hangman in ZKGrails'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4708369044099422423</id><published>2008-09-18T03:40:00.001+07:00</published><updated>2008-09-18T03:43:15.042+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='thought'/><category scheme='http://www.blogger.com/atom/ns#' term='SAP'/><category scheme='http://www.blogger.com/atom/ns#' term='distro'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Trust me, Grails will be a platform</title><content type='html'>Recently, SAP has released its &lt;a href="https://wiki.sdn.sap.com/wiki/display/Community/Composition+On+Grails"&gt;Composition on Grails 1.0&lt;/a&gt;, the world first Grails distribution outside the project itself.&lt;br /&gt;Yes, I said it is "the world first Grails distribution". This is really important to me as the release sent out a special signal that "Grails" will be "something" more that a normal web framework on JVM.&lt;br /&gt;&lt;br /&gt;Thanks to Grails plugin architecture, you are able to get its core (thinking of it as a Linux kernel), put some plugins and scripts (think of them as programs around Linux), pack them together and that's it ! You got a web framework distribution that contains special features !&lt;br /&gt;&lt;br /&gt;For example, imagine that you can have a Blog-ready Grails distro, a distro that contains some preset plugins, which help you create a blog like Wordpress in minutes. Or you can have a CMS-ready Grails distro, which enable you to 'grails create-cms' and you've got a Drupal-like system.&lt;br /&gt;&lt;br /&gt;This will be a big step to take Grails into the next level ! Trust me, it's going to be a platform !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4708369044099422423?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4708369044099422423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4708369044099422423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4708369044099422423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4708369044099422423'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/09/trust-me-grails-will-be-platform.html' title='Trust me, Grails will be a platform'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4568307974830973421</id><published>2008-08-28T06:49:00.005+07:00</published><updated>2008-08-28T07:01:51.198+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Interview'/><category scheme='http://www.blogger.com/atom/ns#' term='Thai'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Hey Guillaume Laforge, Thai Geeks are going to interview  you</title><content type='html'>After Groovy has been got the big attention in Thai community this moment, I've been co-operating with &lt;a href="http://www.isriya.com"&gt;Isriya&lt;/a&gt; of &lt;a href="http://www.blognone.com/"&gt;Blognone.com&lt;/a&gt; (a leading technology news site in Thailand) to arrange an interview for &lt;a href="http://glaforge.free.fr/weblog/"&gt;Guillaume Laforge&lt;/a&gt;. This interview will be a community-based. All question will come from news readers, which of course are Thai geeks. After collecting questions there, I'll forward them to Guillaume via email. &lt;br /&gt;&lt;br /&gt;This will be the first time for them to get in touch with him.&lt;br /&gt;&lt;br /&gt;See the post (if you can read Thai): &lt;a href="http://www.blognone.com/node/8770"&gt;http://www.blognone.com/node/8770&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4568307974830973421?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4568307974830973421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4568307974830973421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4568307974830973421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4568307974830973421'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/08/hey-guillaume-laforge-thai-geeks-are.html' title='Hey Guillaume Laforge, Thai Geeks are going to interview  you'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6861461837844488027</id><published>2008-08-15T20:15:00.001+07:00</published><updated>2008-08-15T20:18:25.464+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GJIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='BarCamp'/><category scheme='http://www.blogger.com/atom/ns#' term='Bangkok'/><title type='text'>Do anything at BarCamp Bangkok 2</title><content type='html'>To help promote BarCamp Bangkok 2, here's my screencast:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://screencast.com/t/JRZprfG6"&gt;http://screencast.com/t/JRZprfG6&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Enjoy !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6861461837844488027?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6861461837844488027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6861461837844488027' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6861461837844488027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6861461837844488027'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/08/do-anything-at-barcamp-bangkok-2.html' title='Do anything at BarCamp Bangkok 2'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3933953189304591983</id><published>2008-08-15T07:19:00.003+07:00</published><updated>2008-08-15T07:43:46.139+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JVMIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>A Java-near-speed Groovy</title><content type='html'>Almost 2 months that I have not posted here. I'm still in the final phase of Google Summer of Code. The world is going to be wonderful when you have got a really good result from your hard work, is that right ?&lt;br /&gt;&lt;br /&gt;I'm currently be able to make Groovy speed step closer to Java. It's a high aim, and it's clear to be possible with JVMIT now. I was working on optimising callsites, but could not find a way to make it faster than Alex T.'s implementation because he did really good job of implementing it. So I went back to look at my old GJIT code. What I found is that something had been fooling my eyes for almost a year. There is a way to avoid JVM 6 specific code to implement an agent for JVM 5. Then I re-read AspectJ source again, and found something useful. I has started to re-write a &lt;a href="http://code.google.com/p/gjit/"&gt;GJIT&lt;/a&gt; agent for JVM 5 from then. &lt;br /&gt;&lt;br /&gt;My prototype of the second generation of GJIT was done with &lt;a href="http://www.sable.mcgill.ca/soot/"&gt;Soot&lt;/a&gt; framework, where I really learned a lot of useful optimisation tricks (e.g., SourceValue). Later, I found that Soot is not suite for implementing JIT, because of 1. it's somewhat big structure 2. it's class loading problem. I then have had to implement a whole thing using &lt;a href="http://asm.objectweb.org/"&gt;ASM&lt;/a&gt;. It really was a nightmare because there is no Jimple to help your analysis. I re-wrote at least 3-4 version of ASM optimisers, and finally got the current one, which has a good enough structure to patch. &lt;br /&gt;&lt;br /&gt;Now my goal is to beat all &lt;a href="http://shootout.alioth.debian.org/"&gt;shootout&lt;/a&gt; benchmarks. Here's the result from &lt;a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=partialsums&amp;lang=groovy"&gt;partial sums benchmark&lt;/a&gt; compared with Java on my machine.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;$ export JAVA_OPTS="-server"&lt;br /&gt;$ time `java -cp bin alioth.PartialSumsJ 5000000`&lt;br /&gt;real    0m10.246s&lt;br /&gt;user    0m0.030s&lt;br /&gt;sys     0m0.015s&lt;br /&gt;&lt;br /&gt;$ time `groovy.bat test/partial_sums.groovy 5000000`&lt;br /&gt;real    0m27.110s&lt;br /&gt;user    0m0.030s&lt;br /&gt;sys     0m0.016s&lt;br /&gt;&lt;br /&gt;$ time `groovy.bat test/alioth/PartialSums.groovy 5000000`&lt;br /&gt;real    0m28.409s&lt;br /&gt;user    0m0.030s&lt;br /&gt;sys     0m0.015s&lt;br /&gt;&lt;br /&gt;$ export JAVA_OPTS="-server&lt;br /&gt;-javaagent:C:\\groovy-ck1\\healthy\\target\\install\\lib\\gjit-0.1.jar"&lt;br /&gt;$ time `groovy.bat test/alioth/PartialSums.groovy 5000000`&lt;br /&gt;real    0m13.434s&lt;br /&gt;user    0m0.030s&lt;br /&gt;sys     0m0.030s&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;It's 200% faster than current Groovy, and ~20-30% slower than Java. There's still room to go. I hope to take some more steps closer to Java's speed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3933953189304591983?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3933953189304591983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3933953189304591983' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3933953189304591983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3933953189304591983'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/08/java-near-speed-groovy.html' title='A Java-near-speed Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-292088504082218894</id><published>2008-06-21T06:24:00.002+07:00</published><updated>2008-06-21T20:42:21.828+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Summer of Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Expression-Wide Optimisation (Primitive Callsite #2)</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;This is a technique I proposed for optimizing Groovy primitive expressions.&lt;br/&gt;&lt;br/&gt;Let's say, we have:&lt;br/&gt;&lt;blockquote&gt;public double a(int i, int j) {&lt;br/&gt;  return 1 / ((i+j)*(i+j+1)/2.0D +i+1);&lt;br/&gt;}&lt;br/&gt;&lt;/blockquote&gt;This expression consists of 7 callsites. If we can make sure that the following 3 conditions&lt;br/&gt;1. All variables are primitive.&lt;br/&gt;2. The metaclass of each callsite is default&lt;br/&gt;3. The meta method of each callsite is default&lt;br/&gt;are true, the we can replace the entire expression with primitive and native Java bytecodes. Thus, we can by-pass any overhead here.&lt;br/&gt;&lt;br/&gt;When some meta-method has been replaced, then the above condition is invalid. The original code will be performed instead of the fast one.&lt;br/&gt;&lt;br/&gt;This technique is reasonable to implement because:&lt;br/&gt;1. Callsite makes this checking cheap. We can define "isDefault" flag for a "default" callsite.&lt;br/&gt;2. Instead of checking the default flag one-by-one, checking these flags for a whole expression makes this even cheaper. This also results in easier code generation.&lt;br/&gt;&lt;br/&gt;However, we have to generate code twice, say fast and slow paths, for each expression-to-be-optimised.&lt;br/&gt;&lt;p class='code'&gt;&lt;br/&gt;final boolean exprCallSet = $getExprCallSet(0);&lt;br/&gt;if(exprCallSet) {&lt;br/&gt;  return 1 / ((i+j)*(i+j+1)/2.0D +i+1);&lt;br/&gt;} else {&lt;br/&gt;  $reevaluateExprCallSet.get()[0] = true;&lt;br/&gt;  return DefaultTypeTransformation&lt;br/&gt;      .doubleUnbox(ScriptBytecodeAdapter.castToType(&lt;br/&gt;          acallsite[0].call($const$0, acallsite[1].call(&lt;br/&gt;              acallsite[2].call(acallsite[3].call(&lt;br/&gt;                  acallsite[4].call(acallsite[5].callOII(i, j),&lt;br/&gt;                      acallsite[6].call(acallsite[7].callOII(i,j),$const$0)),&lt;br/&gt;                  $const$1),&lt;br/&gt;                  DefaultTypeTransformation.box(i)),&lt;br/&gt;              $const$0)),&lt;br/&gt;          $get$$class$java$lang$Double()));&lt;br/&gt;}&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;The above snippet is a mock code I'm working on. The next step is to generalise this and modify the Groovy class generator. With this technique, we can unleash all power of Java primitives which will be &amp;gt; 800% faster than the normal callsite caching in 1.6-beta1.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-292088504082218894?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/292088504082218894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=292088504082218894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/292088504082218894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/292088504082218894'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/06/expression-wide-optimisation-primitive.html' title='Expression-Wide Optimisation (Primitive Callsite #2)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5367686172063117526</id><published>2008-06-17T22:09:00.001+07:00</published><updated>2008-06-17T22:12:23.537+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Summer of Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Primitive Callsite Again (Part 1)</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Current Groovy implementation always do boxing, unboxing regardless types of primitive parameters. This is the reason why it's slow down for arithmetic operations.  I've come up with some experiments to optimise primitive for Groovy.&lt;br/&gt; &lt;br/&gt;The idea is that I'll generate primitive callsite, or primitive calls when:&lt;br/&gt;&lt;br/&gt;1. typing is obvious. For example,&lt;br/&gt;&lt;br/&gt;int a = 5&lt;br/&gt;int b = a * (a + 5)&lt;br/&gt;&lt;br/&gt;in the above example, the second expression will have 1 box/unbox call and 1 primitive call because of type of  (a+5).&lt;br/&gt;&lt;br/&gt;With (a +5), this can be generated as &lt;em&gt;Object call((int)a, (int)5)&lt;/em&gt; because type of a is obvious, also '5'.&lt;br/&gt;But we won't know type of the result. So that a * (...) will be generated using &lt;em&gt;Object call ((int)a, Object)&lt;/em&gt; rather than &lt;em&gt;Object call(int, int)&lt;/em&gt;.&lt;br/&gt;&lt;br/&gt;One may argue that this might be not worth, as for a very long and complex expression this optimisation will be useless. For example,&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;private double a(int i, int j) {&lt;br/&gt;  return 1 / ((i+j)*(i+j+1)/2.0D +i+1)&lt;br/&gt;}&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;The above optimisation can do it job only just for 2 inner most expressions. But you will be surprised that it's actually ~23% faster ! Thus IMHO, it's worth to do that.&lt;br/&gt;&lt;br/&gt;2. This second part is to trying to optimise that long expression. The entire expression can be replaced with all primitive calls &lt;em&gt;if only if&lt;/em&gt; their meta-class and meta-methods are "DEFAULT". I hope I could detect this via a property of CallSite, then generate 1. fast path, 2. original path. This second idea has not been fully experimented yet. So wait and see what can be done.&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5367686172063117526?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5367686172063117526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5367686172063117526' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5367686172063117526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5367686172063117526'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/06/primitive-callsite-again-part-1.html' title='Primitive Callsite Again (Part 1)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4215699141363222975</id><published>2008-05-27T03:57:00.001+07:00</published><updated>2008-05-27T03:57:42.855+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Summer of Code'/><title type='text'>Proof-of-Concept Backport Invokedynamic in Groovy</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;It is my first day of Google Summer of Code, and here is what I've done today ;-)&lt;br/&gt;&lt;br/&gt;I have been reading hard and trying to understand Invokedynamic EDR since last week. It is quite difficult for me, who has little background of this kind of things. However, I have got some good sources for studying how invokedynamic work from John Rose's &lt;a href='http://blogs.sun.com/jrose/entry/method_handles_in_a_nutshell'&gt;blog&lt;/a&gt;, Alex Tkachman's Method Handle &lt;a href='http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/main/org/codehaus/groovy/reflection'&gt;code&lt;/a&gt;, Jeroen Frijters's &lt;a href='http://weblog.ikvm.net/PermaLink.aspx?guid=cb5d0f75-879f-41e1-93e0-8ed92a65d296'&gt;blog&lt;/a&gt;, and Rémi Forax's &lt;a href='http://weblogs.java.net/blog/forax/archive/2008/05/javac_invokedyn_1.html'&gt;blog&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Although, there is no something complex like Jeroen's sample, here is a working version of Hello World that uses my backport of invokedynamic APIs.&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;&lt;br/&gt;package groovy.dyn.subject.vm5;&lt;br/&gt;&lt;br/&gt;import groovy.dyn.CallSite;&lt;br/&gt;import groovy.dyn.Linkage;&lt;br/&gt;import groovy.dyn.MethodHandle;&lt;br/&gt;import groovy.dyn.MethodHandles;&lt;br/&gt;import groovy.dyn.MethodType;&lt;br/&gt;import groovy.dyn.StaticContext;&lt;br/&gt;import groovy.dyn.internal.CallSiteImpl;&lt;br/&gt;import groovy.dyn.internal.StaticContextImpl;&lt;br/&gt;&lt;br/&gt;import java.io.PrintStream;&lt;br/&gt;import java.lang.reflect.Method;&lt;br/&gt;&lt;br/&gt;public class InvokeDynamicSubject {&lt;br/&gt;    &lt;br/&gt;    private static CallSite[] callsites;&lt;br/&gt;    private static final int NUM_OF_CALLSITES = 1;&lt;br/&gt;    &lt;br/&gt;    static {&lt;br/&gt;        initCallSites();&lt;br/&gt;        try {&lt;br/&gt;            Method method = InvokeDynamicSubject.class&lt;br/&gt;            .getDeclaredMethod("bootstrapInvokeDynamic", &lt;br/&gt;                    CallSite.class, Object.class, Object[].class);&lt;br/&gt;            MethodHandle mh = MethodHandles.unreflect(method);&lt;br/&gt;            Linkage.registerBootstrapMethod(InvokeDynamicSubject.class, mh);            &lt;br/&gt;        } catch (Throwable e) {&lt;br/&gt;            // do nothing now&lt;br/&gt;        } &lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    private static void initCallSites() {&lt;br/&gt;        callsites = new CallSite[NUM_OF_CALLSITES];    &lt;br/&gt;        callsites[0] = new CallSiteImpl(0,&lt;br/&gt;                            new StaticContextImpl(&lt;br/&gt;                                    PrintStream.class,&lt;br/&gt;                                    "println", &lt;br/&gt;                                    MethodType.make(void.class, String.class)&lt;br/&gt;                            )&lt;br/&gt;                       );                        &lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    private static Object bootstrapInvokeDynamic(CallSite cs, &lt;br/&gt;            Object receiver, Object[] args) throws Throwable {&lt;br/&gt;        Method method=null;&lt;br/&gt;        CallSiteImpl csi = (CallSiteImpl)cs; // down cast: language specific&lt;br/&gt;        switch(csi.index()) {&lt;br/&gt;            case 0: {        &lt;br/&gt;                StaticContext sc = cs.getStaticContext();&lt;br/&gt;                Class&amp;amp;lt;?&amp;amp;amp;gt; c = sc.getCallingClass();                &lt;br/&gt;                method = c.getDeclaredMethod(&lt;br/&gt;                            sc.getName(), &lt;br/&gt;                            sc.getType().parameterType(1));&lt;br/&gt;                MethodHandle mh = MethodHandles.unreflect(method);&lt;br/&gt;                cs.setTarget(mh);&lt;br/&gt;                return mh.invoke(receiver, args);                &lt;br/&gt;            }            &lt;br/&gt;        }&lt;br/&gt;        return null;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    public void test() throws Throwable {&lt;br/&gt;        // System.out.println("Hello World");&lt;br/&gt;        MethodHandle mh = callsites[0].getTarget();&lt;br/&gt;        if(mh == null) {&lt;br/&gt;            bootstrapInvokeDynamic(callsites[0], System.out, new Object[]{"Hello World"});&lt;br/&gt;        } else {&lt;br/&gt;            mh.invoke(System.out, "Hello World");            &lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4215699141363222975?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4215699141363222975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4215699141363222975' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4215699141363222975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4215699141363222975'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/05/proof-of-concept-backport-invokedynamic.html' title='Proof-of-Concept Backport Invokedynamic in Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-8115869450165974715</id><published>2008-05-18T23:15:00.001+07:00</published><updated>2008-05-18T23:21:29.690+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Groovy, Bazaar and bzr-svn</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div style=''&gt;In the past, I was wondering how could I manage my Groovy fork (SVN is not good to do that because it's centralized nature). I was thinking to use SVK, but failed to set it up.&lt;br/&gt;&lt;br/&gt;Today, &lt;a href='http://www.russel.org.uk/'&gt;Russel&lt;/a&gt; posted to &lt;a href='http://markmail.org/message/snia64qcqeuu3l2y'&gt;groovy-dev&lt;/a&gt; that he set up a branch of &lt;a href='http://groovy.codehaus.org/'&gt;Groovy&lt;/a&gt; on &lt;a href='https://launchpad.net/groovy/'&gt;Launchpad&lt;/a&gt;. I have heard about Launchpad, but never tried to be its user. More that 2 hours that I have tried to set everything up.&lt;br/&gt;&lt;br/&gt;I registered to be a Launchpad user, then forked my branch from Russel's one. OK, then what's next?&lt;br/&gt;I'm still on Windows XP, so I need a set of &lt;a href='http://www.chiark.greenend.org.uk/%7Esgtatham/putty/'&gt;putty&lt;/a&gt; programs for SSH. Later, I use PUTTYGEN to generate my public key and import it into Launchpad.&lt;br/&gt;&lt;br/&gt;The next step is to download Python 2.5, Bazaar for Windows. Then, I installed bazaar and was able to branch Russel's trunk locally.&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr branch http://bazaar.launchpad.net/~russel/groovy/trunk&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;After that I pushed it back to my branch.&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr push bzr+ssh://chanwit@bazaar.launchpad.net/~chanwit/groovy/ck1&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;Then, something went wrong. I did not setup SSH properly. bazaar blamed me that I forgot to set BZR_SSH.&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;set BZR_SSH=plink&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;OK, here we go. Now everything went smoothly. I can push my local codes back to Launchpad. So I did clean and re-build Groovy to see if everything was fine. But hey !, the branch of Russel is out-of-date. I need the latest patch Alex just committed. So what to do?&lt;br/&gt;&lt;br/&gt;I checked some docs on bazaar wiki and they said it is able to merge code from SVN using bzr-svn plugin. That sounds great to me. So I downloaded &lt;a href='http://launchpadlibrarian.net/14464464/bzr-svn-0.4.10.tar.gz'&gt;bzr-svn&lt;/a&gt;, but thing did not go smooth again. I need Python-Subversion binding with the special patches. Come on, &lt;a href='http://walkerte.u44.websitesource.net/bzr/'&gt;where&lt;/a&gt; on the earth it is? Alright ! It seems I got everything to run bzr-svn.&lt;br/&gt;&lt;br/&gt;I ran this command:&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr merge http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;but it was not successful. The document said it should be svn+http. How silly I am. I tried merging again:&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr merge svn+http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;And it worked ! After that I did commit.&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr commit -m "message goes here"&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;and push all committed code back to Launchpad again:&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;bzr push&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;Wow, it was fun and cool!. Now I can have my experiment branch without missing any new patch from the main trunk! That's great, isn't it?&lt;br/&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/7910126-8115869450165974715?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/8115869450165974715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=8115869450165974715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/8115869450165974715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/8115869450165974715'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/05/groovy-bazaar-and-bzr-svn.html' title='Groovy, Bazaar and bzr-svn'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-547285844696430908</id><published>2008-03-26T05:27:00.000+07:00</published><updated>2008-03-26T05:28:22.591+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SPLAT'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>My SPLAT 2008 Homework</title><content type='html'>&lt;b&gt;Using Groovy AOP to express business logics in Grails framework&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This document describes a number of problems found in the scenario of applying Groovy AOP to Grails framework that reflects Comprehensibility.&lt;br /&gt;&lt;br /&gt;From &lt;a href="http://grails.org"&gt;http://grails.org&lt;/a&gt;,&lt;br /&gt;&lt;br /&gt;"Grails aims to bring the "coding by convention" paradigm to Groovy. It's an open-source web application framework that leverages the Groovy language and complements Java Web development. You can use Grails as a standalone development environment that hides all configuration details or integrate your Java business logic. Grails aims to make development as simple as possible and hence should appeal to a wide range of developers not just those from the Java community."&lt;br /&gt;&lt;br /&gt;There are high-level artefacts e.g., Controllers, or Domain classes in Grails framework. An AOP language needs a good design to cover high-level pointcuts for expressing such software artefacts in Grails. Moreover, Grails is extensible via its plug-in system. A developer can define their own artefacts in a newly developed plug-in. For Grails, the AOP language needs to be extensible to capture join points introduced by these artefacts.&lt;br /&gt;&lt;br /&gt;For example, Groovy AOP comes with a set of primitive pointcuts like:&lt;br /&gt;- pcall(&lt;i&gt;pattern&lt;/i&gt;)&lt;br /&gt;- etc.&lt;br /&gt;&lt;br /&gt;But these do not reflect the semantics of Grails artefacts.  Their users need some PCDs like:&lt;br /&gt;- controller(&lt;i&gt;pattern&lt;/i&gt;)&lt;br /&gt;- action(&lt;i&gt;pattern&lt;/i&gt;)&lt;br /&gt;- etc.&lt;br /&gt;&lt;br /&gt;Here is an example of a web application written using Grails.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;class BookController {&lt;br /&gt;  def list = {&lt;br /&gt;    def books = Book.list()&lt;br /&gt;    render(view:'book', model:[books: books])&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  def show = {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def update = {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;An aspect written in Groovy AOP:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;aspect SecurityAspect {&lt;br /&gt;  def pc = pcall('BookController.*')&lt;br /&gt;  around(pc) {&lt;br /&gt;    // check access&lt;br /&gt;  }&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;An aspect written in Groovy AOP, with a higher level of PCDs:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;aspect SecurityAspect {&lt;br /&gt;  def pc = controller('book') &amp;amp; action('*')&lt;br /&gt;  around(pc) {&lt;br /&gt;    // check access&lt;br /&gt;  }&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;An aspect written using a variant syntax Groovy AOP, with a higher level of PCD (shortcut form):&lt;br /&gt;This syntax is probably preferred by the developers, according to idioms they are familiar with.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;aspect SecurityAspect {&lt;br /&gt;   around(controller:'book', action:'*') {&lt;br /&gt;      // check access&lt;br /&gt;   }&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Groovy AOP also needs to support a good way to be able to extend and cover a new software artefact added through Grails plugin system as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;As a general purpose AOP system for Groovy, Groovy AOP can be used with Grails framework. It may help expressing business logics as application-level aspects. However, the implementation of Grails framework is dynamic because a developer can add a new software artefact by creating a plug-in. To make an AOP system meets this requirement, it should support the ability to define new PCDs through the same plug-in architecture.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ability to understand by developers ?&lt;/b&gt;&lt;br /&gt; - A system should provide idioms that developer are familiar with in the AOP language&lt;br /&gt;&lt;b&gt;Ability to evolve &amp;amp; customize ?&lt;/b&gt;&lt;br /&gt; - A system should provide the way to define new PCDs&lt;br /&gt;&lt;b&gt;How well does AOSD support/go along with Comprehensibility?&lt;/b&gt;&lt;br /&gt; - Depends on its implementation, and its base language (e.g. Java / AspectJ, Groovy / Groovy AOP). Currently, Groovy AOP has not support this approach well yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-547285844696430908?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/547285844696430908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=547285844696430908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/547285844696430908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/547285844696430908'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/03/my-splat-2008-homework.html' title='My SPLAT 2008 Homework'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3002966149745900052</id><published>2008-03-23T00:48:00.001+07:00</published><updated>2008-03-23T02:50:07.037+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GORM'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Composite Id and FK as PK in GORM</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I've been discussing with my colleage about how to map 2 classes in GORM. It's a bit complicated, where we need to use the foreign key from one, &lt;i&gt;Process&lt;/i&gt;, class to be the primary key for another class, &lt;i&gt;State&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;Code listing as follows:&lt;br/&gt;&lt;p class='code'&gt;class Process implements Serializable {&lt;br/&gt;&lt;br/&gt;   String name&lt;br/&gt;   static hasMany = [states: State]&lt;br/&gt;&lt;br/&gt;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p class='code'&gt;class State {&lt;br/&gt;&lt;br/&gt;  String stateId&lt;br/&gt;  Process process&lt;br/&gt;  &lt;br/&gt;  static mapping = {&lt;br/&gt;	version false&lt;br/&gt;	id composite:['stateId','process'], generator:'assigned'&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;Don't forget to use obj.save(insert:true), when you have a GORM mapping with version=false and generation='assigned'.&lt;br/&gt;&lt;br/&gt;You see, life is much more easier with GORM.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3002966149745900052?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3002966149745900052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3002966149745900052' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3002966149745900052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3002966149745900052'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/03/composite-id-and-fk-as-pk-in-gorm.html' title='Composite Id and FK as PK in GORM'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2303231636782076471</id><published>2008-03-21T02:47:00.001+07:00</published><updated>2008-03-21T02:48:44.463+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>G2One's released Grails 1.0.2</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;The team has just released the simple but powerful Web framework on JVM, Grails 1.0.2. I've also uploaded its Installer for Windows. Check &lt;a href='http://grails.org/Download'&gt;them&lt;/a&gt; out.&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;G2One Inc (&lt;a href='http://www.g2one.com/'&gt;http://www.g2one.com&lt;/a&gt;) and the Grails development team are&lt;br/&gt;pleased to announce the release of Grails 1.0.2, which includes 84 bug&lt;br/&gt;fixes and improvements. The release is available to download from &lt;a href='http://grails.org/Download'&gt;http://grails.org/Download&lt;/a&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;Fixes in this release seem to focus on GORM component.&lt;br/&gt;&lt;br/&gt;From: &lt;a href='http://grails.org'&gt;Grails.org&lt;/a&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-2303231636782076471?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2303231636782076471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2303231636782076471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2303231636782076471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2303231636782076471'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/03/g2one-released-grails-102.html' title='G2One&amp;#39;s released Grails 1.0.2'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7597475778316733098</id><published>2008-02-22T07:15:00.001+07:00</published><updated>2008-02-22T07:15:41.798+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OpenLaszlo'/><category scheme='http://www.blogger.com/atom/ns#' term='RIA'/><title type='text'>OpenLaszlo 4.0.10 released</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;OpenLaszlo 4.0.10 is released today. It seems to contain a lot of bug fixed (compared with 4.0.9). This version is getting closer to 4.1, which will be the production version that supports DHTML runtime.&lt;br/&gt;&lt;br/&gt;I'm really looking forward to use 4.1, but now it's time to upgrade one of my production application to use 4.0.10.&lt;br/&gt;&lt;br/&gt;Source: &lt;a href='http://www.openlaszlo.org/node/398'&gt;OpenLaszlo.org&lt;/a&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7597475778316733098?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7597475778316733098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7597475778316733098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7597475778316733098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7597475778316733098'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/02/openlaszlo-4010-released.html' title='OpenLaszlo 4.0.10 released'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-9120073380029869921</id><published>2008-02-09T01:56:00.001+07:00</published><updated>2008-02-09T01:56:37.723+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Grails Popularity Indicator?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Just got this nabble &lt;a href='http://www.nabble.com/Web-Development-Framework-f16257.html'&gt;link&lt;/a&gt; from &lt;a href='http://graemerocher.blogspot.com/2008/01/grails-making-java-developers-forget.html'&gt;Graeme's blog&lt;/a&gt;. It's sure to show how much popularity of Grails to date.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p class='poweredbyperformancing'&gt;Powered by &lt;a href='http://scribefire.com/'&gt;ScribeFire&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-9120073380029869921?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/9120073380029869921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=9120073380029869921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9120073380029869921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9120073380029869921'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/02/grails-popularity-indicator.html' title='Grails Popularity Indicator?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4052140660670152712</id><published>2008-02-05T04:09:00.000+07:00</published><updated>2008-02-05T04:14:05.082+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='HBase'/><category scheme='http://www.blogger.com/atom/ns#' term='Hadoop'/><title type='text'>Matrix computation environment over Hadoop/HBase</title><content type='html'>I've been forming up the &lt;a href="http://code.google.com/p/hama"&gt;Hama&lt;/a&gt; project with &lt;a href="http://blog.udanax.org/"&gt;Edward Yoon&lt;/a&gt;.&lt;br /&gt;He's been doing the really great job of getting matrix computation work over Map/Reduce pattern. Now we are planning to have a MATLAB-like environment for them.&lt;br /&gt;Here's a number of issues:&lt;br /&gt;&lt;br /&gt;- The language needs to support lazy evaluation, &lt;br /&gt;  for re-arragement of a numerical expression to properly pick the right algorithm before computation.&lt;br /&gt;&lt;br /&gt;I love Groovy, so it's time to develop the Groovy-derived langauge that suites numerical computing.&lt;br /&gt;&lt;br /&gt;- Support BigDecimal, BigInteger by default.&lt;br /&gt;Yep, we're again looking on large-scale computation, and sometime it's beyond the integer's boundary. &lt;br /&gt;So we need the built-in support for these kinds of data type.&lt;br /&gt;&lt;br /&gt;- Matrix and Vector to be the first class elements. For example,&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;def a = [1 2 3] // this is going to be a Vector&lt;br /&gt;def b = [1 2 3; 4 5 6; 7 8 9] // this is going to be a matrix&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;while,&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;def a = [1, 2, 3] // this is going to be an ArrayList&lt;br /&gt;def a = [a:"a"]   // this is going to be a HashMap&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;- Java integration in the same spirit as Groovy&lt;br /&gt;So it should compile to bytecode.&lt;br /&gt;Compile code will be exactly Java class, not like e.g., JRuby compile .class, in which contains a lot of specific magic&lt;br /&gt;&lt;br /&gt;- Support Closure&lt;br /&gt;An anonymous closure will be inlined, whilst a normal closure will be encoded as an inner class.&lt;br /&gt;&lt;br /&gt;More to come ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4052140660670152712?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4052140660670152712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4052140660670152712' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4052140660670152712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4052140660670152712'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/02/matrix-computation-environment-over.html' title='Matrix computation environment over Hadoop/HBase'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3309002634851801749</id><published>2008-01-13T02:04:00.000+07:00</published><updated>2008-01-13T02:15:42.298+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Dataflow Analysis with ASM 3.1 and StackMap</title><content type='html'>Very surprised that I've got a huge benefit from stack map feature of Java 6.&lt;br /&gt;&lt;br /&gt;I'm trying to do some dataflow analysis over compiled Groovy classes, and what I've found in &lt;a href="http://asm.objectweb.org/"&gt;ASM 3.1&lt;/a&gt; is that it comes with method visitor for doing this for me. I've just added some partial evaluation for constants (for almost kinds of JVM instructions with a constant as their operand) and when the visitor visits method instruction, like &lt;span style="font-weight:bold;"&gt;INVOKESTATIC&lt;/span&gt;, I've got type information of each wrapped arguments (Groovy uses Object[] to hold them for dispatching the call with ScriptBytecodeAdapter). &lt;br /&gt;&lt;br /&gt;Now my new unwrapping meta-method algorithm is blazing fast. Thanks ASM guys !!.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3309002634851801749?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3309002634851801749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3309002634851801749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3309002634851801749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3309002634851801749'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/01/dataflow-analysis-with-asm-31-and.html' title='Dataflow Analysis with ASM 3.1 and StackMap'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-9006843048384386297</id><published>2008-01-06T08:07:00.000+07:00</published><updated>2008-01-06T09:25:11.918+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AspectJ'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Application-Specific Performance Tuning for Groovy</title><content type='html'>You all know that if we bypass meta-layer of Groovy, the performance will be boosted. I have 1 class, 1 closure (as an inner class) and 3 method calls in the following codes (System#currentTimeMillis, times, and println):&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;package org.codehaus.groovy.aop&lt;br /&gt;&lt;br /&gt;class Test {&lt;br /&gt; static void main(args) {&lt;br /&gt;  def s1 = System.currentTimeMillis()&lt;br /&gt;  1000000.times {&lt;br /&gt;   int i = 10&lt;br /&gt;   println "test ${i}"&lt;br /&gt;  }&lt;br /&gt;  def s2 = System.currentTimeMillis()&lt;br /&gt;  println "time: ${s2-s1}"&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;I have 100% confidence that those calls won't be dynamic. Then I can have an aspect (written in AspectJ) applied to them for the performance reason. Although, it's quite complicated piece of codes here, but at least your application will be faster.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;public aspect TestBooster {&lt;br /&gt;  &lt;br /&gt;    pointcut inv_println(String methodName, Object[] params): &lt;br /&gt;      call(static * ScriptBytecodeAdapter.invoke*Method*N(..)) &amp;&amp;&lt;br /&gt;      (&lt;br /&gt;        withincode(public static void org.codehaus.groovy.aop.Test.main(..)) &lt;br /&gt;        || withincode(public Object org.codehaus.groovy.aop.Test$_main_closure1.doCall(..))&lt;br /&gt;      ) &lt;br /&gt;      &amp;&amp; args(..,methodName,params)&lt;br /&gt;      &amp;&amp; if("println".equals(methodName));&lt;br /&gt;    &lt;br /&gt;    Object around(String methodName, Object[] params): &lt;br /&gt;      inv_println(methodName, params) {&lt;br /&gt;      DefaultGroovyMethods.println((Object)null, params[0]);&lt;br /&gt;      return null;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    pointcut inv_times(Object self, String methodName, Object[] params): &lt;br /&gt;      call(static *  ScriptBytecodeAdapter.invokeMethodN(..)) &amp;&amp; &lt;br /&gt;      ( &lt;br /&gt;        withincode(public static void org.codehaus.groovy.aop.Test.main(..))&lt;br /&gt;      )&lt;br /&gt;      &amp;&amp; args(Class,self,methodName,params)&lt;br /&gt;      &amp;&amp; if("times".equals(methodName));&lt;br /&gt;    &lt;br /&gt;    Object around(Object self, String methodName, Object[] params): &lt;br /&gt;      inv_times(self, methodName, params) {&lt;br /&gt;      DefaultGroovyMethods.times((Number)self, (Closure)params[0]);&lt;br /&gt;      return null;&lt;br /&gt;    }&lt;br /&gt;              &lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The above aspect is for by-passing calls to "times" and "println" with the replacement of the real targets. The woven code is averagely 15% faster (in both client and server VM) because the call distance is shorten from 36 levels to 17.&lt;br /&gt;With this technique, you can apply the optimisation in the way you want just before you deploying the app (without touching your source). Anyway, don't forget to do the regression tests after the optimisation ;-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-9006843048384386297?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/9006843048384386297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=9006843048384386297' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9006843048384386297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/9006843048384386297'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2008/01/application-specific-performance-tuning.html' title='Application-Specific Performance Tuning for Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4064574911929755898</id><published>2007-12-26T00:53:00.000+07:00</published><updated>2007-12-26T01:11:04.645+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Inlining closure</title><content type='html'>I did some manual experiments of inlining the body of closure from the previous post to make it fast. So far the inlining technique would work only for anonymous closures as it won't be referred by other codes.&lt;br /&gt;&lt;br /&gt;For example, if &lt;span style="font-weight:bold;"&gt;a$a&lt;/span&gt; is an anonymous closure:&lt;br /&gt;&lt;p class="code"&gt;  DefaultMethods.times(100, a$a);&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;can be inlined as the private method &lt;span style="font-weight:bold;"&gt;inlined_DefaultMethods_times&lt;/span&gt;:&lt;br /&gt;&lt;p class="code"&gt;  inlined_DefaultMethods_times(100);&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Then the body of DefaultMethods#times will be copied to construct the above private method. After that the callsite of Closure &lt;span style="font-weight:bold;"&gt;a$a&lt;/span&gt; will be replaced with its body, the method &lt;span style="font-weight:bold;"&gt;a$a__0&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The original &lt;span style="font-weight:bold;"&gt;DefaultMethods#times&lt;/span&gt;: &lt;br /&gt;&lt;p class="code"&gt; public static void times(int num, Closure closure) {&lt;br /&gt;  for(int i=0;i&amp;lt;num;i++) {&lt;br /&gt;   closure.call(i);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The inlined method &lt;span style="font-weight:bold;"&gt;inlined_DefaultMethod_times&lt;/span&gt;: &lt;br /&gt;&lt;p class="code"&gt; private void inlined_DefaultMethod_times(int num) {&lt;br /&gt;  for(int i=0;i&amp;lt;num;i++) {&lt;br /&gt;   a$a__0(i);&lt;br /&gt;  }  &lt;br /&gt; }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The result is reallly impressive, 22 sec, which is comparable to original Java code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4064574911929755898?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4064574911929755898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4064574911929755898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4064574911929755898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4064574911929755898'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/inlining-closure.html' title='Inlining closure'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7222534109679670423</id><published>2007-12-24T03:31:00.000+07:00</published><updated>2007-12-24T03:42:43.984+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Qdg'/><title type='text'>Steps toward encoding fast closures, reflection-based closure</title><content type='html'>With the reflection-based closure approach from last post, I've got some codes to compare performance.&lt;br /&gt;&lt;br /&gt;The following is a Groovy code,&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;class TestGen_002 {&lt;br /&gt;    def a = {&lt;br /&gt;      1000000.times {&lt;br /&gt;          println it&lt;br /&gt;      }  &lt;br /&gt;    } &lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;And this is the manually translated code. Class TestGen_002 contains reflection-based closures, &lt;span style="font-weight:bold;"&gt;a&lt;/span&gt; and an anonymous closure for &lt;span style="font-weight:bold;"&gt;times&lt;/span&gt;.&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;package org.codehaus.qdg;&lt;br /&gt;&lt;br /&gt;import org.codehaus.groovy.qdg.Closure;&lt;br /&gt;import org.codehaus.qdg.runtime.DefaultMethods;&lt;br /&gt;&lt;br /&gt;public class TestGen_002 {&lt;br /&gt; &lt;br /&gt; public Closure a = new Closure(this, "a__0");&lt;br /&gt; &lt;br /&gt; private Object a__0(Object... args) {&lt;br /&gt;  Closure a$a = new Closure(this, "a$a__0");&lt;br /&gt;  DefaultMethods.times(1000000, a$a);&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; private Object a$a__0(Object... args) {&lt;br /&gt;  System.out.println(args[0]);&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Although it's fast, 28 secs, compared with traditional Java for loop (22 secs). I've been trying to get its speed closer to Java.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7222534109679670423?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7222534109679670423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7222534109679670423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7222534109679670423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7222534109679670423'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/steps-toward-encoding-fast-closures.html' title='Steps toward encoding fast closures, reflection-based closure'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7898563874840736485</id><published>2007-12-24T00:22:00.000+07:00</published><updated>2007-12-24T00:37:58.688+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Implementing Closure without using inner classes</title><content type='html'>This implementation is inspired from &lt;a href="http://groups.google.com/group/jvm-languages/browse_frm/thread/dbc3a4a382868904"&gt;Charles Nutters' discussion&lt;/a&gt; about his experiences implementing JRuby. I didn't have much time to look into it, until now. So here's my first implementation of it.&lt;br /&gt;&lt;br /&gt;I have my Closure field a, and its body a_body.&lt;br /&gt;In the Closure class, the ctor will reflectively get the declared method "a_body" by name.&lt;br /&gt;When you'd like to invoke the closure, just call a.call(). Then it will normally invoke the "a_body" method with reflection.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;package org.codehaus.qdg;&lt;br /&gt;&lt;br /&gt;import org.codehaus.groovy.qdg.Closure;&lt;br /&gt;&lt;br /&gt;public class TestGen_001 {&lt;br /&gt; &lt;br /&gt; public Closure a = new Closure(this, "a_body");&lt;br /&gt; &lt;br /&gt; private Object a_body(Object... args) {&lt;br /&gt;  System.out.println(args[0]);&lt;br /&gt;  System.out.println("a_body");&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;And here's a simple implementation of the class Closure:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;package org.codehaus.groovy.qdg;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.InvocationTargetException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.security.AccessController;&lt;br /&gt;import java.security.PrivilegedAction;&lt;br /&gt;&lt;br /&gt;public class Closure {&lt;br /&gt;&lt;br /&gt; private Object target;&lt;br /&gt; private Method method;&lt;br /&gt;&lt;br /&gt; public Closure(Object target, String methodName) {&lt;br /&gt;  this.target = target;&lt;br /&gt;  try {&lt;br /&gt;   method = target.getClass().getDeclaredMethod(&lt;br /&gt;                  methodName, new Class[]{Object[].class});&lt;br /&gt;    AccessController.doPrivileged(&lt;br /&gt;                             new PrivilegedAction(){&lt;br /&gt;    @Override&lt;br /&gt;    public Object run() {&lt;br /&gt;     method.setAccessible(true);&lt;br /&gt;     return null;&lt;br /&gt;    }     &lt;br /&gt;    });   &lt;br /&gt;  } catch (SecurityException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } catch (NoSuchMethodException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Object call(Object... args) {&lt;br /&gt;  try {&lt;br /&gt;   return method.invoke(target, (Object)args);&lt;br /&gt;  } catch (IllegalArgumentException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } catch (IllegalAccessException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } catch (InvocationTargetException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;A closure body, which is a private method, is accessible by setting Method#setAccessible(true).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7898563874840736485?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7898563874840736485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7898563874840736485' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7898563874840736485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7898563874840736485'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/implementing-closure-without-using.html' title='Implementing Closure without using inner classes'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-308315805708760669</id><published>2007-12-23T09:06:00.000+07:00</published><updated>2007-12-23T09:21:44.640+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Quasi Dynamic Groovy</title><content type='html'>I'm trying to summarise what I want from Groovy.&lt;br /&gt;One of my goal is to use Groovy for numerical computing. I love Groovy syntax because it's concise, compact, and elegance when writing an algorithm. So I've started writing code generator from Groovy parser. It's relatively easy to start, if you have .jar distribution of Groovy.&lt;br /&gt;&lt;br /&gt;Here's a list of my requirements:&lt;br /&gt;- Partially static Groovy&lt;br /&gt;- AOP support by design, at the level of the runtime system.&lt;br /&gt;&lt;br /&gt;Challenges so far are:&lt;br /&gt;1. Is it possible to make a Groovy class partially static? IMO, I think it would. The support reason is very obvious. Now, we can mix Groovy and Java classes in the same system.&lt;br /&gt;So what if we resolve method references at compile-time. If the method reference is found we make it static, if not we just make it dynamic.&lt;br /&gt;2. Is it possible to use the envelope technique to wrap around method calls, getters, setters, etc.&lt;br /&gt;This technique can be used to have a dynamic AOP support.&lt;br /&gt;3. How to keep the class semantic to be as similar as possible to the classic Groovy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-308315805708760669?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/308315805708760669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=308315805708760669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/308315805708760669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/308315805708760669'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/quasi-dynamic-groovy.html' title='Quasi Dynamic Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4180263443688615242</id><published>2007-12-10T16:41:00.000+07:00</published><updated>2007-12-10T17:03:54.464+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Groovy AOP - Part #4, Getter and Setter PCDs</title><content type='html'>I haven't implemented pointcut designators (PCDs) for getter and setter because I actually forgot about them.&lt;br /&gt;&lt;br /&gt;I recall them this morning, and really see the advantage of using them for Grails domain classes. I think using it can definitely solve the problem's been caused by Hibernate setter issue. Here's the situation.&lt;br /&gt;&lt;br /&gt;I have the domain class, &lt;span style="font-style:italic;"&gt;User&lt;/span&gt; containing the password field &lt;span style="font-style:italic;"&gt;passwd&lt;/span&gt;:&lt;br /&gt;&lt;p class="code"&gt;class User {&lt;br /&gt;  ...&lt;br /&gt;  String passwd&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;What I wanted to do is to store MD5ed password by just calling &lt;span style="font-weight:bold;"&gt;new User(password:'abc').save()&lt;/span&gt;. But this won't work. It's the Hibernate limitation that does not allow me to have the &lt;span style="font-style:italic;"&gt;setter&lt;/span&gt; for passwd, say setPasswd, because the setter will be called, at least, twice when Hibernate 1. initialises the object, 2. sets the value into the property. Yes, I got my password hashed twice !&lt;br /&gt;&lt;br /&gt;So here can be a solution (I have to try it first to confirm this anyway).&lt;br /&gt;&lt;br /&gt;Groovy AOP can provide a shortcut for getter and setter like: &lt;br /&gt;&lt;p class="code"&gt;class User {&lt;br /&gt;  static aspect = {&lt;br /&gt;    before(set:'passwd'){ value -&gt; value = MD5(value) }&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;  String passwd&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Why this's going to work? I think it works because Groovy AOP works at meta-layer, while Hibernate works at bytecode (proxied) layer. It's possible for Hibernate to set the property directly (as it does not invoke the call through Groovy invoker). Good use case?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4180263443688615242?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4180263443688615242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4180263443688615242' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4180263443688615242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4180263443688615242'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/groovy-aop-part-4-getter-and-setter.html' title='Groovy AOP - Part #4, Getter and Setter PCDs'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5547138563356426813</id><published>2007-12-08T23:02:00.000+07:00</published><updated>2007-12-08T23:17:29.851+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Groovy AOP - Redesign #3, Advise By Convention</title><content type='html'>This idea came solely from seeing what Grails's using for interception.&lt;br /&gt;The idea is simple, like ActiveRecord pattern used in Grails (e.g., &lt;span style="font-style:italic;"&gt;find*&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;In Grails, users'd like to have &lt;span style="font-style:italic;"&gt;before, after&lt;/span&gt; interceptions for their controllers, domain classes, etc.&lt;br /&gt;&lt;br /&gt;Like this:&lt;br /&gt;&lt;p class="code"&gt;  class MyController {&lt;br /&gt;    static beforeInterceptor = ['*', this.&amp;auth]&lt;br /&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;and this:&lt;br /&gt;&lt;p class="code"&gt; class MyDomain {&lt;br /&gt;    String field1&lt;br /&gt;&lt;br /&gt;    static beforeUpdate = {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;So Groovy AOP would support these kind of functionalities with conventions in its aspect language like the following for controllers:&lt;br /&gt;&lt;p class="code"&gt; MyController {&lt;br /&gt;    static aspect {&lt;br /&gt;      beforeAll { println 'test' } // = before(call:'*') { }&lt;br /&gt;      beforeUpdate { println 'test' } // = before(call:'update') {} &lt;br /&gt;    }&lt;br /&gt; }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;and following for domain class dynamic methods:&lt;br /&gt;&lt;p class="code"&gt; MyDomain {&lt;br /&gt;    static aspect = { &lt;br /&gt;      beforeSave { }&lt;br /&gt;      beforeUpdate { } &lt;br /&gt;      afterUpdate { }&lt;br /&gt;      afterSave { }&lt;br /&gt;      beforeNew {}&lt;br /&gt;    }&lt;br /&gt; }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;To sum up here, what Groovy AOP should support in its aspect language are &lt;span style="font-style:italic;"&gt;before*, after*, and around*&lt;/span&gt; to simplify the use of AOP in practice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5547138563356426813?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5547138563356426813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5547138563356426813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5547138563356426813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5547138563356426813'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/groovy-aop-redesign-3-advice-by.html' title='Groovy AOP - Redesign #3, Advise By Convention'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5909861373620945127</id><published>2007-12-03T21:57:00.000+07:00</published><updated>2007-12-03T23:10:12.208+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Groovy AOP - Redesigned #2</title><content type='html'>OK, I'm now continuing to show that what've I made changes to the syntax of Groovy AOP.&lt;br /&gt;Last post, I've showed the new syntax, and there's a few more tweaks here.&lt;br /&gt;&lt;br /&gt;In the trunk, now we can have aspect like this:&lt;br /&gt;&lt;p class="code"&gt;class MyClass {&lt;br /&gt;  static aspect = {&lt;br /&gt;    before(call:'update1') { println 'before update 1 ..'}&lt;br /&gt;    after(call:'update2')  { println 'after update 2 ..' }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;and this:&lt;br /&gt;&lt;p class="code"&gt;class MyClass {&lt;br /&gt;  static aspect = {&lt;br /&gt;    before('update1') { println 'before update 1 ..'}&lt;br /&gt;    after('update2')  { println 'after update 2 ..' }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Both have the same semantic. They read, &lt;span style="font-style:italic;"&gt;before&lt;/span&gt; the call of (join point of) MyClass#update1, do ..., and &lt;span style="font-style:italic;"&gt;after&lt;/span&gt; the call of (join point of) MyClass#update2 do ...&lt;br /&gt;I think these shortcuts will be comfortable enough for people to use without AOP knowledge.&lt;br /&gt;&lt;br /&gt;The implementation's also changed internally to override MetaClassImpl#invokeMissingMethod rather than MetaClassImpl#invokeMethod.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5909861373620945127?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5909861373620945127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5909861373620945127' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5909861373620945127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5909861373620945127'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/groovy-aop-redesigned-2.html' title='Groovy AOP - Redesigned #2'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3793226992512461910</id><published>2007-12-03T08:50:00.000+07:00</published><updated>2007-12-03T09:02:41.927+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Groovy AOP - Aspect Builder Redesign #1</title><content type='html'>I've just got Groovy AOP running first time with Groovy 1.1, and seriously I'm looking to integrate  it with Grails when its 1.0 debuts. My problem now is still the classic AOP problem, how could we have an expressive and easy pointcut language for people?&lt;br /&gt;&lt;br /&gt;I know that advantages of Groovy AOP to Grails are quite clear, but if and only if developers uses it. So I'm trying to re-design the pointcut language before getting 0.3 out.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;class MyController {&lt;br /&gt;  static aspect = {&lt;br /&gt;    before(call:'*') { println 'something' }&lt;br /&gt;    before(withIn:'') { }&lt;br /&gt;    around(call:'update*') { inv -&gt;&lt;br /&gt;      println 'before'&lt;br /&gt;      inv.proceed(inv.args)&lt;br /&gt;      println 'after'&lt;br /&gt;    }&lt;br /&gt;    def pc = call('update*') &amp; within('main')&lt;br /&gt;    around(pc) { inv -&gt;&lt;br /&gt;      println 'before'&lt;br /&gt;      inv.proceed(inv.args)&lt;br /&gt;      println 'after'&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def update() {&lt;br /&gt;  }&lt;br /&gt;    &lt;br /&gt;  def update2() {&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Above is how we can embed "aspect" into Grails controller. I intend to leave the "static aspect" block to say that "hey, you're using AOP here". Don't know if people will have objection to this.&lt;br /&gt;&lt;br /&gt;The shortest code we can use to have "before interceptor" for every method in the class is:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;  static aspect {&lt;br /&gt;    before(call:'*') { println 'before' }&lt;br /&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Tomorrow, I'll continue with next thought about this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3793226992512461910?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3793226992512461910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3793226992512461910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3793226992512461910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3793226992512461910'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/12/groovy-aop-aspect-builder-redesign-1.html' title='Groovy AOP - Aspect Builder Redesign #1'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6109637140801376360</id><published>2007-11-30T05:56:00.000+07:00</published><updated>2007-11-30T06:01:34.864+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><title type='text'>Groovy equivalence to Chapel's code</title><content type='html'>Ability to have our own DSL in Groovy makes it possible to have a high-level language for parallel computing. I'm trying to clone all features of &lt;a href="http://chapel.cs.washington.edu/"&gt;Chapel&lt;/a&gt; to Groovy and then optimise the generated codes to make it run (I hope) fast.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;int n = 1000&lt;br /&gt;def A = new Vector(size: n)&lt;br /&gt;def B = new Vector(size: n)&lt;br /&gt;forall(2..n-1) { i -&gt;&lt;br /&gt;  B[i] = ((A[i-1] + A[i+1])) / 2&lt;br /&gt;}&lt;br /&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/7910126-6109637140801376360?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6109637140801376360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6109637140801376360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6109637140801376360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6109637140801376360'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/11/groovy-equivalence-to-chapels-code.html' title='Groovy equivalence to Chapel&apos;s code'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2796218731681567691</id><published>2007-11-13T08:32:00.000+07:00</published><updated>2008-11-13T19:05:12.556+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mobile'/><title type='text'>Hello Android, Are you wanting to sit on Grails?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7gu9HQYUUjE/RzkBU8ENr-I/AAAAAAAAAB4/grWaFoAKkjA/s1600-h/android_on_grails.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_7gu9HQYUUjE/RzkBU8ENr-I/AAAAAAAAAB4/grWaFoAKkjA/s400/android_on_grails.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5132134709598203874" /&gt;&lt;/a&gt; Google's released Android SDK yesterday. After quick skimming on packages supported by the SDK, here what I can summarise,&lt;br /&gt;- android packages, UI + 2D + 3D, SAX, DB, device APIs, OS calls&lt;br /&gt;- java packages, java.nio, and java.concurrent (including atomic)&lt;br /&gt;- httpcli&lt;br /&gt;- JSON support&lt;br /&gt;- cryptography, SSL&lt;br /&gt;- Bluetooth support&lt;br /&gt;- Google Map APIs&lt;br /&gt;- XMPP&lt;br /&gt;&lt;br /&gt;It seems to be not Java ME packages, but likely the striped down version of Java SE. So I think this could be possible to make quite complicate applications.&lt;br /&gt;My first try here is not about making an app, but I'll see if I can have some templates to generate Grails scaffolding for it. If this can be done in a month, a full-blow application with Grails as a back-end will be easily developed. And it's going to be a big boosting up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-2796218731681567691?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2796218731681567691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2796218731681567691' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2796218731681567691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2796218731681567691'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/11/hello-android-are-you-wanting-to-sit-on.html' title='Hello Android, Are you wanting to sit on Grails?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7gu9HQYUUjE/RzkBU8ENr-I/AAAAAAAAAB4/grWaFoAKkjA/s72-c/android_on_grails.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6907087323251688934</id><published>2007-11-07T04:48:00.000+07:00</published><updated>2007-11-07T05:03:18.233+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Does Grails need a real compiler?</title><content type='html'>We all know what a DSL is, so what's about a domain specific compiler (DSC)?&lt;br /&gt;&lt;br /&gt;I've just accidentally seen Grails 1.0-RC1's been invoking its compiler during my work. So I think it's possible to have a DSC to support Grails in someway. It could be definitely based on the Groovy compiler with &lt;span style="font-weight:bold;"&gt;addition Grails knowledge&lt;/span&gt;. For example, in a Grails controller, we can use "render" method to render things like XML, JSON. What if we can compile this render block into a real XML, or JSON chunk embedded in the controller, rather than invoking the dynamic method.&lt;br /&gt;&lt;br /&gt;In the development time, we've got Grails running fine and it offers us a great rapid environment. So we just keep using the original Groovy here. And if we have DSC, and it works just before &lt;span style="font-weight:bold;"&gt;grails war&lt;/span&gt;, then our Grails apps performance will be really great during its execution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6907087323251688934?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6907087323251688934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6907087323251688934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6907087323251688934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6907087323251688934'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/11/does-grails-need-real-compiler.html' title='Does Grails need a real compiler?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6336221580603796897</id><published>2007-11-04T04:43:00.000+07:00</published><updated>2007-11-04T04:48:01.773+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Map-Reduce'/><title type='text'>Convention over Configuration for Map-Ruduce</title><content type='html'>I'd just like to have a quick look to &lt;a href="http://svn.apache.org/viewvc/lucene/hadoop/branches/branch-0.14/src/examples/org/apache/hadoop/examples/WordCount.java?view=markup"&gt;Hadoop's word-count example&lt;/a&gt;, if it can be written in Groovy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Disclaimer: this code doesn't work !&lt;/span&gt;&lt;br /&gt;&lt;p class="code"&gt;class WordCountMapReduce {&lt;br /&gt;  def map = {key, value, output, reporter -&gt;&lt;br /&gt;    def line = value.toString()&lt;br /&gt;    def itr = new StringTokenizer(line)&lt;br /&gt;    while(itr.hasMoreTokens()) {&lt;br /&gt;      word.set(itr.nextToken())&lt;br /&gt;      output.collect(word, one)&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def reduce = {key, values, output, reporter -&gt;&lt;br /&gt;    int sum = 0;&lt;br /&gt;    values.each {&lt;br /&gt;      sum += it.get()&lt;br /&gt;    }&lt;br /&gt;    output.collect(key, sum)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;It's time for Groovy to go fore massive computation?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6336221580603796897?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6336221580603796897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6336221580603796897' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6336221580603796897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6336221580603796897'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/11/convention-over-configuration-for-map.html' title='Convention over Configuration for Map-Ruduce'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7869164274530762074</id><published>2007-10-15T05:09:00.001+07:00</published><updated>2007-10-15T05:21:09.635+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Profiling Groovy Meta-layer</title><content type='html'>I'm planning to profile the meta-layer of Groovy. What I'm looking for in this profiling is a number of arguments needed by methods of general applications.&lt;br /&gt;&lt;br /&gt;Currently, ScriptByteCodeAdapter#invoke* alway use Object[] as a wrapper of a target method's arguments when dispatching it, and it's difficult for my JIT compiler to replace it with a new call, as suggested by Charles Nutter that my dataflow analysis may be time-consuming. So I came up with the idea of profiling.&lt;br /&gt;&lt;br /&gt;There are invoke*0 and invoke*N in ScriptByteCodeAdapter class, and I think there would be invoke*1, invoke*2 ... invoke*K, where K is a threshold number found by the profiler. Then the class ASMClassGen would be patched to generate these newly added methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7869164274530762074?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7869164274530762074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7869164274530762074' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7869164274530762074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7869164274530762074'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/10/profiling-groovy-meta-layer.html' title='Profiling Groovy Meta-layer'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3589955471755580874</id><published>2007-09-10T06:05:00.000+07:00</published><updated>2007-09-10T06:16:42.914+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>How does Groovy AOP relate to GIT?</title><content type='html'>GIT is the name of Groovy just-in-time compiler, which is being developed. I'm using it as an underlying layer for Groovy AOP.&lt;br /&gt;&lt;br /&gt;MetaClassImpl, the default meta-class of Groovy, picks a call for each invocation, which is a joinpoint in AOP theory.&lt;br /&gt;&lt;br /&gt;GIT is trying to optimise this invocation process by checking the change of a MetaClass of each class. It replaces the meta-call with the real call, which is returned by the MetaClass. Weaving process in Groovy AOP will take the similar approach. But when MetaClass picks a real call, it would return "WovenMetaMethod" that contains also "before", "after", and "around" information. The runtime weaver then uses this information to generate an equivalent list of bytecode instructions and use them to replace the meta-call.&lt;br /&gt;&lt;br /&gt;This is how GIT relates to Groovy AOP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3589955471755580874?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3589955471755580874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3589955471755580874' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3589955471755580874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3589955471755580874'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/09/how-does-groovy-aop-relate-to-git.html' title='How does Groovy AOP relate to GIT?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-186147385681436643</id><published>2007-09-08T01:47:00.000+07:00</published><updated>2007-09-08T01:53:25.644+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Geogia'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>An ERP built with Grails</title><content type='html'>I've setup the project called &lt;a href="http://code.google.com/p/geogia"&gt;Geogia&lt;/a&gt; at Google Code for developing an ERP system using Grails. All domain classes are being re-written based on UML diagrams of project &lt;a href="http://neogia.org"&gt;Neogia&lt;/a&gt;.  &lt;a href="http://gentleware.com"&gt;Gentleware AG&lt;/a&gt; kindly sponsored Poseidon UML CE edition for this project. Thank you :).&lt;br /&gt;&lt;br /&gt;This project is being developed using version 0.6 of Grails.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-186147385681436643?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/186147385681436643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=186147385681436643' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/186147385681436643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/186147385681436643'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/09/erp-built-with-grails.html' title='An ERP built with Grails'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-1061027078448337044</id><published>2007-09-07T10:50:00.000+07:00</published><updated>2007-09-07T10:53:27.191+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Xfire plugin for Grails 0.6 released</title><content type='html'>Nothing's fancy. I've just released my latest Xfire plugin for Grails 0.6.&lt;br /&gt;It's now available from Grails plugins repository.&lt;br /&gt;&lt;br /&gt;This command:&lt;br /&gt;&lt;p class="code"&gt;$ grails install-plugin xfire&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;is enough to give it a go.&lt;br /&gt;&lt;br /&gt;A few note here, it uses Xerces 2.8.1, where Grails ships with 2.6.2. Just in case for any incompatibility.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-1061027078448337044?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/1061027078448337044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=1061027078448337044' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1061027078448337044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1061027078448337044'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/09/xfire-plugin-for-grails-06-released.html' title='Xfire plugin for Grails 0.6 released'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5928280548477100735</id><published>2007-09-04T09:46:00.001+07:00</published><updated>2007-09-04T22:41:17.362+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Dynamic Recompiling a Groovy Class</title><content type='html'>After we identified an &lt;a href="http://chanwit.blogspot.com/2007/04/invariant-dynamic-calls.html"&gt;invariant dynamic call&lt;/a&gt;, the call replacement technique could be applied to the caller method. The following describes an early version of the algorithm to do so:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;1. find an invocation statement to ScriptBytecodeAdapter&lt;br /&gt;2. determine a number of parameters that the statement needs.&lt;br /&gt;  2.1 if the number of parameters = 3, this invocation has no argument.&lt;br /&gt;  2.2 if the number of parameters = 4, this invocation has a set of arguments.&lt;br /&gt;3. statically unwrap the last parameter passed to this statement&lt;br /&gt;  (note that Groovy's using Object[] &lt;br /&gt;   to wrap a set of method arguments, &lt;br /&gt;   and we need to unwrap and pass them &lt;br /&gt;   to the new invocation statement)&lt;br /&gt;  3.1 in this step, we can also clean up unneeded the Object[] variable &lt;br /&gt;        and its assignment statements.&lt;br /&gt;4. construct the new invocation statement, &lt;br /&gt;    using information gathered from the profiler.&lt;br /&gt;    (we can not infer the target class using&lt;br /&gt;     any information provided by the statement,&lt;br /&gt;     because the real call will be chosen by Groovy meta-class).&lt;br /&gt;5. fix object casting, this can be done by traversing backwardly &lt;br /&gt;    to the statement prior to the invocation. &lt;br /&gt;    Then change casting type from GroovyObject &lt;br /&gt;    to the correct type (also get this value from the profiler)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The result so far:&lt;br /&gt;&lt;p class="code"&gt;   $r19_2 = $r19;&lt;br /&gt;   goto label7;&lt;br /&gt;label6:&lt;br /&gt;   $r19_2 = org.codehaus.groovy.aop.tests.Target.class$groovy$lang$GroovyObject;&lt;br /&gt;label7:&lt;br /&gt;   $r20 = ScriptBytecodeAdapter.castToType(r0, $r19_2);&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   $r21 = (org.codehaus.groovy.aop.tests.Target) $r20;&lt;br /&gt;   $r23 = $r21.method2("test");&lt;br /&gt;&lt;/span&gt;   $r18[$i0] = $r23;&lt;br /&gt;   $r24 = ScriptBytecodeAdapter.invokeMethodOnCurrentN(r2, $r16, $r17, $r18);&lt;br /&gt;   return $r24;&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/7910126-5928280548477100735?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5928280548477100735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5928280548477100735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5928280548477100735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5928280548477100735'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/09/dynamic-recompiling-groovy-class.html' title='Dynamic Recompiling a Groovy Class'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6113554500000210742</id><published>2007-09-03T08:05:00.000+07:00</published><updated>2007-09-04T09:46:27.377+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Bytecode incompatibility</title><content type='html'>Last post, I've blogged about using Soot to optimise class files. Soot is alright for me when I used it as a generator. But in the dynamic context, I've got some compiled classes from the different generator (say Groovyc),  but I'd like to get them optimised with Soot and then re-define then with the Intromentation. This approach completely failed as Soot-compiled classes have different attributes compared with the original classes.&lt;br /&gt;&lt;br /&gt;After this problem's kept me busy for a couple of days, I've came with a solution to use Javassist, another bytecode manipulation to help me re-mix two different versions of class.&lt;br /&gt;&lt;br /&gt;I got the original class from Javassist class pool, removed the old target method. Then I loaded the Soot-optimised class from disk, using Javassist's ClassFile, and took only the optimised target method from it. After that I created a new MethodInfo for that method with &lt;span style="font-weight:bold;"&gt;constant pool of the original class&lt;/span&gt; and then I added it to the original class.  I finally obtained its bytecode and give it to Intrumentation for class re-definition.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;soot.Main.main( new String[]{&lt;br /&gt;  "-d",&lt;br /&gt;  "mydir",&lt;br /&gt;  "-via-shimple",&lt;br /&gt;  className&lt;br /&gt;});&lt;br /&gt;try { &lt;br /&gt; String fname = "mydir/"+ className.replace('.', '/') +".class";&lt;br /&gt; ClassPool cp = ClassPool.getDefault();&lt;br /&gt; CtClass target = cp.get(className);   &lt;br /&gt; target.defrost();&lt;br /&gt; String mName = "main";&lt;br /&gt; ClassFile srcClassFile = &lt;br /&gt;    new ClassFile(new DataInputStream(new FileInputStream(fname)));&lt;br /&gt; MethodInfo srcMethodInfo = &lt;br /&gt;    getMethod(srcClassFile, mName, "([Ljava/lang/String;)V");   &lt;br /&gt; MethodInfo newMethodInfo = &lt;br /&gt;    new MethodInfo(target.getClassFile2().getConstPool(), &lt;br /&gt;                             mName, srcMethodInfo, null);   &lt;br /&gt; target.removeMethod(target.getMethod(mName, "([Ljava/lang/String;)V"));&lt;br /&gt; CtMethod newMethod = CtMethod.make(newMethodInfo, target);&lt;br /&gt; target.addMethod(newMethod);   &lt;br /&gt; Instrumentation i = Agent.getInstrumentation();&lt;br /&gt; i.redefineClasses(&lt;br /&gt;    new ClassDefinition[]{&lt;br /&gt;      new ClassDefinition(Class.forName(className), target.toBytecode())&lt;br /&gt; });   &lt;br /&gt;} catch (Exception e) {&lt;br /&gt; e.printStackTrace();&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Tell me, if you have a better idea !!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6113554500000210742?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6113554500000210742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6113554500000210742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6113554500000210742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6113554500000210742'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/09/bytecode-incompatibility.html' title='Bytecode incompatibility'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-1549242389021626176</id><published>2007-08-21T18:51:00.000+07:00</published><updated>2007-09-04T09:46:04.403+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimisation'/><title type='text'>Optimising Groovy bytecodes with Soot</title><content type='html'>I'm playing around &lt;a href="http://www.sable.mcgill.ca/soot/"&gt;Soot&lt;/a&gt; framework and get some optimised bytecodes after applying its default optimisation to Groovy-generated classes.&lt;br /&gt;This does not help much for speed improvement, but I think it could help reduce the usage of PermGen space.&lt;br /&gt;&lt;br /&gt;I've tested with a trivial class, and its file size after optimisation is 8.5% shrinker than the original. I'm expecting that this figure would be large if we optimise a whole application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-1549242389021626176?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/1549242389021626176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=1549242389021626176' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1549242389021626176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1549242389021626176'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/08/optimising-groovy-bytecodes-with-soot.html' title='Optimising Groovy bytecodes with Soot'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5919759541357587092</id><published>2007-08-08T18:38:00.000+07:00</published><updated>2007-08-08T19:26:26.935+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JVMIT'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><title type='text'>Possible JIT for Groovy with JVMTI</title><content type='html'>Nothing involves Groovy bytecode analysis at the moment, but I show you here the possible way to re-define a Java class with a Java 6 JVMTI agent. Yes, I say Java 6 as Java 5 does not support class re-definition through &lt;b&gt;java.lang.instrument&lt;/b&gt; package.&lt;br /&gt;&lt;br /&gt;As you might know, several AOP systems, that enable load-time weaving, use class transformation at load-time to weave aspects to the existing programs. They use a java JVMTI agent to achieve this.&lt;br /&gt;&lt;br /&gt;Now in Java 6, you can do a bit more further as it offers method&lt;br /&gt;&lt;p class="code"&gt;Instrumentation.redefineClasses(ClassDefinition[] defs);&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm experimenting this technique with a normal class, here:&lt;br /&gt;&lt;p class="code"&gt;package org.groovy.git.test;&lt;br /&gt;&lt;br /&gt;public class TestClass {&lt;br /&gt;&lt;br /&gt; public void myMethod(){&lt;br /&gt;  System.out.println("a");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The re-definition process is performed just to change a TestClass object from printing "a" to printing "b".&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;package org.groovy.git.test;&lt;br /&gt;&lt;br /&gt;import java.lang.instrument.ClassDefinition;&lt;br /&gt;import java.lang.instrument.Instrumentation;&lt;br /&gt;&lt;br /&gt;import javassist.ClassPool;&lt;br /&gt;import javassist.CtClass;&lt;br /&gt;import javassist.CtMethod;&lt;br /&gt;&lt;br /&gt;import org.groovy.git.Agent;&lt;br /&gt;&lt;br /&gt;public class AgentTest {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  &lt;b&gt;// get an instrumentation from the agent&lt;/b&gt;&lt;br /&gt;  Instrumentation i = Agent.getInstrumentation();&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;// here, print "a"&lt;/b&gt;&lt;br /&gt;  TestClass t1 = new TestClass();&lt;br /&gt;  t1.myMethod();&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;// doing bytecode manipulation, &lt;br /&gt;  // replace a new method body for "myMethod"&lt;/b&gt;&lt;br /&gt;  CtClass ct = ClassPool.getDefault().get(TestClass.class.getName());&lt;br /&gt;  CtMethod m = ct.getDeclaredMethod("myMethod");&lt;br /&gt;  m.setBody("{ System.out.println(\"b\");}"); &lt;b&gt;// make it printing "b"&lt;/b&gt;&lt;br /&gt;  byte[] bytes = ct.toBytecode();&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;// prepare a new class definition&lt;/b&gt;&lt;br /&gt;  ClassDefinition[] def=new ClassDefinition[1];&lt;br /&gt;  def[0] = new ClassDefinition(TestClass.class, bytes);&lt;br /&gt;  i.redefineClasses(def);&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;// this shows "b"&lt;/b&gt;&lt;br /&gt;  TestClass t2 = new TestClass();&lt;br /&gt;  t2.myMethod();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;You might see that the above code get instrumentation from the Agent class, which is in a jar loaded by -javaagent:jarfile. In this experiment, I use Javassist for bytecode manipulation.&lt;br /&gt;&lt;br /&gt;As you expected, the above code will show:&lt;br /&gt;&lt;p class="code"&gt;a&lt;br /&gt;b&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;as the TestClass has been re-defined and its method, &lt;b&gt;myMethod&lt;/b&gt;, body's been replaced.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5919759541357587092?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5919759541357587092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5919759541357587092' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5919759541357587092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5919759541357587092'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/08/possible-jit-for-groovy-with-jvmti.html' title='Possible JIT for Groovy with JVMTI'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7547984173821928577</id><published>2007-07-16T22:13:00.000+07:00</published><updated>2007-07-16T22:22:33.062+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Groovy AOP coming soon on the desktop near you.</title><content type='html'>I've just committed the early Groovy AOP's grammar, its compilation unit, and ant task. Actually, everything is getting to work now, but I'd like to add some advice caching mechanism to have, at least, some performance impression.&lt;br /&gt;&lt;br /&gt;I'm trying to have it released by the end of this month (July 2007).&lt;br /&gt;&lt;br /&gt;If you'd like to see what's going on in the mean time, check out its &lt;a href="http://svn.grails-plugins.codehaus.org/browse/grails-plugins/grails-aop"&gt;SVN&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7547984173821928577?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7547984173821928577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7547984173821928577' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7547984173821928577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7547984173821928577'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/07/groovy-aop-coming-soon-on-desktop-near.html' title='Groovy AOP coming soon on the desktop near you.'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4275994452758169023</id><published>2007-05-05T04:35:00.000+07:00</published><updated>2007-05-05T04:45:56.912+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>XFire plugin for Grails 0.5 released</title><content type='html'>I've released the XFire plugin for Grails 0.5 recently. Now it's using XFire 1.2.6 and &lt;br /&gt;Its forked aegis engine has been updated as well. In Grails 0.5, the Artefact APIs for plugin development has been introduced. All Grails core artefacts (domain, controller, etc.) are moved to use these APIs.&lt;br /&gt;&lt;br /&gt;This week seems to be a 0.5-plugin-release week. Beside my XFire, we now have Tsuyoshi's Acegi, Sigi's converters, and Peter's remoting plugins running for 0.5. Check them out on &lt;a href="http://grails.codehaus.org/Plugins"&gt;Grails Plugins Page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4275994452758169023?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4275994452758169023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4275994452758169023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4275994452758169023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4275994452758169023'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/05/xfire-plugin-for-grails-05-released.html' title='XFire plugin for Grails 0.5 released'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5983216424829973986</id><published>2007-05-01T18:59:00.000+07:00</published><updated>2007-05-01T19:15:26.158+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>JIT dynamic weaving for Groovy AOP</title><content type='html'>From the previous &lt;a href="http://chanwit.blogspot.com/2007/04/patterns-for-selecting-metaclass-will.html"&gt;post&lt;/a&gt;, I was talking about selecting metaclass using pattern will give some benefits for AOP in Groovy. Now I come up with a cool idea of what is that benefit. The point here is about MOP infrastructure of Groovy is flexible enough by letting us to change the metaclass of any class at runtime, and this allow JIT (Just-in-Time) dynamic weaving of aspects for Groovy.&lt;br /&gt;&lt;br /&gt;What does it mean by JIT dynamic weaving?&lt;br /&gt;&lt;br /&gt;In my current implementation of Groovy AOP, there's a big overhead of matching pointcuts and invoking advices in the AOP metaclass, but this process can be improved by assigning a new, optimised, metaclass to the woven class. This new metaclass will be generated at runtime (using any bytecode manipulation framework) and it will contain a minimum set of instructions for invoking advices (no more matching process). However, there're still some important open questions like conflictions, etc. that need to be further investigated.&lt;br /&gt;&lt;br /&gt;I'm pretty sure that this technique can improve some performance for Groovy AOP. Although, it's obviously slower than &lt;a href="http://eclipse.org/aspectj"&gt;AspectJ&lt;/a&gt;, but it's worth comparing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5983216424829973986?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5983216424829973986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5983216424829973986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5983216424829973986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5983216424829973986'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/05/jit-dynamic-weaving-for-groovy-aop.html' title='JIT dynamic weaving for Groovy AOP'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-296162993282746162</id><published>2007-04-28T05:37:00.000+07:00</published><updated>2008-11-13T19:05:12.964+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Groovy running fine on .NET</title><content type='html'>It's just a crazy idea to test Groovy on .NET, after I read this &lt;a href="http://weblog.ikvm.net/PermaLink.aspx?guid=d33a3f51-c6fc-4aaa-b3ce-64b742017c40"&gt;post&lt;/a&gt; on IKVM weblog that the author test IKVM using JRuby. If JRuby runs fine, probably Groovy does so.&lt;br /&gt;&lt;br /&gt;Simple steps here,&lt;br /&gt;&lt;br /&gt;1. Download .NET 2.0 Runtime.&lt;br /&gt;2. Download SharpDevelop IDE 2.1, just in case that you're lazy enough to code.&lt;br /&gt;3. Download IKVM for .NET 0.34 rc2 binary&lt;br /&gt;4. compile your Groovy jar with the following command:&lt;br /&gt;&lt;pre&gt;ikvmc -target:library groovy-all-1.1-SNAPSHOT.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Some errors will appear, just ignore them.&lt;br /&gt;You'll get groovy-all-1.1-SNAPSHOT.dll.&lt;br /&gt;&lt;br /&gt;5. Open SharpDevelop, create a new .NET console application.&lt;br /&gt;6. Add references, all IKVM DLLs and your groovy DLL.&lt;br /&gt;7. Open your main class, type the following code (in C# for example)&lt;br /&gt;&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;namespace GroovyDotNet {&lt;br /&gt;  class MainClass {&lt;br /&gt;    public static void Main(string[] args) {&lt;br /&gt;      groovy.ui.InteractiveShell.main(args);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;8. Run the program, and you'll also have an executable file as well.&lt;br /&gt;&lt;br /&gt;Alright, if you don't want to get your hand dirty, do step 1 and wait for the binary. I'll upload it soon.&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;Here's the screen shot.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7gu9HQYUUjE/RjO5oDsuJQI/AAAAAAAAAA8/uMJtQyL697A/s1600-h/groovy_net.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_7gu9HQYUUjE/RjO5oDsuJQI/AAAAAAAAAA8/uMJtQyL697A/s400/groovy_net.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5058590904305984770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and here's the &lt;a href="http://docs.codehaus.org/download/attachments/77491/groovy_net.zip"&gt;binary&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-296162993282746162?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/296162993282746162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=296162993282746162' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/296162993282746162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/296162993282746162'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/groovy-running-fine-on-net.html' title='Groovy running fine on .NET'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7gu9HQYUUjE/RjO5oDsuJQI/AAAAAAAAAA8/uMJtQyL697A/s72-c/groovy_net.png' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6845882805391219668</id><published>2007-04-24T23:22:00.000+07:00</published><updated>2007-04-24T23:24:01.856+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Patterns for selecting metaclass will allow better support AOP in Groovy</title><content type='html'>I'm still being with quantification thoughts for dynamic AOP. &lt;br /&gt;&lt;br /&gt;There're some diffirences between dynamic and static weaving implementation. I'm saying about what AspectJ does, and what I'm going to do with Groovy AOP.&lt;br /&gt;&lt;br /&gt;In AspectJ, it's focusing on static weaving for better performance. The idea behind is that every dynamic joinpoint has the corresponding static shadow, which is projected on source or bytecode of the target program. All quantifying will be done by AspectJ compiler to match every defined pointcuts, of course, at compile-time or load-time. Easy kinds of quantifiable joinpint are, for example, constructors and methods.&lt;br /&gt;&lt;br /&gt;But nothing like this exists when we're talking about dynamic AOP. Dynamic AOP has nothing to do about 'static' shadows. This kind of weaving allows re-definition of aspect at run-time. Dynamic joinpoint in Groovy is powerful and a bit more complex to implement because of its MOP mechanism. Every class in Groovy has its own Metaclass to control the behaviour. ACtually, from AOP perspective, the metaclass can be though of as a basic per-target aspect. But when we're saying about AOP weaving, it allows multiple aspects to weave into a single target class. Comparing with MOP in Groovy, it's clear that AOP is somehow more powerful. In case of my AOP implementation, I have the AOP-metaclass to help dispatching advices. &lt;br /&gt;&lt;br /&gt;So what's more ?&lt;br /&gt;&lt;br /&gt;To fully support AOP quantification in Groovy, I came up with pattern matching idea to assign a metaclass for the target class. I'm feeling strange with this. I'm thinking of it as a good way to support pointcut-advice AOP model for Groovy. But there's something interesting about it that's beyond my head. &lt;br /&gt;&lt;br /&gt;I hope I can figure it out soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6845882805391219668?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6845882805391219668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6845882805391219668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6845882805391219668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6845882805391219668'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/patterns-for-selecting-metaclass-will.html' title='Patterns for selecting metaclass will allow better support AOP in Groovy'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4072493680851473385</id><published>2007-04-22T17:46:00.000+07:00</published><updated>2007-04-22T17:55:07.631+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Ubuntu 7.04</title><content type='html'>Ubuntu Linux 7.04 came out, I did upgrade and everything goes fine.&lt;br /&gt;Many guys in Java community get excited that JDK 1.6 is already in it's repository. My OpenOffice got updated to 2.2 as well, and that's great. &lt;br /&gt;&lt;br /&gt;I've also tried it in VMWare player and, of course, there's no correct driver for 7.04 at the moment. The problem I have is just about the mouse. But it's not a big deal, I tweaked XOrg.conf and set the driver back to the original one ("mouse" instead of "vmmouse").&lt;br /&gt;&lt;br /&gt;My new Ubuntu experience has just started !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4072493680851473385?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4072493680851473385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4072493680851473385' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4072493680851473385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4072493680851473385'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/ubuntu-704.html' title='Ubuntu 7.04'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-75702223575513970</id><published>2007-04-21T18:17:00.000+07:00</published><updated>2007-04-21T19:41:22.361+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>AOP for Groovy is here !! Code moved to be Grails-AOP</title><content type='html'>AOP for Groovy is here !&lt;br /&gt;&lt;br /&gt;I've just refactored and uploaded my AOP subsystem into the Grails-Plugins repo. Anyway, it cannot say that this AOP implementation is Grails-Plugins. It's likely to be a drop-in module because it contains ObjectMetaClass that will hook into system-wide metaclass instantiation process.&lt;br /&gt;&lt;br /&gt;This is an AspectJ-like, the pointcut-advice model implementation of AOP for Groovy. Both 2 important properties of AOP, Quantification and Obliviousness, has been implemented by design.&lt;br /&gt;&lt;br /&gt;Browse the repo: &lt;a href="http://svn.codehaus.org/grails-plugins/grails-aop/"&gt;http://svn.codehaus.org/grails-plugins/grails-aop/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-75702223575513970?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/75702223575513970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=75702223575513970' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/75702223575513970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/75702223575513970'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/aop-code-moved-to-be-grails-aop.html' title='AOP for Groovy is here !! Code moved to be Grails-AOP'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7359102331284679924</id><published>2007-04-19T02:52:00.000+07:00</published><updated>2007-04-23T23:02:02.588+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>The ways to express pointcuts, the choice is yours</title><content type='html'>From the non-AOP programmers' perspective, the pointcut mini-language in AspectJ seems to be a bit difficult to learn. Before they can start writing some aspects, they need to know background concepts about join points, the way how to quantify them with a combination of pointcut designators, and the way how to express advice codes.&lt;br /&gt;&lt;br /&gt;I cannot argue this because making pointcut languages simple yet powerful is quite an active research in the AOP area.&lt;br /&gt;&lt;br /&gt;Some workaround to solve this problem could be having different kind of way to express pointcuts in one framework. So this means we're going to have several mini-languages inside the host language for describing aspects. They are what I'm going to implement for my AOP subsystem for Groovy.&lt;br /&gt;&lt;br /&gt;For example, call() PCD is a quite common one you often use, so having:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;Test.around['test*'] = {} &lt;b&gt;instead of&lt;/b&gt; around(): call(Test.test*(..)) { }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;can reduce the learning curve.&lt;br /&gt;&lt;br /&gt;But when, the power of the basic pointcut language is not enough, you can use the full version of pointcut language, like this:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;static aspect = {&lt;br /&gt;  def p = pointcut{&lt;br /&gt;        pcall('public *':'set*') &amp; pcall( ... ) &amp; &lt;br /&gt;        within(MyClass:'some*')&lt;br /&gt;  }&lt;br /&gt;  around(p) { context -&gt;&lt;br /&gt;    proceed(context.args)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The choice of expressing pointcuts is just yours.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7359102331284679924?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7359102331284679924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7359102331284679924' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7359102331284679924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7359102331284679924'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/ways-to-express-pointcuts-choice-is.html' title='The ways to express pointcuts, the choice is yours'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4121340328397458571</id><published>2007-04-16T03:21:00.000+07:00</published><updated>2007-04-16T03:32:22.571+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Aspect Groovy: Per class and Per instance</title><content type='html'>From &lt;a href="http://chanwit.blogspot.com/2007/04/groovy-and-aop-metaclass.html"&gt;last post&lt;/a&gt;, I'm going to the next step by re-implementing my AOPSupportMetaClass again in Java to have some precise controls. Now the AOP metaclass got updated and support weaving both per class and per instance. However, the pointcut expression style is still based on &lt;a href="http://www.infoq.com/articles/aop-with-groovy"&gt;John McClean's implementation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is for per instance weaving&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt; def t = new TestObject()&lt;br /&gt; t.around['save'] = { inv -&gt;&lt;br /&gt;   inv.args[0] = inv.args[0] + '.'&lt;br /&gt;   inv.proceed(inv.args)     &lt;br /&gt; }&lt;br /&gt; t.save('test')&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;And you can guess, this is per class weaving&lt;br /&gt;&lt;p class="code"&gt; &lt;br /&gt; TestObject.around['save'] = { inv -&gt;&lt;br /&gt;   inv.args[0] = inv.args[0] + '.'&lt;br /&gt;   inv.proceed(inv.args)     &lt;br /&gt; }&lt;br /&gt; def t = new TestObject()&lt;br /&gt; t.save('test')&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Last test code can be obtained from &lt;a href="http://bnclone.googlecode.com/svn/trunk/sandbox/pl_aop/src/org/plaop/AOPSupportMetaClass.java"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4121340328397458571?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4121340328397458571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4121340328397458571' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4121340328397458571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4121340328397458571'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/aspect-groovy-per-class-and-per.html' title='Aspect Groovy: Per class and Per instance'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7638499941546306929</id><published>2007-04-15T04:29:00.000+07:00</published><updated>2007-04-15T04:47:45.174+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Groovy and AOP Metaclass</title><content type='html'>I've recently found John McClean's last year &lt;a href="http://www.infoq.com/articles/aop-with-groovy"&gt;article&lt;/a&gt; about AspectJ-like AOP model implemented in Groovy. In its comments, his readers posted that he should have a custom MetaClass to support his approach. I'm sure he probably did it because he's going to talk about AOP in Groovy at &lt;a href="http://grails-exchange.com"&gt;Grails Exchange&lt;/a&gt; conference this May. However based on his implementation, I've done the similar MetaClass as well, as I need some kind of AOP facility to support my research.&lt;br /&gt;&lt;br /&gt;Probably after the Grails Exchange event, I can see his AOP code somewhere.&lt;br /&gt;&lt;br /&gt;Here's my implementation:&lt;br /&gt;&lt;p class="code"&gt;package org.plaop;&lt;br /&gt;&lt;br /&gt;import groovy.lang.DelegatingMetaClass&lt;br /&gt;&lt;br /&gt;public class AOPSupportMetaClass extends DelegatingMetaClass {&lt;br /&gt;&lt;br /&gt;  def after = [:]&lt;br /&gt;  def before = [:]&lt;br /&gt;  def around = [:]  &lt;br /&gt;&lt;br /&gt;  public AOPSupportMetaClass(MetaClass delegate) {&lt;br /&gt;    super(delegate);    &lt;br /&gt;    initialize();&lt;br /&gt;  }&lt;br /&gt;    &lt;br /&gt;  public Object getProperty(Object object, String prop) {&lt;br /&gt;    if(prop == 'around') return this.around else&lt;br /&gt;    if(prop == 'before') return this.before else&lt;br /&gt;    if(prop == 'after') return this.after else&lt;br /&gt;    return super.getProperty(object, prop)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Object invokeMethod(Object arg0, String name, Object[] args) {&lt;br /&gt;    if(before[name]!=null) {&lt;br /&gt;      before[name](inv)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def inv = new InvocationContext(methodName: name, args: args, called: arg0)&lt;br /&gt;    inv.proceed = { arglist -&gt;&lt;br /&gt;      super.invokeMethod(arg0, name, arglist)     &lt;br /&gt;    }&lt;br /&gt;        &lt;br /&gt;    def result = null&lt;br /&gt;    if(around[name]!=null) {&lt;br /&gt;      result = around[name](inv)&lt;br /&gt;    } else {&lt;br /&gt;      result = super.invokeMethod(arg0, name, args)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    inv.proceed = null&lt;br /&gt;    &lt;br /&gt;    if(after[name]!=null) {&lt;br /&gt;      after[name](inv)&lt;br /&gt;    }&lt;br /&gt;    return result&lt;br /&gt;  }   &lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;This is how to use it:&lt;br /&gt;&lt;p class="code"&gt;void testBasicAround() {        &lt;br /&gt;  def mcr = InvokerHelper.getInstance().metaRegistry    &lt;br /&gt;  AOPSupportMetaClass amc = new AOPSupportMetaClass(&lt;br /&gt;                            mcr.getMetaClass(TestObject.class))&lt;br /&gt;  mcr.setMetaClass(TestObject.class, amc)&lt;br /&gt;  &lt;br /&gt;  def t = new TestObject()&lt;br /&gt;  t.around['save'] = { inv -&gt;&lt;br /&gt;    inv.args[0] = inv.args[0] + '.'&lt;br /&gt;    inv.proceed(inv.args)&lt;br /&gt;  }&lt;br /&gt;  t.save('test')&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The big bug here is that this MetaClass hasn't yet supported per class weaving model. But it's not that hard to implement. John's article really realised me the power of Groovy MOP from AOP perspective.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7638499941546306929?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7638499941546306929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7638499941546306929' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7638499941546306929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7638499941546306929'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/groovy-and-aop-metaclass.html' title='Groovy and AOP Metaclass'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7232935034522951038</id><published>2007-04-08T21:26:00.000+07:00</published><updated>2007-04-08T21:44:21.163+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Invariant Dynamic Calls</title><content type='html'>Basically, dynamically typed languages, &lt;a href="http://groovy.codehaus.org"&gt;Groovy&lt;/a&gt; in this context, dispatch calls by firstly choosing appropriate methods, then invoking them. The choosing process is obviously expensive. Several techniques, such as method caching, are currently implemented in Groovy to speed things up. However, choosing methods through reflection won't allow JIT to optimise method bodies for callers. With caching, the shortest steps for Groovy are still:&lt;br /&gt;&lt;p class="code"&gt;calling an invokeX method -&gt; looking up cache -&gt; calling the cached chosen method,&lt;br /&gt;&lt;/p&gt;and you can not further optimise the invocation beyond this point.&lt;br /&gt;&lt;br /&gt;The only way to do this is to simply replace that call by the chosen method call.&lt;br /&gt;It's basic and everyone on the groovy-dev list knows about this (I supposed). Anyway, there're a lot arguments in the list that we should preserve the "dynamicity" of Groovy. I agree with those arguments, so we should leave Groovy core as it is, but we can really do somethings at the application level, in production phase.&lt;br /&gt;&lt;br /&gt;During unit testing, developers may find sets of "&lt;span style="font-weight:bold;"&gt;invariant dynamic calls&lt;/span&gt;" of their applications. I roughly define an invariant dynamic call as a call that has only one chosen method. Trivial examples for this kind of call in &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt; framework are Domain class' .save() and .delete(). If we assume that our test suites cover the application enough, so we can basically conclude that each dynamic call identified by the test suites is an &lt;span style="font-weight:bold;"&gt;invariant dynamic call&lt;/span&gt;, if there is only one chosen method for it. Then, we just simply replace these calls with static signatures, in class files or even by on-the-fly transformation, to gain performance back.&lt;br /&gt;&lt;br /&gt;My current technique to analyse calls at bytecode-level is, firstly scanning for ScriptBytecodeAdapter.invoke*, then reverse looking for LDC "methodName" and other arguments that will be stored onto the stack.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Beyond Java 6&lt;/b&gt;&lt;br /&gt;I dont exactly know when INVOKEDYNAMIC will arrive, but with this instruction replacing invariant dynamic calls will be much easier by &lt;br /&gt;1. changing INVOKEDYNAMIC to appropriate kind of invoke, say INVOKEVIRTUAL, INVOKESPACIAL, INVOKESTATIC or INVOKEINTERFACE.&lt;br /&gt;2. changing type descriptors to the correct classes.&lt;br /&gt;&lt;br /&gt;I haven't followed the spec of INVOKEDYNAMIC at the moment, it's time to have a quick read again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7232935034522951038?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7232935034522951038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7232935034522951038' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7232935034522951038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7232935034522951038'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/04/invariant-dynamic-calls.html' title='Invariant Dynamic Calls'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-3167440247884738800</id><published>2007-03-31T06:04:00.000+07:00</published><updated>2007-03-31T06:10:27.011+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OpenLaszlo'/><category scheme='http://www.blogger.com/atom/ns#' term='RIA'/><title type='text'>OpenLaszlo 4.0.0</title><content type='html'>OpenLaszlo 4 released a few days ago. I was impressed with its CSS support, although it's a pull (not push - like HTML's CSS) style. Anyway I've found some bugs that prevented me from compiling an LZX program for the DHTML runtime. Hopefully, these bugs will be get fixed soon. &lt;br /&gt;&lt;br /&gt;Another thing is that styles, which are working well in Flash runtimes, doesn't work for the DHTML runtime as well. However, these bugs don't stop me from using this great software !!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-3167440247884738800?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/3167440247884738800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=3167440247884738800' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3167440247884738800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/3167440247884738800'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/03/openlaszlo-400.html' title='OpenLaszlo 4.0.0'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-2509297886055555692</id><published>2007-03-24T04:49:00.000+07:00</published><updated>2008-11-13T19:05:13.400+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hotspot'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Get OpenJDK Hotspot Compiled !</title><content type='html'>I'm very newbie on hacking JVM and I'm very happy to get OpenJDK Hotspot B10 compiled on Ubuntu 6.10. Compilation time is 1 hour and 5 mins. Actually, what I'm wanting to do from now on is to add some modification into its interpreter mode. Everything's just started.&lt;br /&gt;&lt;br /&gt;Some configuration&lt;br /&gt;- OpenJDK Hotspot VM 7-EA-B10 (21 Mar 07)&lt;br /&gt;- Importing JDK 1.6_01 &lt;br /&gt;- Ubuntu 6.10&lt;br /&gt;- GCC 4.1.2 (Ubuntu 4.1.1-13ubuntu5)&lt;br /&gt;- Linux 2.6.17-11&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7gu9HQYUUjE/RgROpWQ2vII/AAAAAAAAAA0/hcLl6De9tng/s1600-h/hotspot.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_7gu9HQYUUjE/RgROpWQ2vII/AAAAAAAAAA0/hcLl6De9tng/s400/hotspot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5045243954819677314" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-2509297886055555692?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/2509297886055555692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=2509297886055555692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2509297886055555692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/2509297886055555692'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/03/get-openjdk-hotspot-compiled.html' title='Get OpenJDK Hotspot Compiled !'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_7gu9HQYUUjE/RgROpWQ2vII/AAAAAAAAAA0/hcLl6De9tng/s72-c/hotspot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6374588121676772917</id><published>2007-02-05T18:37:00.000+07:00</published><updated>2007-02-05T18:44:37.995+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Flattening Xml to Map using depthFirst</title><content type='html'>It's very wonderful and extremely easy to use groovy.xml.XmlParser to flatten an XML document into a Grails compatible Map:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;  def Map xmlToMap(String xml) {&lt;br /&gt;    def root = new XmlParser().parseText(xml)&lt;br /&gt;    def map = [:]&lt;br /&gt;    root.depthFirst().each { n -&gt;     &lt;br /&gt;      if(n.value.size == 1) {&lt;br /&gt;        def key = n.name&lt;br /&gt;        def p = n.parent&lt;br /&gt;        while(p.parent != null) {&lt;br /&gt;          key = "${p.name}.${key}"&lt;br /&gt;          p = p.parent&lt;br /&gt;        }&lt;br /&gt;        map[key] = n.value[0]&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    return map&lt;br /&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/7910126-6374588121676772917?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6374588121676772917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6374588121676772917' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6374588121676772917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6374588121676772917'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/02/flattening-xml-to-map-using-depthfirst.html' title='Flattening Xml to Map using depthFirst'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5940606009954859918</id><published>2007-02-04T11:27:00.000+07:00</published><updated>2007-02-04T11:31:01.788+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Multiple Assignment soon in Groovy 1.1</title><content type='html'>Beside other cool features, the last entry in &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GDC+3+report"&gt;GDC 3 report&lt;/a&gt; about what's going to be added into Groovy 1.1 is &lt;span style="font-style:italic;"&gt;multiple assignment&lt;/span&gt;. I'm definitely looking forward to use it !!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5940606009954859918?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5940606009954859918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5940606009954859918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5940606009954859918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5940606009954859918'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/02/multiple-assignment-soon-in-groovy-11.html' title='Multiple Assignment soon in Groovy 1.1'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-939829035472378424</id><published>2007-02-04T11:21:00.000+07:00</published><updated>2007-02-04T11:24:53.953+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>GORM and Data Grid</title><content type='html'>Graeme Rocher &lt;a href="http://graemerocher.blogspot.com/2007/01/of-activerecordgorm-and-dao-patterns.html"&gt;revealed&lt;/a&gt; the possibility for GORM to support data grid on top of Terracotta or Tangasol Coherence.&lt;br /&gt;&lt;br /&gt;This's going to be a big impact, at least, from my research perspective.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-939829035472378424?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/939829035472378424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=939829035472378424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/939829035472378424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/939829035472378424'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/02/gorm-and-data-grid.html' title='GORM and Data Grid'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4091422445471997787</id><published>2007-02-04T11:10:00.000+07:00</published><updated>2007-02-04T11:15:14.949+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Groovy is the most interesting JVM-based non-Java language</title><content type='html'>By Java.net &lt;a href="http://www.java.net/pub/pq/143"&gt;poll&lt;/a&gt;, Groovy gets 27.3% and becomes the most interesting non-Java language running on JVM. However, JRuby ranks no. 2 with 20.9%.&lt;br /&gt;&lt;br /&gt;This survey gives a good picture of Groovy, and of course Grails, momentum.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4091422445471997787?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4091422445471997787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4091422445471997787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4091422445471997787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4091422445471997787'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/02/groovy-is-most-interesting-jvm-based.html' title='Groovy is the most interesting JVM-based non-Java language'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-7039373380512020837</id><published>2007-01-22T07:37:00.000+07:00</published><updated>2007-02-03T18:30:20.156+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Configuring Grails datasource with a .properties file</title><content type='html'>A Grails user needs to configure Grails data sources with an external .properties file (&lt;a href="http://www.nabble.com/PropertyPlaceholderConfigurer-in-resources.xml-tf3045830.html"&gt;posted here&lt;/a&gt;), but having Spring beans inside "resources.xml" for it won't work for some reasons. I was trying to investigate what's going on, and found that there're steps done by Grails Hibernate plugin to retrieve references of datasouce before some beans defined in "resources.xml" are processed.&lt;br /&gt;&lt;br /&gt;Anyway, I like the concept of using .properties file as well. So I modified *some*DataSource.groovy to see how can I use .properties to fill the data source properties, and here's the code:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;import java.util.Properties&lt;br /&gt;import org.springframework.core.io.FileSystemResource&lt;br /&gt;&lt;br /&gt;class DevelopmentDataSource {&lt;br /&gt;   &lt;br /&gt;  def static propFile = "web-app/WEB-INF/conf.properties"; &lt;br /&gt;&lt;br /&gt;  boolean pooling = true&lt;br /&gt;  String dbCreate = "create-drop" &lt;br /&gt;   &lt;br /&gt;  String url&lt;br /&gt;  String driverClassName&lt;br /&gt;  String username&lt;br /&gt;  String password&lt;br /&gt;  &lt;br /&gt;  public DevelopmentDataSource() {&lt;br /&gt;    def props = new Properties()&lt;br /&gt;    try {       &lt;br /&gt;      props.load(new FileSystemResource(propFile).inputStream)&lt;br /&gt;    } catch(Exception e){&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    this.driverClassName = props.getProperty("jdbc.driver","org.hsqldb.jdbcDriver")&lt;br /&gt;    this.url = props.getProperty("jdbc.url","jdbc:hsqldb:mem:inDB")&lt;br /&gt;    this.username = props.getProperty("jdbc.username","sa")&lt;br /&gt;    this.password = props.getProperty("jdbc.password","")   &lt;br /&gt;  }      &lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;I know that it's not an elegant solution for the moment, but it works :).&lt;br /&gt;With this modified datasource, you use the "propFile" to point to some file outside .WAR, and have some better level of abstraction.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-7039373380512020837?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/7039373380512020837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=7039373380512020837' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7039373380512020837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/7039373380512020837'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/01/grails-user-needs-to-configure-grails.html' title='Configuring Grails datasource with a .properties file'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-1623442376404536907</id><published>2007-01-20T05:20:00.000+07:00</published><updated>2007-01-20T05:24:43.180+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>XFire plugin changed convention and upgraded to XFire 1.2.4</title><content type='html'>I've patched the XFire plugin to 1.2.4 and changed some convention to be more compatible with Grails.&lt;br /&gt;Now you can just tweak your Grails services to be Web services by adding the static property 'expose'.&lt;br /&gt;Here's an example:&lt;br /&gt;&lt;p class="code"&gt;class TestService {&lt;br /&gt;&lt;br /&gt;  static expose=['xfire']&lt;br /&gt;&lt;br /&gt;  def String doSomething(DomainClass dc) {&lt;br /&gt;    return "done"&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def String getData() {&lt;br /&gt;    return "data"&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def void setSomething(String something) {&lt;br /&gt;    // set some values here&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The current build is going to skip all properties in a service, including transactional.&lt;br /&gt;However, it's smart enough to expose some methods like 'getData' or void 'setSomething' correctly.&lt;br /&gt;The policy used to expose methods in this build will detect existence of both "getter" and "setter" for a property.&lt;br /&gt;Because in Groovy and Grails, we usually have property by simply defining a property with the '&lt;b&gt;def&lt;/b&gt;' keyword.&lt;br /&gt;&lt;br /&gt;BTW, I was trying to compile it using JDK 1.4 but nothing works.&lt;br /&gt;Some type casting exception has been occurred inside XFireSpringServlet and I cannot fix it yet.&lt;br /&gt;So please stay tuned if you're going to use this plugin with Grails on 1.4 VM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-1623442376404536907?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/1623442376404536907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=1623442376404536907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1623442376404536907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/1623442376404536907'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/01/xfire-plugin-changed-convention-and.html' title='XFire plugin changed convention and upgraded to XFire 1.2.4'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-5546960833277055232</id><published>2007-01-11T13:27:00.000+07:00</published><updated>2007-01-11T13:55:45.724+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>I've finally done XFire plugin for Grails</title><content type='html'>Last post, I mentioned about Grails plugin architecture in 0.4. This great feature allows us to develop our own plugins. I firstly thought that it might be difficult to develop my own one. But after having a look into some plugin codes in Grails itself, and another one - &lt;a href="http://grails.org/OpenLaszlo+plugin"&gt;OpenLaszlo plugin&lt;/a&gt;. I finally got some ideas about how the plugin works, and what to do.&lt;br /&gt;&lt;br /&gt;However, I was suffered a bit by bugs from Spring Bean Builder because it doesn't provide complete APIs to cover methods I need, such as "bean.initMethod". Anyway, it's not too hard to figure it out, and I have some workaround to avoid these bugs. I'm planning to fix them soon after my XFire plugin is stable for Grails 0.4.&lt;br /&gt;&lt;br /&gt;So, what's about the XFire plugin for Grails ?&lt;br /&gt;It's a plugin to expose a Grils service as a Web service. Only requirement is that the service must have "XFireService" suffix. The plugin scans pulbic methods of the service, and generates complex type definition for parameter and return types using a modified XFire's Aegis engine.&lt;br /&gt;For a Grails domain class, this plugin will generate type information for every properties, including "id", but it will ignore "version" and other Groovy specific properties. &lt;br /&gt;If you want to exclude some methods, you can define "static excludes = []" in the service.&lt;br /&gt;&lt;br /&gt;Here's some example:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;class MyXFireService {&lt;br /&gt;&lt;br /&gt;  def static excludes = ["notMe"]&lt;br /&gt;  &lt;br /&gt;  def String myMethod(MyDomain d) {&lt;br /&gt;    d.save()&lt;br /&gt;    return "test"&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def String notMe() {&lt;br /&gt;    return "nothing"&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;I've added a page for this plugin at Grails space here:&lt;br /&gt;&lt;a href="http://grails.org/XFire+plugin"&gt;http://grails.org/XFire+plugin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-5546960833277055232?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/5546960833277055232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=5546960833277055232' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5546960833277055232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/5546960833277055232'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/01/ive-finally-done-xfire-plugin-for.html' title='I&apos;ve finally done XFire plugin for Grails'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-8257655555657986630</id><published>2007-01-06T16:44:00.000+07:00</published><updated>2007-01-08T06:55:34.947+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>XFire for Grails Applications - the pre-plugin Era</title><content type='html'>I've updated my Grails from 0.3.1 to 0.4 snapshot and its new coming plug-in architecture looks very promising.  I'm hoping that someone will implement an XFire plugin for Grails soon (mentioned some where in Grails' wiki). Anyway, I'm going to talk about how to integrate XFire into an Grails application manually. &lt;br /&gt;&lt;br /&gt;Here, I briefly show you steps to integrate annotation-based XFire Web services into your Grails Applications.&lt;br /&gt;&lt;br /&gt;1. download XFire distro (I'm using 1.2.3).&lt;br /&gt;2. put everything (.jar files) of XFire into ${YOUR_GRAILS_APP}\lib&lt;br /&gt;3. create your Web service class in src/java&lt;br /&gt;4. modify resources.xml&lt;br /&gt;5. modify web.template.xml&lt;br /&gt;6. grails run-app&lt;br /&gt;&lt;br /&gt;It's still configuration-based approach, not conventional yet.&lt;br /&gt;Anyway, this might be useful to someone, who currently need to use XFire, when the XFire plugin still be an imaginary thing.&lt;br /&gt;&lt;br /&gt;Note that, this covers only HTTP-based transportation of XFire, since Grails is mainly for Web.&lt;br /&gt;&lt;br /&gt;Let's go into details:&lt;br /&gt;Before starting, you have to put all XFire .jar files into your &lt;grails-app&gt;/lib folder first.&lt;br /&gt;&lt;br /&gt;So, you can start by put your annotation-based classes in "src/java" folder.&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;@WebService&lt;br /&gt;public class MyService {&lt;br /&gt;&lt;br /&gt;  @WebMethod&lt;br /&gt;  public String doSomething() {&lt;br /&gt;    return "hello";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @WebMethod(exclude=true)&lt;br /&gt;  public void hideMePlease() {&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;what you needs are modification of "resources.xml" for spring, and "web.template.xml".&lt;br /&gt;&lt;br /&gt;OK, then add some XML chunks into your spring/resources.xml&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"&lt;br /&gt;    "http://www.springframework.org/dtd/spring-beans.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;beans&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- You need this line to import "xfire" and &lt;br /&gt;    "xfire.transportManager" references in --&amp;gt;&lt;br /&gt;    &amp;lt;import resource="classpath:org/codehaus/xfire/spring/xfire.xml" /&amp;gt;&lt;br /&gt;  &lt;br /&gt;    &amp;lt;!-- Your service goes here --&amp;gt;&lt;br /&gt;    &amp;lt;bean name="myService" class="org.codehaus.xfire.spring.ServiceBean"&amp;gt;&lt;br /&gt;        &amp;lt;property name="xfire" ref="xfire"/&amp;gt;&lt;br /&gt;        &amp;lt;property name="serviceBean" ref="myService"/&amp;gt;&lt;br /&gt;        &amp;lt;property name="serviceClass" value="MyService"/&amp;gt;&lt;br /&gt;        &amp;lt;property name="serviceFactory" ref="jsr181"/&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt; &lt;br /&gt;  &lt;br /&gt;  &amp;lt;!-- Here's initialising an "jsr181" instance to be &lt;br /&gt;     a factory object for your services --&amp;gt;&lt;br /&gt;  &amp;lt;bean id="jsr181"  &lt;br /&gt;    class="org.codehaus.xfire.spring.config.ServiceFactoryBean"&lt;br /&gt;    init-method="initialize"&amp;gt;&lt;br /&gt;    &amp;lt;constructor-arg index="0" value="jsr181" /&amp;gt;&lt;br /&gt;    &amp;lt;property name="transportManager" ref="xfire.transportManager" /&amp;gt;&lt;br /&gt;  &amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;p&gt;&lt;br /&gt;Finally, put some servlet configuration into your "web.template.xml", like this&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;    &amp;lt;servlet-name&amp;gt;XFireServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;    &amp;lt;display-name&amp;gt;XFire Servlet&amp;lt;/display-name&amp;gt;&lt;br /&gt;    &amp;lt;servlet-class&amp;gt;&lt;br /&gt;        org.codehaus.xfire.spring.XFireSpringServlet&lt;br /&gt;    &amp;lt;/servlet-class&amp;gt;&lt;br /&gt;    &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;        &lt;br /&gt;  &amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;    &amp;lt;servlet-name&amp;gt;XFireServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;    &amp;lt;url-pattern&amp;gt;/servlet/XFireServlet/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;  &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;    &amp;lt;servlet-name&amp;gt;XFireServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;    &amp;lt;url-pattern&amp;gt;/services/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;  &amp;lt;/servlet-mapping&amp;gt;&lt;/p&gt;&lt;br /&gt;OK, let's type "grails run-app" and browse to "http://localhost:8080/${your_grails_app}/services/myService/" to see its WSDL link.&lt;br /&gt;And that's all, your XFire service is now ready.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-8257655555657986630?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/8257655555657986630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=8257655555657986630' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/8257655555657986630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/8257655555657986630'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2007/01/xfire-for-grails-applications-pre.html' title='XFire for Grails Applications - the pre-plugin Era'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-6563725150046326478</id><published>2006-12-08T10:45:00.000+07:00</published><updated>2007-01-06T16:44:17.021+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Are you suffering from using Dojo in Grails ?</title><content type='html'>Everything works fine for Grails 0.3.1 when I'm not using Dojo.&lt;br /&gt;But after I'm using it with Grails, I'm suffering from the 100% CPU usage.&lt;br /&gt;This performance hit's caused by Jetty (Grails' default server) is trying to response Dojo files.&lt;br /&gt;&lt;br /&gt;From my understanding, it might be that &lt;br /&gt;1. Jetty in Grails distribution has not been configured for this purpose ? or&lt;br /&gt;2. It's normal that a Servlet container's not good at serving a big static file ?&lt;br /&gt;&lt;br /&gt;Anyway, I still don't know what's going on inside the container, but I've got a workaround for this problem.&lt;br /&gt;My current solution is to use &lt;a href="http://www.lighttpd.net/download/"&gt;lighttpd&lt;/a&gt; as the front server to serve this Dojo monster ;)&lt;br /&gt;I connect lighttpd with Grails' server using the mod_proxy.&lt;br /&gt;Here's my current config in &lt;lighttpd&gt;\etc\lighttpd.conf&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;proxy.server = ( "/&lt;Your Grails Project&gt;" =&gt;&lt;br /&gt;                 ( "127.0.0.1" =&gt;&lt;br /&gt;                   (&lt;br /&gt;                      "host" =&gt; "127.0.0.1",&lt;br /&gt;                      "port" =&gt; 8080&lt;br /&gt;                   )&lt;br /&gt;                 )&lt;br /&gt;               )&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Then you need to put your Dojo files into the &lt;lighttpd&gt;\htdocs, and correct all script's references in your GSP pages.&lt;br /&gt;Lighttpd uses the default 80 port. So, you just point your browser to http://127.0.0.1/&lt;Your Grails Project&gt;/, every should work correctly.&lt;br /&gt;&lt;br /&gt;IMO, this solution should work for the production phase as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-6563725150046326478?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/6563725150046326478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=6563725150046326478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6563725150046326478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/6563725150046326478'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/12/are-you-suffering-from-using-dojo-in.html' title='Are you suffering from using Dojo in Grails ?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-4765463076453695400</id><published>2006-12-01T21:12:00.000+07:00</published><updated>2006-12-02T04:02:03.518+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Minimum "rt.jar" for Hello World</title><content type='html'>Here's a list of classes that are needed to run a Java hello world program.&lt;br /&gt;I find this list using &lt;span style="font-weight:bold;"&gt;java -verbose&lt;/span&gt; (motivated by this &lt;a href="http://weblogs.java.net/blog/enicholas/archive/2006/09/java_browser_ed.html"&gt;post&lt;/a&gt;).&lt;br /&gt;&lt;p class="code"&gt;== listfile.txt ==&lt;br /&gt;/java/io/BufferedInputStream.class&lt;br /&gt;/java/io/BufferedOutputStream.class&lt;br /&gt;/java/io/BufferedWriter.class&lt;br /&gt;/java/io/Closeable.class&lt;br /&gt;/java/io/DataInput.class&lt;br /&gt;/java/io/DataInputStream.class&lt;br /&gt;/java/io/ExpiringCache.class&lt;br /&gt;/java/io/ExpiringCache$1.class&lt;br /&gt;/java/io/ExpiringCache$Entry.class&lt;br /&gt;/java/io/File.class&lt;br /&gt;/java/io/FileDescriptor.class&lt;br /&gt;/java/io/FileInputStream.class&lt;br /&gt;/java/io/FileOutputStream.class&lt;br /&gt;/java/io/FilePermission.class&lt;br /&gt;/java/io/FilePermission$1.class&lt;br /&gt;/java/io/FilePermissionCollection.class&lt;br /&gt;/java/io/FileSystem.class&lt;br /&gt;/java/io/FilterInputStream.class&lt;br /&gt;/java/io/FilterOutputStream.class&lt;br /&gt;/java/io/Flushable.class&lt;br /&gt;/java/io/InputStream.class&lt;br /&gt;/java/io/ObjectStreamClass.class&lt;br /&gt;/java/io/ObjectStreamField.class&lt;br /&gt;/java/io/OutputStream.class&lt;br /&gt;/java/io/OutputStreamWriter.class&lt;br /&gt;/java/io/PrintStream.class&lt;br /&gt;/java/io/Serializable.class&lt;br /&gt;/java/io/Win32FileSystem.class&lt;br /&gt;/java/io/WinNTFileSystem.class&lt;br /&gt;/java/io/Writer.class&lt;br /&gt;/java/lang/AbstractStringBuilder.class&lt;br /&gt;/java/lang/Appendable.class&lt;br /&gt;/java/lang/ArithmeticException.class&lt;br /&gt;/java/lang/ArrayStoreException.class&lt;br /&gt;/java/lang/Boolean.class&lt;br /&gt;/java/lang/Byte.class&lt;br /&gt;/java/lang/CharSequence.class&lt;br /&gt;/java/lang/Character.class&lt;br /&gt;/java/lang/CharacterDataLatin1.class&lt;br /&gt;/java/lang/Class.class&lt;br /&gt;/java/lang/Class$1.class&lt;br /&gt;/java/lang/Class$3.class&lt;br /&gt;/java/lang/ClassCastException.class&lt;br /&gt;/java/lang/ClassLoader.class&lt;br /&gt;/java/lang/ClassLoader$3.class&lt;br /&gt;/java/lang/ClassLoader$NativeLibrary.class&lt;br /&gt;/java/lang/ClassNotFoundException.class&lt;br /&gt;/java/lang/Cloneable.class&lt;br /&gt;/java/lang/Comparable.class&lt;br /&gt;/java/lang/Compiler.class&lt;br /&gt;/java/lang/Compiler$1.class&lt;br /&gt;/java/lang/Double.class&lt;br /&gt;/java/lang/Error.class&lt;br /&gt;/java/lang/Exception.class&lt;br /&gt;/java/lang/Float.class&lt;br /&gt;/java/lang/IncompatibleClassChangeError.class&lt;br /&gt;/java/lang/Integer.class&lt;br /&gt;/java/lang/Iterable.class&lt;br /&gt;/java/lang/LinkageError.class&lt;br /&gt;/java/lang/Long.class&lt;br /&gt;/java/lang/Math.class&lt;br /&gt;/java/lang/NoClassDefFoundError.class&lt;br /&gt;/java/lang/NoSuchMethodError.class&lt;br /&gt;/java/lang/NullPointerException.class&lt;br /&gt;/java/lang/Number.class&lt;br /&gt;/java/lang/Object.class&lt;br /&gt;/java/lang/OutOfMemoryError.class&lt;br /&gt;/java/lang/Readable.class&lt;br /&gt;/java/lang/Runnable.class&lt;br /&gt;/java/lang/Runtime.class&lt;br /&gt;/java/lang/RuntimeException.class&lt;br /&gt;/java/lang/RuntimePermission.class&lt;br /&gt;/java/lang/Short.class&lt;br /&gt;/java/lang/Shutdown.class&lt;br /&gt;/java/lang/Shutdown$Lock.class&lt;br /&gt;/java/lang/StackOverflowError.class&lt;br /&gt;/java/lang/StackTraceElement.class&lt;br /&gt;/java/lang/StrictMath.class&lt;br /&gt;/java/lang/String.class&lt;br /&gt;/java/lang/String$CaseInsensitiveComparator.class&lt;br /&gt;/java/lang/StringBuffer.class&lt;br /&gt;/java/lang/StringBuilder.class&lt;br /&gt;/java/lang/StringCoding.class&lt;br /&gt;/java/lang/StringCoding$CharsetSD.class&lt;br /&gt;/java/lang/StringCoding$CharsetSE.class&lt;br /&gt;/java/lang/StringCoding$StringDecoder.class&lt;br /&gt;/java/lang/StringCoding$StringEncoder.class&lt;br /&gt;/java/lang/System.class&lt;br /&gt;/java/lang/System$2.class&lt;br /&gt;/java/lang/SystemClassLoaderAction.class&lt;br /&gt;/java/lang/Terminator.class&lt;br /&gt;/java/lang/Terminator$1.class&lt;br /&gt;/java/lang/Thread.class&lt;br /&gt;/java/lang/Thread$UncaughtExceptionHandler.class&lt;br /&gt;/java/lang/ThreadDeath.class&lt;br /&gt;/java/lang/ThreadGroup.class&lt;br /&gt;/java/lang/ThreadLocal.class&lt;br /&gt;/java/lang/ThreadLocal$ThreadLocalMap.class&lt;br /&gt;/java/lang/ThreadLocal$ThreadLocalMap$Entry.class&lt;br /&gt;/java/lang/Throwable.class&lt;br /&gt;/java/lang/VirtualMachineError.class&lt;br /&gt;/java/lang/annotation/Annotation.class&lt;br /&gt;/java/lang/management/MemoryUsage.class&lt;br /&gt;/java/lang/ref/FinalReference.class&lt;br /&gt;/java/lang/ref/Finalizer.class&lt;br /&gt;/java/lang/ref/Finalizer$FinalizerThread.class&lt;br /&gt;/java/lang/ref/PhantomReference.class&lt;br /&gt;/java/lang/ref/Reference.class&lt;br /&gt;/java/lang/ref/Reference$Lock.class&lt;br /&gt;/java/lang/ref/Reference$ReferenceHandler.class&lt;br /&gt;/java/lang/ref/ReferenceQueue.class&lt;br /&gt;/java/lang/ref/ReferenceQueue$Lock.class&lt;br /&gt;/java/lang/ref/ReferenceQueue$Null.class&lt;br /&gt;/java/lang/ref/SoftReference.class&lt;br /&gt;/java/lang/ref/WeakReference.class&lt;br /&gt;/java/lang/reflect/AccessibleObject.class&lt;br /&gt;/java/lang/reflect/AnnotatedElement.class&lt;br /&gt;/java/lang/reflect/Constructor.class&lt;br /&gt;/java/lang/reflect/Field.class&lt;br /&gt;/java/lang/reflect/GenericDeclaration.class&lt;br /&gt;/java/lang/reflect/Member.class&lt;br /&gt;/java/lang/reflect/Method.class&lt;br /&gt;/java/lang/reflect/Modifier.class&lt;br /&gt;/java/lang/reflect/ReflectAccess.class&lt;br /&gt;/java/lang/reflect/ReflectPermission.class&lt;br /&gt;/java/lang/reflect/Type.class&lt;br /&gt;/java/net/ContentHandler.class&lt;br /&gt;/java/net/Parts.class&lt;br /&gt;/java/net/URL.class&lt;br /&gt;/java/net/URLClassLoader.class&lt;br /&gt;/java/net/URLClassLoader$1.class&lt;br /&gt;/java/net/URLConnection.class&lt;br /&gt;/java/net/URLStreamHandler.class&lt;br /&gt;/java/net/URLStreamHandlerFactory.class&lt;br /&gt;/java/net/UnknownContentHandler.class&lt;br /&gt;/java/nio/Bits.class&lt;br /&gt;/java/nio/Buffer.class&lt;br /&gt;/java/nio/ByteBuffer.class&lt;br /&gt;/java/nio/ByteOrder.class&lt;br /&gt;/java/nio/CharBuffer.class&lt;br /&gt;/java/nio/HeapByteBuffer.class&lt;br /&gt;/java/nio/HeapCharBuffer.class&lt;br /&gt;/java/nio/charset/Charset.class&lt;br /&gt;/java/nio/charset/Charset$3.class&lt;br /&gt;/java/nio/charset/CharsetDecoder.class&lt;br /&gt;/java/nio/charset/CharsetEncoder.class&lt;br /&gt;/java/nio/charset/CoderResult.class&lt;br /&gt;/java/nio/charset/CoderResult$1.class&lt;br /&gt;/java/nio/charset/CoderResult$2.class&lt;br /&gt;/java/nio/charset/CoderResult$Cache.class&lt;br /&gt;/java/nio/charset/CodingErrorAction.class&lt;br /&gt;/java/nio/charset/spi/CharsetProvider.class&lt;br /&gt;/java/security/AccessControlContext.class&lt;br /&gt;/java/security/AccessController.class&lt;br /&gt;/java/security/AllPermission.class&lt;br /&gt;/java/security/BasicPermission.class&lt;br /&gt;/java/security/BasicPermissionCollection.class&lt;br /&gt;/java/security/CodeSource.class&lt;br /&gt;/java/security/Guard.class&lt;br /&gt;/java/security/Permission.class&lt;br /&gt;/java/security/PermissionCollection.class&lt;br /&gt;/java/security/Permissions.class&lt;br /&gt;/java/security/Principal.class&lt;br /&gt;/java/security/PrivilegedAction.class&lt;br /&gt;/java/security/PrivilegedActionException.class&lt;br /&gt;/java/security/PrivilegedExceptionAction.class&lt;br /&gt;/java/security/ProtectionDomain.class&lt;br /&gt;/java/security/SecureClassLoader.class&lt;br /&gt;/java/security/UnresolvedPermission.class&lt;br /&gt;/java/security/cert/Certificate.class&lt;br /&gt;/java/util/AbstractCollection.class&lt;br /&gt;/java/util/AbstractList.class&lt;br /&gt;/java/util/AbstractMap.class&lt;br /&gt;/java/util/AbstractSet.class&lt;br /&gt;/java/util/ArrayList.class&lt;br /&gt;/java/util/BitSet.class&lt;br /&gt;/java/util/Collection.class&lt;br /&gt;/java/util/Collections.class&lt;br /&gt;/java/util/Collections$EmptyList.class&lt;br /&gt;/java/util/Collections$EmptyMap.class&lt;br /&gt;/java/util/Collections$EmptySet.class&lt;br /&gt;/java/util/Collections$ReverseComparator.class&lt;br /&gt;/java/util/Collections$SynchronizedMap.class&lt;br /&gt;/java/util/Comparator.class&lt;br /&gt;/java/util/Dictionary.class&lt;br /&gt;/java/util/Enumeration.class&lt;br /&gt;/java/util/HashMap.class&lt;br /&gt;/java/util/HashMap$Entry.class&lt;br /&gt;/java/util/HashSet.class&lt;br /&gt;/java/util/Hashtable.class&lt;br /&gt;/java/util/Hashtable$EmptyEnumerator.class&lt;br /&gt;/java/util/Hashtable$EmptyIterator.class&lt;br /&gt;/java/util/Hashtable$Entry.class&lt;br /&gt;/java/util/Iterator.class&lt;br /&gt;/java/util/LinkedHashMap.class&lt;br /&gt;/java/util/LinkedHashMap$Entry.class&lt;br /&gt;/java/util/List.class&lt;br /&gt;/java/util/Locale.class&lt;br /&gt;/java/util/Map.class&lt;br /&gt;/java/util/Map$Entry.class&lt;br /&gt;/java/util/Properties.class&lt;br /&gt;/java/util/Random.class&lt;br /&gt;/java/util/RandomAccess.class&lt;br /&gt;/java/util/Set.class&lt;br /&gt;/java/util/SortedMap.class&lt;br /&gt;/java/util/Stack.class&lt;br /&gt;/java/util/StringTokenizer.class&lt;br /&gt;/java/util/TreeMap.class&lt;br /&gt;/java/util/TreeMap$Entry.class&lt;br /&gt;/java/util/Vector.class&lt;br /&gt;/java/util/concurrent/atomic/AtomicLong.class&lt;br /&gt;/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.class&lt;br /&gt;/java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl.class&lt;br /&gt;/java/util/jar/JarEntry.class&lt;br /&gt;/java/util/jar/JarFile.class&lt;br /&gt;/java/util/jar/JarFile$JarFileEntry.class&lt;br /&gt;/java/util/jar/JavaUtilJarAccessImpl.class&lt;br /&gt;/java/util/zip/Inflater.class&lt;br /&gt;/java/util/zip/InflaterInputStream.class&lt;br /&gt;/java/util/zip/ZipConstants.class&lt;br /&gt;/java/util/zip/ZipEntry.class&lt;br /&gt;/java/util/zip/ZipFile.class&lt;br /&gt;/java/util/zip/ZipFile$2.class&lt;br /&gt;/java/util/zip/ZipFile$ZipFileInputStream.class&lt;br /&gt;/sun/io/Converters.class&lt;br /&gt;/sun/misc/ASCIICaseInsensitiveComparator.class&lt;br /&gt;/sun/misc/AtomicLong.class&lt;br /&gt;/sun/misc/AtomicLongCSImpl.class&lt;br /&gt;/sun/misc/ExtensionDependency.class&lt;br /&gt;/sun/misc/FileURLMapper.class&lt;br /&gt;/sun/misc/JarIndex.class&lt;br /&gt;/sun/misc/JavaLangAccess.class&lt;br /&gt;/sun/misc/JavaUtilJarAccess.class&lt;br /&gt;/sun/misc/Launcher.class&lt;br /&gt;/sun/misc/Launcher$AppClassLoader.class&lt;br /&gt;/sun/misc/Launcher$AppClassLoader$1.class&lt;br /&gt;/sun/misc/Launcher$ExtClassLoader.class&lt;br /&gt;/sun/misc/Launcher$ExtClassLoader$1.class&lt;br /&gt;/sun/misc/Launcher$Factory.class&lt;br /&gt;/sun/misc/NativeSignalHandler.class&lt;br /&gt;/sun/misc/Resource.class&lt;br /&gt;/sun/misc/SharedSecrets.class&lt;br /&gt;/sun/misc/Signal.class&lt;br /&gt;/sun/misc/SignalHandler.class&lt;br /&gt;/sun/misc/SoftCache.class&lt;br /&gt;/sun/misc/URLClassPath.class&lt;br /&gt;/sun/misc/URLClassPath$3.class&lt;br /&gt;/sun/misc/URLClassPath$FileLoader.class&lt;br /&gt;/sun/misc/URLClassPath$FileLoader$1.class&lt;br /&gt;/sun/misc/URLClassPath$JarLoader.class&lt;br /&gt;/sun/misc/URLClassPath$Loader.class&lt;br /&gt;/sun/misc/Unsafe.class&lt;br /&gt;/sun/misc/VM.class&lt;br /&gt;/sun/misc/Version.class&lt;br /&gt;/sun/net/www/MessageHeader.class&lt;br /&gt;/sun/net/www/ParseUtil.class&lt;br /&gt;/sun/net/www/URLConnection.class&lt;br /&gt;/sun/net/www/protocol/file/FileURLConnection.class&lt;br /&gt;/sun/net/www/protocol/file/Handler.class&lt;br /&gt;/sun/net/www/protocol/jar/Handler.class&lt;br /&gt;/sun/nio/ByteBuffered.class&lt;br /&gt;/sun/nio/cs/AbstractCharsetProvider.class&lt;br /&gt;/sun/nio/cs/FastCharsetProvider.class&lt;br /&gt;/sun/nio/cs/HistoricallyNamedCharset.class&lt;br /&gt;/sun/nio/cs/MS1252.class&lt;br /&gt;/sun/nio/cs/MS1252$Decoder.class&lt;br /&gt;/sun/nio/cs/MS1252$Encoder.class&lt;br /&gt;/sun/nio/cs/SingleByteDecoder.class&lt;br /&gt;/sun/nio/cs/SingleByteEncoder.class&lt;br /&gt;/sun/nio/cs/StandardCharsets.class&lt;br /&gt;/sun/nio/cs/StandardCharsets$Aliases.class&lt;br /&gt;/sun/nio/cs/StandardCharsets$Cache.class&lt;br /&gt;/sun/nio/cs/StandardCharsets$Classes.class&lt;br /&gt;/sun/nio/cs/StreamEncoder.class&lt;br /&gt;/sun/nio/cs/StreamEncoder$CharsetSE.class&lt;br /&gt;/sun/nio/cs/Surrogate.class&lt;br /&gt;/sun/nio/cs/Surrogate$Parser.class&lt;br /&gt;/sun/nio/cs/ext/ExtendedCharsets.class&lt;br /&gt;/sun/nio/cs/ext/MS874.class&lt;br /&gt;/sun/nio/cs/ext/MS874$Decoder.class&lt;br /&gt;/sun/nio/cs/ext/MS874$Encoder.class&lt;br /&gt;/sun/reflect/ConstantPool.class&lt;br /&gt;/sun/reflect/ConstructorAccessor.class&lt;br /&gt;/sun/reflect/ConstructorAccessorImpl.class&lt;br /&gt;/sun/reflect/DelegatingClassLoader.class&lt;br /&gt;/sun/reflect/DelegatingConstructorAccessorImpl.class&lt;br /&gt;/sun/reflect/LangReflectAccess.class&lt;br /&gt;/sun/reflect/MagicAccessorImpl.class&lt;br /&gt;/sun/reflect/MethodAccessor.class&lt;br /&gt;/sun/reflect/MethodAccessorImpl.class&lt;br /&gt;/sun/reflect/NativeConstructorAccessorImpl.class&lt;br /&gt;/sun/reflect/Reflection.class&lt;br /&gt;/sun/reflect/ReflectionFactory.class&lt;br /&gt;/sun/reflect/ReflectionFactory$1.class&lt;br /&gt;/sun/reflect/ReflectionFactory$GetReflectionFactoryAction.class&lt;br /&gt;/sun/reflect/misc/ReflectUtil.class&lt;br /&gt;/sun/security/action/GetPropertyAction.class&lt;br /&gt;/sun/security/util/Debug.class&lt;br /&gt;/sun/util/PreHashedMap.class&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The following is a command for &lt;a href="http://www.7-zip.org/"&gt;7z&lt;/a&gt; to strip down the rt.jar (from 37,043 Kb to 1,806 Kb).&lt;br /&gt;&lt;p class="code"&gt;7z.exe d -r -x@listfile.txt rt.jar *.class&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;I tested with JRE 1.5_08 on Windows XP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-4765463076453695400?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/4765463076453695400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=4765463076453695400' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4765463076453695400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/4765463076453695400'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/11/minimum-rtjar-for-hello-world.html' title='Minimum &quot;rt.jar&quot; for Hello World'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-114450361976036536</id><published>2006-04-08T20:38:00.000+07:00</published><updated>2006-10-27T02:45:44.925+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Practical AOP #2 - What's done behind-the-scene?</title><content type='html'>I'll show you something that I think it's hard to maintain without AOP.&lt;br /&gt;As in my Practical AOP #1, I mentioned that I have 8 inter-type declarations and 5 pointcuts to make data-binding work in ZK framework.&lt;br /&gt;&lt;br /&gt;The main important thing is that I need one of the ZK base class to implement my Bindable interface. This change can be considered as somekind of the architectural change. Other point is that several UI element classes need to be modified. One of my pointcuts weaves to add the special event trigger to, at least, 9 classes.&lt;br /&gt;&lt;br /&gt;The figure below partially shows the UML-like class diagram for the data-binding aspect.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6699/383/1600/data_binding_1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6699/383/400/data_binding_1.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-114450361976036536?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/114450361976036536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=114450361976036536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114450361976036536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114450361976036536'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/04/practical-aop-2-whats-done-behind.html' title='Practical AOP #2 - What&apos;s done behind-the-scene?'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-114450127933986040</id><published>2006-04-08T20:00:00.000+07:00</published><updated>2006-10-27T02:45:44.857+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>AOP | Modularity ~= Responsibility</title><content type='html'>It's difficult to making change to many opensource projects that their developers are taking full responsibility to their own codes. The process of changing must be done via their process. Many projects use the opensource community to find their bugs rather than feature enhancement becuase the developer still want to control the way the project should be.  This is somewhat to crash the innovations. Someone who has some ideas to completely enhace the original project has to *fork* to the new project. In my opinion, we can use &lt;span style="font-weight:bold;"&gt;AOP&lt;/span&gt; to solve these social phenomena.&lt;br /&gt;&lt;br /&gt;What I've done is in the same way I mentioned above. At the first place, I want to add some new features to ZK. I created some new code and was thinking about sending the patch to ZK developers. But I stopped and thought again. If I send my patches to them, my code may break their code and it's not good for the ZK community.  The development may have to be slow down because something will be patched into the core. So my solution is to convert all my new code into an aspect. Then I'll take all responsibilities to my aspect rather than push it to the ZK core developers. I think this solution could be good when someone wants to contribute a new thing to the core of some &lt;span style="font-weight:bold;"&gt;working&lt;/span&gt; frameworks. That's why the data-binding aspect has been made.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-114450127933986040?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/114450127933986040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=114450127933986040' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114450127933986040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114450127933986040'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/04/aop-modularity-responsibility.html' title='AOP | Modularity ~= Responsibility'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-114444593140136288</id><published>2006-04-08T04:37:00.000+07:00</published><updated>2006-10-27T02:45:44.794+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Practical AOP #1: Data-Binding Aspect for Web UI</title><content type='html'>ZK (&lt;a href="http://zk1.sf.net"&gt;http://zk1.sf.net&lt;/a&gt;) is one of the best XUL tool for Java that I've known. It's a very powerful framework working on server-side to render DHTML with Ajax capability. ZK is heavily based on MVC model, but I personally want to use the .NET-like data-binding feature in this framework.  To avoid making changes direct to the ZK core, which is being maintained by its developers, I use AspectJ (1.5) to create the "data-binding" aspect.  &lt;br /&gt;&lt;br /&gt;However, I firstly started with OO approach in my development process.  After I have some working code, I've tried to refactor the data-binding aspect out of the base code.  During development, I've found that it is difficult to develop aspects without looking to the base source code. Because I need to ensure that my aspect weaves the base code correctly.&lt;br /&gt;&lt;br /&gt;In my data-binding aspect, I have &lt;span style="font-weight:bold;"&gt;5 pointcuts&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;8 inter-type declarations&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Result&lt;/span&gt;&lt;br /&gt;I've finished the first version of zk-databinding aspect outside the ZK team.&lt;br /&gt;With AspectJ 1.5 and Java 5, I can deploy my aspect to a Web container (tested with&lt;br /&gt;Tomcat 5.5.16) and get the data-binding feature transparently.&lt;br /&gt;Not surprisingly, the data-binding aspect works with ZK 1.1 and ZK 1.2 flawlessly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-114444593140136288?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/114444593140136288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=114444593140136288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114444593140136288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114444593140136288'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/04/practical-aop-1-data-binding-aspect.html' title='Practical AOP #1: Data-Binding Aspect for Web UI'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-114236183933027048</id><published>2006-03-15T01:41:00.000+07:00</published><updated>2006-10-27T02:45:44.729+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>Together + NHibernate ~= A Great Duo</title><content type='html'>I just have an opportunity to use Borland Together 2005 for VS.NET. Its LiveSource ?  feature is very cool !!!. So, I’m here to tell my experience.&lt;br /&gt;I’m evaluating a modeling tool for modeling business sytem that will be implemented using NHibernate. This system will contains 70-80 classes (a small-medium system). Someone who visited my website may be wonder why I don’t use ECO III.  The main reason is because ECO III doesn’t work will with MySQL dbms. The other reason is that ECO III uses the unified approach to maintain object id, so the system may have a number of objects no more that 2^31 (please correct me if I’m wrong). However, this limitation is not a problem for a small to medium system. I calculated that the system can run and work well for at least 50 years.  But the problem will occur when there are a lot of transaction per day.  Object ids will be run out, and ECO won’t reuse any deleted id.&lt;br /&gt;&lt;br /&gt;On the other hand, NHibernate is boring because it cannot fully manage bi-directional associations because it isn’t controlled by a state machine, which ECO has. The main advantages of NHibernate are.  1. ) It allows developer to do o/r mapping at low-level, and 2.) NHibernate objects are plain .NET objects (while ECO objects are not, all ECO business entity implements IObject interface).&lt;br /&gt;&lt;br /&gt;I’m evaluating DevExpress XtraGrid for UI layer, it’s amazing control. Not much needed to say. Its databinding ability is extremely cool !!. One problem I encountered for NHibernate with DevExpress and other GUI layer is just we need to implement Equals, ToString, Hash methods for every class. And I’m now ready to by XtraGrid :). FYI, I use ObjectViews to connect NHibernate to XtraGrid instead of ISet, IList or Array.&lt;br /&gt;&lt;br /&gt;Back to Together, it is useful for modeling and it makes me wonder that why Together for VS.NET is faster that Together for Delphi (they should be share the same implementation, shouldn’t they.) Code synchronization is beautiful (v. SP1) I am much faster to model the business entity. AFAIK, Together is one of a few tools that allow designer to put some attributes to the design elements (class, method). I think Rational XDE also have this feature, but didn’t try yet. One feature I don’t see in Together is automatic field encapsulation as property, which is needed by NHibernate. May be I just don’t know how to use it (please tell me if you know).  Other great features of Together are namespace management, and enum and inner class modeling, which may be useful for one who uses NHibernate. Together also provides very flexible refactoring.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-114236183933027048?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/114236183933027048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=114236183933027048' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114236183933027048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/114236183933027048'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/03/together-nhibernate-great-duo.html' title='Together + NHibernate ~= A Great Duo'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-113756289973668249</id><published>2006-01-18T12:37:00.000+07:00</published><updated>2006-10-27T02:45:44.664+07:00</updated><title type='text'>Moved to Manchester</title><content type='html'>Long time no posting.&lt;br /&gt;I'm very busy about moving from Thailand to Manchester, UK.&lt;br /&gt;This is the first day in Manchester that I can online more than 3 hrs :).&lt;br /&gt;I'll study a PhD research program at the University of Manchester for, at least, 3 years.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-113756289973668249?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/113756289973668249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=113756289973668249' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/113756289973668249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/113756289973668249'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2006/01/moved-to-manchester.html' title='Moved to Manchester'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112919861235551273</id><published>2005-10-13T17:12:00.000+07:00</published><updated>2006-10-27T02:45:44.537+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>Sequence = Firebird Generator in NHibernate 1.0</title><content type='html'>Code below shows how to use "sequence" to have an auto-incremental field in NHibernate 1.0 with Firebird.&lt;br /&gt;I use &lt;b&gt;Generator&lt;/b&gt;(Class="sequence") to make a field to be autoinc, and if you want to specify a generator name, you can use a &lt;b&gt;Param&lt;/b&gt;(Name="sequence", Content) attribute.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;namespace TestNHibernate&lt;br /&gt;{&lt;br /&gt;    [Serializable]&lt;br /&gt;    [Class(NameType=typeof(TestClass))]&lt;br /&gt;    public class TestClass {&lt;br /&gt;&lt;br /&gt;      private int _id;&lt;br /&gt;      private string _name;&lt;br /&gt;&lt;br /&gt;      public TestClass() {&lt;br /&gt;      }&lt;br /&gt;      &lt;b&gt;&lt;br /&gt;      [Id(1, Name="Id")]&lt;br /&gt;      [Generator(2, Class="sequence")]&lt;br /&gt;      [Param(3, Name="sequence", Content="TestClass_Id_Gen")]&lt;/b&gt;&lt;br /&gt;      public int Id {&lt;br /&gt;        get{ return _id;}&lt;br /&gt;        set{ _id = value; }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      [Property(Name="Name", Length=10)]&lt;br /&gt;      public string Name {&lt;br /&gt;        get { return _name; }   &lt;br /&gt;        set { _name = value; }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&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/7910126-112919861235551273?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112919861235551273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112919861235551273' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112919861235551273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112919861235551273'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/10/sequence-firebird-generator-in.html' title='Sequence = Firebird Generator in NHibernate 1.0'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112914459133104575</id><published>2005-10-13T02:15:00.000+07:00</published><updated>2006-10-27T02:45:44.464+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>NHibernate 1.0 and Firebird</title><content type='html'>I've some experiences with Hibernate 2.1 but never touch NHibernate.&lt;br /&gt;It's first time I play around NHibernate, just because I want to test it.&lt;br /&gt;I found that NHibernate meets my all criterias (create DDL, gen mapping on the fly, etc.) to enable MDA.&lt;br /&gt;I use mapping attributes from NHibernateContrib to model a domain class (see below).&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;  // new configuration&lt;br /&gt;  Configuration config = new Configuration();&lt;br /&gt;  // set properties&lt;br /&gt;  IDictionary props = new Hashtable();&lt;br /&gt;  props["hibernate.connection.provider"] =&lt;br /&gt;    "NHibernate.Connection.DriverConnectionProvider"; &lt;br /&gt;  props["hibernate.dialect" ] = &lt;br /&gt;    "NHibernate.Dialect.FirebirdDialect"; &lt;br /&gt;  props["hibernate.connection.driver_class"] = &lt;br /&gt;    "NHibernate.Driver.FirebirdDriver" ;&lt;br /&gt;  props["hibernate.connection.connection_string"] = &lt;br /&gt;    "User=SYSDBA;Password=masterkey;" + &lt;br /&gt;    "Database=C:\\workspace\\FirebirdNET\\test.fdb;" +&lt;br /&gt;    "DataSource=;Port=3050;Dialect=3;Charset=NONE;Role=;" + &lt;br /&gt;    "Connection lifetime=0;Connection timeout=15;" + &lt;br /&gt;    "Pooling=True;Packet Size=8192;Server Type=0";&lt;br /&gt;  config.AddProperties(props);&lt;br /&gt;&lt;br /&gt;  // auto-generate Hbm on-the-fly&lt;br /&gt;  using( MemoryStream stream = new MemoryStream() ) {               &lt;br /&gt;    HbmSerializer.Default.Serialize(stream, typeof(TestClass));&lt;br /&gt;    stream.Position = 0;&lt;br /&gt;    config.AddInputStream(stream);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // create database schema&lt;br /&gt;  SchemaExport s = new SchemaExport(config);&lt;br /&gt;  s.Create(true, true);            &lt;br /&gt;&lt;br /&gt;  sf = config.BuildSessionFactory();&lt;br /&gt;&lt;br /&gt;  // create an object, then save  &lt;br /&gt;  using(ISession ss = sf.OpenSession()) {&lt;br /&gt;    ITransaction tx =  ss.BeginTransaction();&lt;br /&gt;    TestClass tc = new TestClass();&lt;br /&gt;    tc.Id = 1;&lt;br /&gt;    ss.Save(tc);&lt;br /&gt;    tx.Commit();&lt;br /&gt;    ss.Close();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // try find the object as IList&lt;br /&gt;  using(ISession ss = sf.OpenSession()) {&lt;br /&gt;    IList a = ss.Find("from TestClass");&lt;br /&gt;    Text = a.Count.ToString();&lt;br /&gt;    ss.Close();&lt;br /&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;A sample domain class:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using NHibernate.Mapping.Attributes;&lt;br /&gt;&lt;br /&gt;namespace TestNHibernate {&lt;br /&gt;&lt;br /&gt;  [Serializable]&lt;br /&gt;  [Class(NameType=typeof(TestClass))]&lt;br /&gt;  public class TestClass {&lt;br /&gt;&lt;br /&gt;  public TestClass() {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private int id;&lt;br /&gt;&lt;br /&gt;  [Id(-2, Name="Id")]&lt;br /&gt;  [Generator(-1, Class="assigned")]&lt;br /&gt;  public int Id {&lt;br /&gt;    get{ return id;}&lt;br /&gt;    set{ id = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&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/7910126-112914459133104575?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112914459133104575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112914459133104575' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112914459133104575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112914459133104575'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/10/nhibernate-10-and-firebird.html' title='NHibernate 1.0 and Firebird'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112803155486253756</id><published>2005-09-30T04:52:00.000+07:00</published><updated>2006-10-27T02:45:44.393+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>ECO objects cannot be serialized !!!</title><content type='html'>I just &lt;b&gt;understand&lt;/b&gt; that why Borland didnot promote enough their use of ECO for Web Services. I also realize that why there are only few discussion about Web Services issue on &lt;a href="http://tinyurl.com/ahwf4"&gt;ECO news group&lt;/a&gt;. It is because we cannot directly use ECO types as WS complex types.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/6699/383/1600/Eco_Serialized.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6699/383/400/Eco_Serialized.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is my simple code:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;[WebMethod]&lt;br /&gt;public SystemUser[] ListAllUsers() {&lt;br /&gt;  SystemUserEA ea = (SystemUserEA)AccessFactory.Create(EcoSpace,&lt;br /&gt;                    typeof(SystemUserEA));&lt;br /&gt;  return ea.FindAll();&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;However, I've already got the idea and trick how to make ECO fully support Web Services :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112803155486253756?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112803155486253756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112803155486253756' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112803155486253756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112803155486253756'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/09/eco-objects-cannot-be-serialized.html' title='ECO objects cannot be serialized !!!'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112774767476059913</id><published>2005-09-26T22:08:00.000+07:00</published><updated>2006-10-27T02:45:44.328+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>Released EcoAccess 1.0 Final</title><content type='html'>I'm pround to present version 1.0 of EcoAccess, a free proxy-based declarative DAO library for Borland ECO.&lt;br /&gt;&lt;br /&gt;I also updated a website to include one more tutorial - &lt;a href="http://www.centillex.com/repository/blog/EcoAccess%20Tutorial%202.pdf"&gt;Query as List&lt;/a&gt;, and a &lt;a href="http://www.centillex.com/repository/blog/Special%20Report%20-%20Line%20of%20Code%20Comparison.pdf"&gt;special report&lt;/a&gt; to show that you can save many line of codes using EcoAccess.&lt;br /&gt;&lt;br /&gt;You can download EcoAccess v.1.0 Final from &lt;a href="http://www.centillex.com/ecoaccess/"&gt;http://www.centillex.com/ecoaccess/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112774767476059913?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112774767476059913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112774767476059913' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112774767476059913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112774767476059913'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/09/released-ecoaccess-10-final.html' title='Released EcoAccess 1.0 Final'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112757408406930630</id><published>2005-09-24T21:49:00.000+07:00</published><updated>2006-10-27T02:45:44.263+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>Considering Briefcase Model for ECO</title><content type='html'>After playing around &lt;a href="http://www.borland.com/us/products/delphi/eco.html"&gt;ECO II&lt;/a&gt;, I found that it is quite difficult to make ECO's elements serialized with BinaryFormatter. So, I looked back to &lt;a href="http://www.martinfowler.com/eaaCatalog/dataTransferObject.html"&gt;DTO pattern&lt;/a&gt;, and tried to make a utility to generate simple DTO for wrapping ECO objects.&lt;br /&gt;&lt;br /&gt;I named this utility ETO - ECO Transfer Object, and I found that it can work correctly to clone my simple ECO object graph. But I hope it to work with more complicated graph.&lt;br /&gt;If anyone'd like to try this utility please contact me.&lt;br /&gt;&lt;br /&gt;Moreover, I also try to make generated ETO objects to be compatible with &lt;a href="http://forge.novell.com/modules/xfmod/project/?cformatter"&gt;CompactFormatter&lt;/a&gt; and hope that it could work on .NET Compact Framework. That's right, I wanna see ECO working on Pocket PC :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112757408406930630?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112757408406930630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112757408406930630' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112757408406930630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112757408406930630'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/09/considering-briefcase-model-for-eco.html' title='Considering Briefcase Model for ECO'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112348670515103090</id><published>2005-08-08T14:38:00.000+07:00</published><updated>2006-10-27T02:45:44.198+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>Eco on Rails</title><content type='html'>I've successfully tested ECO with EcoAccess on MonoRail Web application framework.&lt;br /&gt;It worked great, and I have some codes to show here.&lt;br /&gt;&lt;p class="code"&gt; /// EcoController.cs&lt;br /&gt;using Castle.MonoRail.Framework;&lt;br /&gt;using Centillex.EcoAccess;&lt;br /&gt;using User;&lt;br /&gt;&lt;br /&gt;namespace EcoRailsSample&lt;br /&gt;{&lt;br /&gt;    public class EcoController : SmartDispatcherController {&lt;br /&gt;        &lt;br /&gt;        UserEcoSpace eco = new UserEcoSpace();        &lt;br /&gt;&lt;br /&gt;        public void List() {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Edit(int id) {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void View(int id) {&lt;br /&gt;            if(eco.Active == false) eco.Active = true;&lt;br /&gt;            ISystemUserEA si;&lt;br /&gt;            si = (ISystemUserEA) AccessFactory.Create(eco, typeof(ISystemUserEA));&lt;br /&gt;            PropertyBag["system_user"] = si.FindById(id);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;I set a simple HTML in View.vm (NVelocity template) like this:&lt;br /&gt;&lt;p class="code"&gt; ## View.vm&lt;br /&gt;&amp;lt;h3&amp;gt;System User&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;Name : $system_user.FirstName &amp;lt;br/&amp;gt;&lt;br /&gt;Last Name: $system_user.LastName &amp;lt;br/&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Here is the screenshot of the above codes:&lt;br /&gt;&lt;img src="http://photos1.blogger.com/blogger/6699/383/1600/Eco_on_Rails_1.gif" title="" border="0"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112348670515103090?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112348670515103090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112348670515103090' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112348670515103090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112348670515103090'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/08/eco-on-rails.html' title='Eco on Rails'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112298866286928952</id><published>2005-08-02T20:17:00.000+07:00</published><updated>2006-10-27T02:45:44.135+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>EcoAccess v.1.0 M1 Released</title><content type='html'>EcoAccess is now available to download from Centillex.com&lt;br /&gt;This is very early access version. However, you can use many exciting features of it.&lt;br /&gt;&lt;br /&gt;Please download it from &lt;a href="http://www.centillex.com/downloads.html"&gt;this page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112298866286928952?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112298866286928952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112298866286928952' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112298866286928952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112298866286928952'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/08/ecoaccess-v10-m1-released.html' title='EcoAccess v.1.0 M1 Released'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-112280945199914465</id><published>2005-07-31T18:30:00.000+07:00</published><updated>2006-10-27T02:45:44.018+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ECO'/><title type='text'>EcoAccess: A Declarative DAO for ECO</title><content type='html'>I'd like to introduce my work for &lt;a href="http://www.borland.com/us/products/delphi/eco.html"&gt;Borland ECO&lt;/a&gt;.&lt;br /&gt;It was inspired by many Java projects such as &lt;a href="http://incubator.apache.org/beehive/"&gt;Beehive&lt;/a&gt; and &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;.&lt;br /&gt;This project "EcoAccess" is based on Dynamic Proxy from &lt;a href="http://www.castleproject.org/index.php/DynamicProxy"&gt;Castle&lt;/a&gt; to enable a declarative programming model to Borland ECO.&lt;br /&gt;Obviously, it utilise many ECO services and let you easy to have OCL access methods.&lt;br /&gt;I'd like to thank many articles from ECO section of &lt;a href="http://howtodothings.com/ViewSubCategory.aspx?SubCategory=60"&gt;HowToDoThings.com&lt;/a&gt; that guide me on ECO.&lt;br /&gt;&lt;br /&gt;The most intesting concept I implemented into EcoAccess is that it provides a pure interface programming model like this:&lt;br /&gt;&lt;p class="code"&gt;[AccessEcoSpace(&lt;b&gt;typeof&lt;/b&gt; (UserEcoSpace))]&lt;br /&gt;&lt;b&gt;public interface&lt;/b&gt; ISystemUserDAO {&lt;br /&gt;    &lt;br /&gt;    [Ocl("SystemUser.allInstances-&gt;select(s|s.id = id)-&gt;first")]&lt;br /&gt;    SystemUser FindById(int id);&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;You can read the first tutorial &lt;a href="http://www.centillex.com/repository/blog/EcoAccess%20Tutorial%201.pdf" title="EcoAccess Tutorial 1.pdf"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-112280945199914465?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/112280945199914465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=112280945199914465' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112280945199914465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/112280945199914465'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/07/ecoaccess-declarative-dao-for-eco.html' title='EcoAccess: A Declarative DAO for ECO'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111338962852314390</id><published>2005-04-13T17:51:00.000+07:00</published><updated>2006-10-27T02:45:43.839+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>First get in touch with Comega</title><content type='html'>Test.cw&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt;  class Address {&lt;br /&gt;    struct {&lt;br /&gt;      string text;&lt;br /&gt;    };&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  static void Main() {&lt;br /&gt;    Address a = &amp;lt;Address&amp;gt;&amp;lt;text&amp;gt;test&amp;lt;/text&amp;gt;&amp;lt;/Address&amp;gt;;&lt;br /&gt;    Console.WriteLine("Comega says hello!");&lt;br /&gt;    Console.WriteLine(a.text);&lt;br /&gt;    Console.ReadLine();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The above code results:&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Comega says hello!&lt;br /&gt;test&lt;br /&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-111338962852314390?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111338962852314390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111338962852314390' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111338962852314390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111338962852314390'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/04/first-get-in-touch-with-comega.html' title='First get in touch with Comega'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111216960209773602</id><published>2005-03-30T14:52:00.000+07:00</published><updated>2006-10-27T02:45:43.782+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>@Inherited won't work with Interface (JDK 1.5)</title><content type='html'>In my early code of SQLWarp, I created the annotation &lt;b&gt;ConnectionInfo&lt;/b&gt; to be annotated on an interface, and I need it for an interface, not a class.  &lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;@Retention(RUNTIME)&lt;br /&gt;@Inherited&lt;br /&gt;public @interface ConnectionInfo {&lt;br /&gt;    public String driver();&lt;br /&gt;    public String url();&lt;br /&gt;    public String userID() default "";&lt;br /&gt;    public String password() default "";&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;The JDK doc says that @Inherited won't work with an Interface, so this is my work around to get annotation from the class that implements the interface which is annotated by @ConnectionInfo.&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;ConnectionInfo c = (ConnectionInfo)obj&lt;br /&gt;       .getClass()&lt;br /&gt;       .getInterfaces()[0]&lt;br /&gt;       .getAnnotation(ConnectionInfo.class);&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/7910126-111216960209773602?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111216960209773602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111216960209773602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111216960209773602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111216960209773602'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/inherited-wont-work-with-interface-jdk.html' title='@Inherited won&apos;t work with Interface (JDK 1.5)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111216888671040797</id><published>2005-03-30T14:42:00.000+07:00</published><updated>2006-10-27T02:45:43.726+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Annotion-Based SQL Maps: Part II (JDK 1.5)</title><content type='html'>I show you the code sample from iBatis SQL Maps 2.0 last post.&lt;br /&gt;I continue realizing the idea:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;public interface MyDAO {&lt;br /&gt;&lt;br /&gt;  @Sql(expr="&lt;br /&gt;  &lt;b&gt;SELECT&lt;/b&gt;&lt;br /&gt;  ADR_ID          as id,&lt;br /&gt;  ADR_DESCRIPTION as description,&lt;br /&gt;  ADR_STREET      as street,&lt;br /&gt;  ADR_CITY        as city,&lt;br /&gt;  ADR_PROVINCE    as province,&lt;br /&gt;  ADR_POSTAL_CODE as postalCode&lt;br /&gt;  &lt;b&gt;FROM&lt;/b&gt; ADDRESS&lt;br /&gt;  &lt;b&gt;WHERE&lt;/b&gt; ADR_ID = &lt;u&gt;?value&lt;/u&gt;&lt;br /&gt;  ")&lt;br /&gt;  public Address getAddress(int value);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;Q: We need code genraotor to create a class from the SQL expression.&lt;br /&gt;A: &lt;a href="http://boss.bekk.no/boss/middlegen/"&gt;MiddleGen&lt;/a&gt; could help.&lt;br /&gt;Q: Implement the above method using a proxy class, a runtime class-wrapper.&lt;br /&gt;A: &lt;a href="http://cglib.sf.net/"&gt;CGLIB &lt;/a&gt;or &lt;a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/"&gt;Javassist&lt;/a&gt;.&lt;br /&gt;Q: Need parsing parameters in the SQL expression, and bind to method's parameters.&lt;br /&gt;A: I think this can be done using in-house parser, or hacked from iBatis SQL Maps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-111216888671040797?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111216888671040797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111216888671040797' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111216888671040797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111216888671040797'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/annotion-based-sql-maps-part-ii-jdk-15.html' title='Annotion-Based SQL Maps: Part II (JDK 1.5)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111206918436708640</id><published>2005-03-29T11:03:00.000+07:00</published><updated>2006-10-27T02:45:43.666+07:00</updated><title type='text'>My Draft Notes on Class Versioning, O/R Mapping and Separation of Concerns</title><content type='html'>Review &lt;a href="http://www.comp.lancs.ac.uk/computing/aose/AODatabases.php"&gt;Rashid's works&lt;/a&gt;:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;class Person&lt;2.0&gt; {&lt;br /&gt;  private String firstName;&lt;br /&gt;  private String surName;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Person&lt;1.0&gt; {&lt;br /&gt;  private String firstName;&lt;br /&gt;  private String lastName;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;Next step?&lt;br /&gt;Separate, then later weave.&lt;br /&gt;this means&lt;br /&gt; + We seperate when design --&gt; yield easier design &lt;br /&gt; + We weave when use --&gt; it must be complex enough to serve  all business logics&lt;br /&gt; + Modification to EJB3 should be great (it's same to OODBMS, dont care RDBMS layer)&lt;br /&gt;&lt;br /&gt;Why?&lt;br /&gt; + It's not possible to change all RBMS invesment to OODB&lt;br /&gt; + It seems that implementing virtual databases over the tranditional RDBMs is better&lt;br /&gt; + A virtual database (in my case OR/mapping - Hibernate, Ejb3) can be fully applied with AOSD&lt;br /&gt; + class versioning schema manager (Rashid 2002-2004)&lt;br /&gt; + annotation&lt;br /&gt; + concern&lt;br /&gt; + data alignment concern&lt;br /&gt;&lt;br /&gt;This is an idea for separating Object and Relation concerns:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;// teacher data concern&lt;br /&gt;@Entity("Teacher", "1.0")&lt;br /&gt;class Teacher {&lt;br /&gt;  private int teacherID;&lt;br /&gt;  private String firstName;&lt;br /&gt;  private String lastName;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Entity("Student", "1.0")&lt;br /&gt;class Student {&lt;br /&gt;  private studentID;&lt;br /&gt;  private firstName;&lt;br /&gt;  private lastName;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// separate advisor concern&lt;br /&gt;@Entity("Teacher", "2.0")&lt;br /&gt;class Advisor {&lt;br /&gt;  private List&lt;Advisee&gt; adviseeLists;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// separate advisor concern&lt;br /&gt;@Entity("Student", "2.0")&lt;br /&gt;class Advisee {&lt;br /&gt;  private Advisor advisor;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Teacher t = entityManager.load(Teacher.class, &lt;br /&gt;              new Integer(1));&lt;br /&gt;Advisor a = versioningManager.morph(t, &lt;br /&gt;              Advisor.class);&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;This is a new idea for field substitution&lt;br /&gt;How the developer access this code?&lt;br /&gt;possible answer: IoC?&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;@Version(2.0)&lt;br /&gt;class Student {&lt;br /&gt;  @Substitute(version="1.0", name="lastName") &lt;br /&gt;  private surName;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class StudentDAO {&lt;br /&gt;&lt;br /&gt;  public Student findById(int id) {&lt;br /&gt;    // codes go here ...&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  @Conform("th.ac.sut.ent.Student", "2.0")&lt;br /&gt;  public static void main(String args[]) {&lt;br /&gt;  &lt;br /&gt;    Student s = new StudentDAO().findById(10);&lt;br /&gt;    // not found, throw exception&lt;br /&gt;    System.out.println(s.getLastName()); &lt;br /&gt;    // should be ok&lt;br /&gt;    System.out.println(s.getSurName());  &lt;br /&gt;  }&lt;br /&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/7910126-111206918436708640?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111206918436708640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111206918436708640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111206918436708640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111206918436708640'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/my-draft-notes-on-class-versioning-or.html' title='My Draft Notes on Class Versioning, O/R Mapping and Separation of Concerns'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111198561148493931</id><published>2005-03-28T11:40:00.000+07:00</published><updated>2006-10-27T02:45:43.610+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Idea on Annotaion-based iBATIS SQLMaps (JDK 1.5)</title><content type='html'>This is my proposal for hacking iBATIS SQLMaps to be annotation-based version.&lt;br /&gt;After looking at &lt;a href="http://www.ibatis.com/common/example.html"&gt;the example&lt;/a&gt;, I saw the following code:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;&amp;lt;select &lt;br /&gt;  id="getAddress" parameterClass="int" &lt;br /&gt;  resultClass="examples.domain.Address"&amp;gt;&lt;br /&gt;  select&lt;br /&gt;    ADR_ID           as id,&lt;br /&gt;    ADR_DESCRIPTION  as description,&lt;br /&gt;    ADR_STREET       as street,&lt;br /&gt;    ADR_CITY         as city,&lt;br /&gt;    ADR_PROVINCE     as province,&lt;br /&gt;    ADR_POSTAL_CODE  as postalCode&lt;br /&gt;  from ADDRESS&lt;br /&gt;  where ADR_ID = #value#&lt;br /&gt;&amp;lt;/select&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;can be changed to annotation attaching on a method of a Java interface.&lt;br /&gt;#value# should be able to bind with the parameter, like this:&lt;br /&gt;&lt;p class="code"&gt;&lt;br /&gt;@Sql("select ... ")&lt;br /&gt;public Address getAttress(int value);&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;Proxy-based AOP is enough for this implementation. A proxy class can be geneated at runtime, using the technique I proposed in SQLWarp.&lt;br /&gt;&lt;br /&gt;later...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-111198561148493931?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111198561148493931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111198561148493931' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111198561148493931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111198561148493931'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/idea-on-annotaion-based-ibatis-sqlmaps.html' title='Idea on Annotaion-based iBATIS SQLMaps (JDK 1.5)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111158380800162367</id><published>2005-03-23T20:12:00.000+07:00</published><updated>2006-10-27T02:45:43.496+07:00</updated><title type='text'>Refactored Suranaree.Galvanium (.NET/Java)</title><content type='html'>It is completely my fault trying to integrate some GUI features into my Galvanium framework. Now I refactor all GUI-related features out of the framework, and upgrade its dependencies (IKVM from 0.8 to 0.12, and lastest Hessian 3.0.8).  The new binary will be posted soon. This version will be 1.0 M3.&lt;br /&gt;&lt;b&gt;Features&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At least 250% faster than XML Web Services&lt;/li&gt;&lt;li&gt;Lightweight Protocol based on Hessian&lt;/li&gt;&lt;li&gt;Seamless Integration of J2EE objects and .NET GUI &lt;/li&gt;&lt;li&gt;Direct .NET/Java type mapping&lt;/li&gt;&lt;li&gt;Display/Edit Java objects in Databinding Controls of .NET&lt;/li&gt;&lt;li&gt;Works behind Firewall&lt;/li&gt;&lt;li&gt;Support Mock Object via ClientProxyFactory&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Components&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ClientProxyFactory&lt;/li&gt;&lt;li&gt;BeanDescriptor&lt;/li&gt;&lt;li&gt;BeanCollection&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;with additional 2 samples.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-111158380800162367?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111158380800162367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111158380800162367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111158380800162367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111158380800162367'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/refactored-suranareegalvanium-netjava.html' title='Refactored Suranaree.Galvanium (.NET/Java)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7910126.post-111149290873657037</id><published>2005-03-22T18:54:00.000+07:00</published><updated>2006-10-27T02:45:43.425+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Annotion-Based Embedded SQL (JDK 1.5)</title><content type='html'>I wanna learn how to create and use annotations in JDK 1.5, so I got some idea from &lt;a href="http://voruta.sourceforge.net/"&gt;voruta.sf.net&lt;/a&gt;.  &lt;br /&gt;Voruta is an embedded SQL framework using Javadoc's style annotation. Based on the same idea, but mine is more dirty :), I implement data access framework for embedding SQL statement with JDK 1.5 annotation.  I call it the &lt;a href="http://centillex.com/repository/java/suranaree.sqlwarp-1.0-M1.zip"&gt;SQLWarp&lt;/a&gt;. You can download and try it here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7910126-111149290873657037?l=chanwit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chanwit.blogspot.com/feeds/111149290873657037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7910126&amp;postID=111149290873657037' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111149290873657037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7910126/posts/default/111149290873657037'/><link rel='alternate' type='text/html' href='http://chanwit.blogspot.com/2005/03/annotion-based-embedded-sql-jdk-15.html' title='Annotion-Based Embedded SQL (JDK 1.5)'/><author><name>chanwit</name><uri>http://www.blogger.com/profile/00064240675718056931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7gu9HQYUUjE/SZylbu8k6jI/AAAAAAAAASU/8LrnKrv5Gcs/s1600-R/8521163ddd403e477d514798488c4b6a%3Fs%3D80'/></author><thr:total>0</thr:total></entry></feed>
