Monday, July 16, 2007

Dealing with method missing with Groovy's MetaClass system

One of the new features coming up in Groovy 1.1 to be released later this year is ExpandoMetaClass. Its an elegant API to programatically extend a class' functionality with Groovy's Meta Object Protocol (MOP).

An example of how we take advantage of this is Grails' dynamic finders in GORM. Dynamic finders allow you to do things like Book.findByTitleAndAuthor("It", "Stephen King"). So how are these implemented in Grails?

First we defined an interface that allows the matching of a method signature to a given method pattern. That interface goes something like this:

interface StaticMethodInvocation {
boolean isMethodMatch(String methodName)
Object invoke(Class theClass, String methodName, Object[] args)

The implementation of this interface just uses regular expressions to match the method signature. Simple enough. So how do we use this from the MetaClass itself? Well, this is where the magic of ExpandoMetaClass comes in as it allows us to override a static "invokeMethod" in Groovy:

1 def dynamicMethods = [...]
2 Book.metaClass.'static'.invokeMethod = { String methodName, args ->
3 def metaMethod = Book.metaClass.getStaticMetaMethod(methodName, args)
4 def result
5 if(metaMethod) {
6 result = metaMethod.invoke(dc.clazz, args)
7 }
8 else {
9 StaticMethodInvocation method =
10 dynamicMethods.find { it.isMethodMatch(methodName) }
11 if(method) {
12 Book.metaClass.'static'."$methodName" = { Object[] varArgs ->
13 method.invoke(Book.class, methodName, varArgs)
14 }
15 result = method.invoke(Book.class, methodName, args)
16 }
17 else {
18 throw new MissingMethodException(methodName, Book.class, args)
19 }
20 }
21 result
22 }

So what is actually happening here? First we look to see if the method already exists
on the line:

3 def metaMethod = Book.metaClass.getStaticMetaMethod(methodName, args)

If it does we simply invoke the method:

6 result = metaMethod.invoke(dc.clazz, args)

Otherwise we attempt to find a method that matches the method signature using a previously defined list of StaticMethodInvocation instances:

9 StaticMethodInvocation method =
10 dynamicMethods.find { it.isMethodMatch(methodName) }

If the method exists we dynamically register a new method on the MetaClass so that the next time the method is invoked it doesn't have to go through the matching process and will simply dispatch like normal:

12 Book.metaClass.'static'."$methodName" = { Object[] varArgs ->
13 method.invoke(dc.clazz, methodName, varArgs)
14 }

Finally, we invoke the method itself, or if the method isn't matched we throw a MethodMissingException:

15 result = method.invoke(dc.clazz, methodName, args)

Job done. As simple as that ;-)

I'm doing a talk at the Grails eXchange about the Grails plug-in system and how we dynamically extend the behaviour of classes. See you there!


Kiran said...

Would be interesting to know how Dynamically methods could be added to Grails Domain classes

derfefww said...

It is the Archlord gold which make me very happy these days, my brother says Archlord money is his favorite games gold he likes, he usually buy some archlord online Gold to start his game and most of the time he will win the buy Archlord gold back and give me some cheap Archlord gold to play the game.

Anonymous said...




Anonymous said...

I do not know why I was very like to play the EVE, so I need eve isk and the eve gold, do you know the eve online isk.

cheap wow power leveling said...

Buy Warcraft(wow power leveling)please point machine (wow power leveling)to enter the website(wow power leveling)of Warcraft

Anonymous said...

^^ nice blog!! ^@^

徵信, 徵信網, 徵信社, 徵信社, 感情挽回, 婚姻挽回, 挽回婚姻, 挽回感情, 徵信, 徵信社, 徵信, 徵信, 捉姦, 徵信公司, 通姦, 通姦罪, 抓姦, 抓猴, 捉猴, 捉姦, 監聽, 調查跟蹤, 反跟蹤, 外遇問題, 徵信, 捉姦, 女人徵信, 女子徵信, 外遇問題, 女子徵信, 外遇, 徵信公司, 徵信網, 外遇蒐證, 抓姦, 抓猴, 捉猴, 調查跟蹤, 反跟蹤, 感情挽回, 挽回感情, 婚姻挽回, 挽回婚姻, 外遇沖開, 抓姦, 女子徵信, 外遇蒐證, 外遇, 通姦, 通姦罪, 贍養費, 徵信, 徵信社, 抓姦, 徵信, 徵信公司, 徵信社, 徵信公司, 徵信社, 徵信公司, 女人徵信,

徵信, 徵信網, 徵信社, 徵信網, 外遇, 徵信, 徵信社, 抓姦, 徵信, 女人徵信, 徵信社, 女人徵信社, 外遇, 抓姦, 徵信公司, 徵信社, 徵信社, 徵信社, 徵信社, 徵信社, 女人徵信社, 徵信社, 徵信, 徵信社, 徵信, 女子徵信社, 女子徵信社, 女子徵信社, 女子徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信社,

徵信, 徵信社,徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 外遇, 抓姦, 離婚, 外遇,離婚,

徵信社,徵信, 徵信社, 徵信, 徵信社, 徵信,徵信社, 徵信社, 徵信, 外遇, 抓姦, 徵信, 徵信社, 徵信, 徵信社, 徵信, 徵信社, 徵信社, 徵信社, 徵信社,徵信,徵信, 徵信, 外遇, 抓姦

cvxv said...

看房子,買房子,建商自售,自售,台北新成屋,台北豪宅,新成屋,豪宅,美髮儀器,美髮,儀器,髮型,EMBA,MBA,學位,EMBA,專業認證,認證課程,博士學位,DBA,PHD,在職進修,碩士學位,推廣教育,DBA,進修課程,碩士學位,網路廣告,關鍵字廣告,關鍵字,課程介紹,學分班,文憑,牛樟芝,段木,牛樟菇,日式料理, 台北居酒屋,日本料理,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,台北結婚,場地,住宿,訂房,HOTEL,飯店,造型系列,學位,SEO,婚宴,捷運,學區,美髮,儀器,髮型,看房子,買房子,建商自售,自售,房子,捷運,學區,台北新成屋,台北豪宅,新成屋,豪宅,學位,碩士學位,進修,在職進修, 課程,教育,學位,證照,mba,文憑,學分班,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北結婚,場地,結婚,場地,推車飲茶,港式點心,尾牙春酒,台北結婚,婚宴場地,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北結婚,場地,居酒屋,燒烤,美髮,儀器,髮型,美髮,儀器,髮型,美髮,儀器,髮型,美髮,儀器,髮型,小套房,小套房,進修,在職進修,留學,證照,MBA,EMBA,留學,MBA,EMBA,留學,進修,在職進修,牛樟芝,段木,牛樟菇,關鍵字排名,網路行銷,PMP,在職專班,研究所在職專班,碩士在職專班,PMP,證照,在職專班,研究所在職專班,碩士在職專班,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,EMBA,MBA,PMP
,在職進修,專案管理,出國留學,EMBA,MBA,PMP,在職進修,專案管理,出國留學,婚宴,婚宴,婚宴,婚宴,漢高資訊,漢高資訊,比利時,比利時聯合商學院,宜蘭民宿,台東民宿,澎湖民宿,墾丁民宿,花蓮民宿,SEO,找工作,汽車旅館,阿里山,日月潭,阿里山民宿,東森購物,momo購物台,pc home購物,購物