Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Group info
Recent pages and files
Metaprogramming in Groovy Pecha Kucha    

Welcome to the Metaprogramming in Groovy Pecha Kucha. It's only six minutes of your life, you might as well watch it:


Click Here to View the Presentation
(sorry, Google Groups won't let us embed YouTube videos)


Thanks to everyone that worked to make this happen:

Mike Calvo         Hamlet D'Arcy
Robert Fischer Mike Hugo
Brian Michelich Jesse O'Neill-Oine
Peter Pascale Paul Wiedel
Justin Grammens

Source video and audio are version controlled at: http://www.assembla.com/wiki/show/metaprogramming_groovy_pk


Here is the text and audio from the slides:

Slide Audio Slide Content
1 Intro

Welcome to metaprogramming in groovy. We're going to explain what meta programming is and walk you through 4 different metaprogramming techniques available in the Groovy.

Many Groovy users first see metaprogramming in the Grails GORM framework or various Groovy DSLs. This presentation explains how frameworks like this work and help you make your own.

Anyone familar with java-like syntax should have no trouble following along.

Metaprogramming in Groovy

* Quick Explanation
* 4 Techniques
* No Groovy Experience Required
2 Intro to Metaprogramming
There is a folk tale of a computer science student caught talking in class. As punishment, the professor made her write a program that prints out "I will not talk in class" 1000 times, along with the line number. The catch was that she wasn't allowed to use iteration, recursion, gotos and any looping.

The solution to this, of course, is to write a program that prints out the source code the professor is asking for.
1. I will not talk in class
2. I will not talk in class
...
999. I will not talk in class
1000. I will not talk in class
3 Intro to Metaprogramming
Writing a program that writes another program is an essential part of metaprogramming. This comes in many forms.

Simple code generators are one form of metaprogramming. Generating XML Bean bindings is a common practice from the Java world.

Monkey patching is another popular form of metaprogramming. This is the act of opening classes at runtime to add behavior without altering the original source code.
(1..1000).each {
println ("println $it. I will not talk in class.")
}
4
Examples of Metaprogramming
Many languages support compile time metaprogramming.. The C Preprocessor, Lisp Macros, and C++ Templates are all examples. These features are used to manipulate behavior and syntax of the computer program before it is compiled.

Groovy supports extensive runtime metaprogramming, which is what our concern is today.
#define MIN(x, y) ((x) > (y) ? (y) : (x))


(defmacro Square (X)
'(* ,X ,X))
5 String Evalutation I
Groovy contains the ability to treat data like code and execute data at runtime.

Both these examples show a string being evaluated at runtime, returning an Integer.

Where do the strings come from? A file, or user input, or maybe Groovy source on disk?
new GroovyShell().evaluate("2+4")

def input = new Binding([a: 2, b: 4])
new GroovyShell(input).evaluate("a + b")



6 String Evalutation II
Why would you do this?

It's an alternative to futzing with classloaders to get a class dynamically loaded, like in Java.

Writing DSLs is another reason. Exposing code snippets in config files allows you to create a program at a higher level of abstraction than the groovy syntax level. Groovy's flexible syntax means code exposed in a file doesn't even have to look like groovy
orderPizza.dsl
--------------
size large
crust thin
toppings Olives, Onions, Bell_Pepper
address "101 Main St.,, ..."
card visa, '1234-1234-1234-1234'

(from Programming Groovy)
7 ExpandoMetaClass I
Moving on... Sometimes the core JDK classes don't contain all the methods you need. Perhaps your project has a StringUtils class that allows you to sanitize input Or maybe a DateUtils that can add days to a date. Wouldn't it be nice if you could dynamically add a method to, say, Integer or String?
"Robert'); DROP TABLE Students;--".sanitize()

3.days.after.today
8 ExpandoMetaClass II
ExpandoMetaClass to the rescue. This allows you to dynamically add methods, constructors, and properties to existing classes.

Every class in Groovy, including Java classes, has a meta class. When a method is invoked on a class, the call is first dispatched to the metaclass. If the method doesn't exist there, then the method on the class is invoked.
[process diagram showing method dispatch]
9 ExpandoMetaClass III
This is a great way to add convenience methods to existing classes.

This example creates a capitalize method on String by assigning a closure to the metaclass. The target of the method call is available in the closure as the delegate object. In the hello example, the delegate is the uncapitalized "hello" string.
String.metaClass.capitalize = {
  if (!delegate) return delegate;
   delegate.substring(0, 1).toUpperCase() +
   delegate.substring(1).toLowerCase();
}

assert "Hello" == "hello".capitalize()
10 ExpandoMetaClass IV
A common usage is in unit testing with mock objects.

Grails controllers are seen as difficult to mock out because so many methods on them are supplied at runtime by the framework itself. An easy way to mock out Grails controllers is to add log() and request() methods to the ExpandoMetaClass of the class under test.
MyController.metaClass.request = {
...
}

MyController.metaClass.log = {
...
}
11 invokeMethod I
Sometimes you don't know what methods will be called on your object until runtime. Typically, calling a non-existent method results in a MethodMissing exception.

But many objects in Groovy respond to method calls that aren't defined in source code. Building XML dynamically is a prime example.

new XmlBuilder()
.root() {
Groovy()
Users()
of()
Minnesota()
}
12 invokeMethod II
Generating XML based on the previous example can be accomplished by overridding a single method call: invokeMethod.

invokeMethod is called on almost every method invocation. You can provide dynamic methods by intercepting the method name and parameters from within it


class XmlBuilder {
  def invokeMethod(String name, args) {
     println "<$name>"
     if((args) && (args[0] instanceof Closure)) {
       args[0].delegate = this
        args[0].call()
     }else if (args) {
       println args[0].toString()
     }
    println "</$name>"
   }
}
13 invokeMethod III
invokeMethod can also be used to wrap existing methods before invocation. Aspect Oriented Around advice for logging is implemented here in 4 lines of code:
Override invokeMethod, log a message, invoke the original target, and log a message at completion. No extra libraries or instrumentation needed!

class Wrapper implements GroovyInterceptable {
  def foo() {
    System.out.println "foo invoked"
   }
   def invokeMethod(String name, args) {
     System.out.println ("Beginning $name")
     Wrapper.metaClass.getMetaMethod(name, args).invoke(this, args)
    System.out.println ("Completed $name")
   }
}
14 InvokeMethod IV
invokeMethod is a great aid for writing builders, validating parameters, logging, data massaging, and DSLs.

A lot of dynamic flexibility comes with the ability to intercept every method call at runtime. However, this advantage is also its weakness. A lot of overhead comes with intercepting every method call at runtime.
Pros: invokeMethod called for every invocation

Cons: invokeMethod called for every invocation
15 MethodMissing I
Normally, when a missing method or property is called, Groovy will throw a MissingProperty or MissingMethod Exception.

But if you override a method called MethodMissing, then Groovy is going to invoke that method before throwing an exception. Using this, you can intercept only those method calls that don't exist on your class.
new String().foo

Exception thrown: groovy.lang.MissingPropertyException: No such property: foo for class: java.lang.String
16 MethodMissing II
The methodMissing concept was invented for Smalltalk in the 80s.

By using it you avoid the overhead of invokeMethod and add runtime functionality lazily.

These examples are simply doing printlines for any method or property invocation that can't be found.
class Catcher {
  def methodMissing(String name, args) {
  println "$name called"
 }

def propertyMissing(String name, args) {
  println "$name accessed"
}
}
17 MethodMissing III
This is how Grail's GORM works.

At design time, your domain object (a book perhaps) will have the property title defined. But there is no definition of a findByTitle method. Instead, it is synthesized at runtime using methodMissing.

The method parses "findByTitle" and calls the database with the data encoded in your method name.
def book = Book.findByTitle("Groovy in Action")
18 MethodMissing IV
The significant overhead of methodMissing led the Grails team to invent a pattern called "InterceptCacheInvoke".

When methodMissing is called the first time you create a new method to invoke. Then add that method to the metaclass, so future invocations will dispatch directly to the metaclass. Finally, you invoke the method you created.
class Catcher {
  def methodMissing(String name, args) {
    def method = { println "$name called" }
    Catcher.metaClass."$name" = method
    return method(args)
  }
}
19 And that's it... you've seen four different metaprogramming techniques in Groovy:

We've evalutated Strings as code,
We've added methods and properties with ExpanoMetaclass,
We've synthesize methods at runtime with invokeMethod,
and we've optimized dynamic methods using methodMissing and interceptcacheinvoke.
shell.evaluate("2+4")

String.metaClass.capitalize = { ...

def invokeMethod(String name, args) { ...

def methodMissing(String name, args) { ...
20 This pecha kucha was created by the Groovy Users of Minnesota, meeting the first first Tuesday of the month in Minneapolis to discuss and learn about Groovy and Grails. Visit our website at www.groovy.mn and, if you're in the area, please stop by and say hi.

Thanks for listening!
Groovy Users of Minnesota
http://groovy.mn

Mike Calvo Hamlet D'Arcy
Robert Fischer Mike Hugo
Brian Michelich Jesse O'Neill-Oine
Peter Pascale Paul Wiedel
Justin Grammens
Version: 
Latest 3 messages about this page (12 total) - view full discussion
Jul 27 2008 by Colin Harrington
Good work!!
http://www.youtube.com/watch?v=Qr4PcOQYFAw
~ Colin Harrington
Jul 25 2008 by staticnullv...@gmail.com
This turned out really well. Kudos to everyone involved.

- Eric Kinsella
Jul 24 2008 by Hamlet D'Arcy
And the DZone link is here:
http://www.dzone.com/links/metaprogramming_in_groovy_pecha_kucha.html

Clicking the Up arrow at the link will help it rise in popularity.
9 more messages »
Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google