2.25.2008
Creating a Simple Builder with Groovy's methodMissing()
Creating a Simple Builder with Groovy's methodMissing()
One of the main theme here at Groovy/Grails Experience is Meta Programming: the ability to use Groovy to dynamically modify the behavior of the language at runtime. During one of Graeme Rocher's session, he did a live demo on how to build a simple Xml builder and Vankat Subramaniam demo'ed the creation of a simple DSL using Groovy. These sessions showed the simplicity and power of Meta programming in Groovy. So, rather than go on and praise the merits of Groovy and make this an all fluff write up (and get crap for it from my buddy James Williams ), I will show a concrete example below.
A Simple Xml Builder in Groovy
This simple xml builder is able to handle most xml tag constructs including:
So, here is a sample usage of the SimpleXmlBuilder class to build XML nodes:
The code snippet above will generate this HTML code:
The Code
Disclaimer: this was put together in less an hour while sitting in a session at the G2 Experience. I am sure it can be done in a more elegant way. The code simply evaluates each of the syntatic possiblities (discussed above) and take appropritae action. So, with that out of the way, here is the code for simple xml builder:
Click to download the Groovy source code.
MOP - methodMissing()
If you are new to Groovy then you may not understand what's going on. Groovy's meta object protocol (MOP) lets developers expand the syntactical constraints of the core language at runtime. This capability makes Groovy the perfect platform to create Domain Specific Language (DSL) where you develop small language with a concise syntax to address a given domain (software dev, business, etc). The methodMissing() method is one of the hooks exposed by Groovy's MOP mechanism that intercepts all calls to undefined methods on a given object. By overriding methodMissing(), you can implement behaviors of methods that are not statically defined on the class.
When Groovy's MOP intercepts an method call, it invokes methodMissing(String methodName, args) with two parameters: the name of the missing method that was invoked and an array representing the method's parameters. So, for instance, when Groovy intercepts xml.title("Hello"), the first parameter of methodMissing() has a value of "title" and args.length = 1 where arg[0] = "Hello".
When the syntax is as follows, xml.header {...}, methodMissing's method name has a value of "header". Here, however, args[0] is a closure. A closure is an executable (callable) code block that can be treated as a variable. As such, we must tell Groovy that we want to execute that code block. However, before we blindly call the closure, we reassign the closure's target to be the SimpleXmlBuilder class (args[0].delegate = this line 11 and 49). Therefore, the next method dispatch request on the closure will be handled by the SimpleXmlBuilder.
Finally, when the syntax of our builder takes the form of xml.html(xmlns:"http;//somenamespace"){ ... }, Groovy's MOP invokes methodMissing where the method name is "html" as expected. In this case, however, argument array has two memebers: the first one is a map and the second member is another closure. Knowing this, we can handle tags with both attributes and function as a container tag as shown above (starting with line 37).
Conclusion
This sample code above demonstrates how Groovy's MOP mechanism can let developers change and extend the language's syntactical behavior to build functional DSL that fit specific needs. Here, in about 30 lines of code, we created a simple XML builder which is able to output well-formed xml document. This is a simple example and shows just a small glimpse of the capabilities of Groovy's meta programming. I hope this inspires you to continue to explore Groovy and come up with your own use for MOP.
References
0. Download Groovy source file - http://vmatters.googlepages.com/SimpleBuilderDemo.groovy
1. Dynamic Groovy - http://groovy.codehaus.org/Dynamic+Groovy
2. Using methodMissing and propertyMissing - http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
3. Meta Programming with Groovy Part 1 - http://groovy.dzone.com/articles/metaprogramming-groovy-i
4. Meta Programming with Groovy Part 2 - http://groovy.dzone.com/articles/metaprogramming-groovy-ii-expa
5. Google Doc version of this write up - http://docs.google.com/Doc?id=df3qdpw5_53chtkh89r
One of the main theme here at Groovy/Grails Experience is Meta Programming: the ability to use Groovy to dynamically modify the behavior of the language at runtime. During one of Graeme Rocher's session, he did a live demo on how to build a simple Xml builder and Vankat Subramaniam demo'ed the creation of a simple DSL using Groovy. These sessions showed the simplicity and power of Meta programming in Groovy. So, rather than go on and praise the merits of Groovy and make this an all fluff write up (and get crap for it from my buddy James Williams ), I will show a concrete example below.
A Simple Xml Builder in Groovy
This simple xml builder is able to handle most xml tag constructs including:
- <tag/>
- <tag atrrib="val"/>
- <tag>String content</tag>
- <tag attrib="val">content</tag>
- <tag attrib="val"><tag>... tag[n] ...</tag></tag>
So, here is a sample usage of the SimpleXmlBuilder class to build XML nodes:
| <html xmlns="htt://namespace" ><header><title>Hello</title></header><body><p>Hello World Sample</p><span id="greet" style="font-family:sans-serif" >Hello World!!</span></body></html> |
The Code
Disclaimer: this was put together in less an hour while sitting in a session at the G2 Experience. I am sure it can be done in a more elegant way. The code simply evaluates each of the syntatic possiblities (discussed above) and take appropritae action. So, with that out of the way, here is the code for simple xml builder:
MOP - methodMissing()
If you are new to Groovy then you may not understand what's going on. Groovy's meta object protocol (MOP) lets developers expand the syntactical constraints of the core language at runtime. This capability makes Groovy the perfect platform to create Domain Specific Language (DSL) where you develop small language with a concise syntax to address a given domain (software dev, business, etc). The methodMissing() method is one of the hooks exposed by Groovy's MOP mechanism that intercepts all calls to undefined methods on a given object. By overriding methodMissing(), you can implement behaviors of methods that are not statically defined on the class.
When Groovy's MOP intercepts an method call, it invokes methodMissing(String methodName, args) with two parameters: the name of the missing method that was invoked and an array representing the method's parameters. So, for instance, when Groovy intercepts xml.title("Hello"), the first parameter of methodMissing() has a value of "title" and args.length = 1 where arg[0] = "Hello".
When the syntax is as follows, xml.header {...}, methodMissing's method name has a value of "header". Here, however, args[0] is a closure. A closure is an executable (callable) code block that can be treated as a variable. As such, we must tell Groovy that we want to execute that code block. However, before we blindly call the closure, we reassign the closure's target to be the SimpleXmlBuilder class (args[0].delegate = this line 11 and 49). Therefore, the next method dispatch request on the closure will be handled by the SimpleXmlBuilder.
Finally, when the syntax of our builder takes the form of xml.html(xmlns:"http;//somenamespace"){ ... }, Groovy's MOP invokes methodMissing where the method name is "html" as expected. In this case, however, argument array has two memebers: the first one is a map and the second member is another closure. Knowing this, we can handle tags with both attributes and function as a container tag as shown above (starting with line 37).
Conclusion
This sample code above demonstrates how Groovy's MOP mechanism can let developers change and extend the language's syntactical behavior to build functional DSL that fit specific needs. Here, in about 30 lines of code, we created a simple XML builder which is able to output well-formed xml document. This is a simple example and shows just a small glimpse of the capabilities of Groovy's meta programming. I hope this inspires you to continue to explore Groovy and come up with your own use for MOP.
References
0. Download Groovy source file - http://vmatters.googlepages.com/SimpleBuilderDemo.groovy
1. Dynamic Groovy - http://groovy.codehaus.org/Dynamic+Groovy
2. Using methodMissing and propertyMissing - http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
3. Meta Programming with Groovy Part 1 - http://groovy.dzone.com/articles/metaprogramming-groovy-i
4. Meta Programming with Groovy Part 2 - http://groovy.dzone.com/articles/metaprogramming-groovy-ii-expa
5. Google Doc version of this write up - http://docs.google.com/Doc?id=df3qdpw5_53chtkh89r
Labels: Dyanic Languages, Grails, Groov
2.05.2008
Integrating Groovy Classes in Spring
Spring Meets Groovy!
[View in Google Doc: http://docs.google.com/Doc?id=df3qdpw5_51fqxz7cft ]
If you don't use Spring or care to know about it, then this write up is not for you. I will look at how your Java-based Spring component can made Groovier!! Again, as a pre-requisite, you must already be using Spring (2.0 or better) and have a working knowledge of Groovy.
Why Groovy and Spring?
After more than ten years of Java, we can all agree that one language does not fit all. We (collective Java community) have been banging square pegs into round holes (with patterns, anti-patterns, best practices, frameworks as lubricant). With the advent of dynamic languages such Groovy and Ruby in the enterprise, we are realizing that it is time to start building polyglot systems. Poly-who, you ask?? A system that is made up of one or more languages. Each language addresses a specific domain (i.e. structural, configuration, business, ui, etc) so that your pegs fit where they should. We are already do this today when we write our views in JSP's, controllers in Java, retrieve data using SQL, and configure our apps using XML.
Groovy in Spring Example
Wiring Groovy beans in Spring is easy and require little deviation from what you already know. You can create your beans following these steps
1. Create a Java Interface
Currently, Groovy beans in Spring must implement an Java-defined interface so that Spring can get type information about your Groovy beans. So, let's create a Payment interface:
2. Implement in Groovy
Create a Groovy class that implements the interface. Place your Groovy file somewhere on the classpath. In this example, the file is placed in groovy/CreditCardPayment.groovy. Your Groovy class has access to any classes on the classpath as well, so you can reference other Java classes or other Groovy classes. The class has two properties (mechantId and serviceUrl) which can be injected at runtime by Spring (see below).
3. Wire in Spring
The first thing to notice is the XML schema declaration. It makes reference to the XML lang namespace and the lang XSD. This allows you to use the specially provided <lang:groovy/> tag. The tag lets you wire in Groovy beans and inject property values into them. Here, we are injecting mechantId and serviceURL with values just as we do regular Java POJO's.
Run the Example
Here, we have a Java class that runs the example. However, you can imagine this setup working in other context such as a web application, a standalone process, or any other context where Spring can live. Note in the code that once the Groovy bean is retrieved from the Spring context, it is used as a regular Java class.
You should see the followings on the screen:
So What?
You may be saying "Why should I care? I can do the same thing in Java!" You would be correct. This is not meant to supplant Java but rather complement it. Integrating a dynamic language such as Groovy into your enterprise development gives you a new level of flexibility and configurability that was not there before (or at least requires additional steps to work smoothly). You can use this approach in several scenarios
- Configuration: Use Groovy beans to capture configuration rules for your system or for your business logic including page flow, process flow, etc.
- Business Rules: some business logic tend to change. You can use Groovy to
- Handle Event: Use Groovy to react to system or application events (i.e. if inventory falls below a level, send email. This works well in conjunction with JMX)
- Validation: validation rules is another context susceptible to changes. Capturing your validation in Groovy lets you adjust to your business needs.
- Expose Edge Services: these are the services that expose functionalities at the boundaries of your system (i.e. MVC controllers, web services, REST services, etc). See project Grails .
Conclusion
We looked at how Groovy can be integrated in your application using Spring. Groovy is a natural choice for Polyglot programming on the Java VM given its flexibility and growing popularity. This write up shows a small instance how Groovy can be integrated into your system using the Spring Framework. Groovy can be injected in your enterprise stack to handle the more fluid context where logic tends to be updated to keep up with business requirements.
References
0. Google Doc for write up - http://docs.google.com/Doc?id=df3qdpw5_51fqxz7cft
1. Spring Dynamic Language Support - http://static.springframework.org/spring/docs/2.5.x/reference/dynamic-language.html
2. Ola Bimi - Language Exploration (blog) - http://ola-bini.blogspot.com/2008/01/language-explorations.html
3. Neal Ford - Polygot Programming (blog) - http://memeagora.blogspot.com/2008/01/polyglot-programming-parallels-perched.html
3. Grok - Polyglot Programming (blog) - http://www.grok-programming.com/2007/11/25/polyglot-programming-is-it-just-too-much-to-ask/
[View in Google Doc: http://docs.google.com/Doc?id=df3qdpw5_51fqxz7cft ]
If you don't use Spring or care to know about it, then this write up is not for you. I will look at how your Java-based Spring component can made Groovier!! Again, as a pre-requisite, you must already be using Spring (2.0 or better) and have a working knowledge of Groovy.
Why Groovy and Spring?
After more than ten years of Java, we can all agree that one language does not fit all. We (collective Java community) have been banging square pegs into round holes (with patterns, anti-patterns, best practices, frameworks as lubricant). With the advent of dynamic languages such Groovy and Ruby in the enterprise, we are realizing that it is time to start building polyglot systems. Poly-who, you ask?? A system that is made up of one or more languages. Each language addresses a specific domain (i.e. structural, configuration, business, ui, etc) so that your pegs fit where they should. We are already do this today when we write our views in JSP's, controllers in Java, retrieve data using SQL, and configure our apps using XML.
Groovy in Spring Example
Wiring Groovy beans in Spring is easy and require little deviation from what you already know. You can create your beans following these steps
1. Create a Java Interface
Currently, Groovy beans in Spring must implement an Java-defined interface so that Spring can get type information about your Groovy beans. So, let's create a Payment interface:
| package demo.vladimirvivien; import java.util.HashMap; public interface Payment { void pay(HashMap info); } |
2. Implement in Groovy
Create a Groovy class that implements the interface. Place your Groovy file somewhere on the classpath. In this example, the file is placed in groovy/CreditCardPayment.groovy. Your Groovy class has access to any classes on the classpath as well, so you can reference other Java classes or other Groovy classes. The class has two properties (mechantId and serviceUrl) which can be injected at runtime by Spring (see below).
| import demo.vladimirvivien.Payment import java.lang.Util.* import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; class CreditCardPayment implements Payment { static Log log = LogFactory.getLog(Payment.class) String merchantId; String serviceUrl; void pay(HashMap info) { log.info("Processing Payment...") println "---------------------------" println "Merchant ID:t${merchantId}" println "Service URL:t${serviceUrl}" println "Payer:nt${info.PAYER_NAME}nt${info.PAYER_ADDR}ntCard:${info.PAYER_CCNUM} Exp:${info.PAYER_CCEXP}" // process payment here } } |
3. Wire in Spring
The first thing to notice is the XML schema declaration. It makes reference to the XML lang namespace and the lang XSD. This allows you to use the specially provided <lang:groovy/> tag. The tag lets you wire in Groovy beans and inject property values into them. Here, we are injecting mechantId and serviceURL with values just as we do regular Java POJO's.
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd"> <lang:groovy id="payManager" script-source="classpath:groovy/CreditCardPayment.groovy"> <lang:property name="merchantId" value="ID343432-4434-34" /> <lang:property name="serviceUrl" value="http://paymentservice/processor.do" /> </lang:groovy> </beans> |
Run the Example
Here, we have a Java class that runs the example. However, you can imagine this setup working in other context such as a web application, a standalone process, or any other context where Spring can live. Note in the code that once the Groovy bean is retrieved from the Spring context, it is used as a regular Java class.
| package demo.vladimirvivien; import java.util.HashMap; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("META-INF/spring-context.xml"); // pull an instance of the Groovy Payment bean Payment payment = (Payment) ctx.getBean("payManager"); HashMap<String,String> info = new HashMap<String,String>(); info.put("PAYER_NAME", "John Foo"); info.put("PAYER_ADDR", "12345 Main Street, USA"); info.put("PAYER_CCNUM", "1234564343343"); info.put("PAYER_CCEXP", "0910"); // call the implemented mehod pay() payment.pay(info); } } |
You should see the followings on the screen:
| |
So What?
You may be saying "Why should I care? I can do the same thing in Java!" You would be correct. This is not meant to supplant Java but rather complement it. Integrating a dynamic language such as Groovy into your enterprise development gives you a new level of flexibility and configurability that was not there before (or at least requires additional steps to work smoothly). You can use this approach in several scenarios
- Configuration: Use Groovy beans to capture configuration rules for your system or for your business logic including page flow, process flow, etc.
- Business Rules: some business logic tend to change. You can use Groovy to
- Handle Event: Use Groovy to react to system or application events (i.e. if inventory falls below a level, send email. This works well in conjunction with JMX)
- Validation: validation rules is another context susceptible to changes. Capturing your validation in Groovy lets you adjust to your business needs.
- Expose Edge Services: these are the services that expose functionalities at the boundaries of your system (i.e. MVC controllers, web services, REST services, etc). See project Grails .
Conclusion
We looked at how Groovy can be integrated in your application using Spring. Groovy is a natural choice for Polyglot programming on the Java VM given its flexibility and growing popularity. This write up shows a small instance how Groovy can be integrated into your system using the Spring Framework. Groovy can be injected in your enterprise stack to handle the more fluid context where logic tends to be updated to keep up with business requirements.
References
0. Google Doc for write up - http://docs.google.com/Doc?id=df3qdpw5_51fqxz7cft
1. Spring Dynamic Language Support - http://static.springframework.org/spring/docs/2.5.x/reference/dynamic-language.html
2. Ola Bimi - Language Exploration (blog) - http://ola-bini.blogspot.com/2008/01/language-explorations.html
3. Neal Ford - Polygot Programming (blog) - http://memeagora.blogspot.com/2008/01/polyglot-programming-parallels-perched.html
3. Grok - Polyglot Programming (blog) - http://www.grok-programming.com/2007/11/25/polyglot-programming-is-it-just-too-much-to-ask/
Subscribe to Posts [Atom]