Thought

WYSIWTF

Too funny

AJAX/Web 2.0
Design
General
Quotes
Software Development
Thought

Comments (0)

Permalink

Groovy + Annotations + Aspects

I have been doing a lot of digging into Groovy and DSLs lately, getting ready for my OSCON talk next week.

The Groovy language has great built-in support for creating DSLs. Along with its dynamic nature, Groovy has the “use” keyword for working with categories, and coming in 1.1, the ExpandoMetaClass if you want to complete.

“Use”ing Categories

Categories help you do scoped “extension” to normal every day objects. An example is in order:

  1. class TacoCategory {
  2.         static String getTacos(final Integer i) {
  3.                 “${i} tasty tacos”
  4.         }
  5. }
  6.  
  7. use (TacoCategory.class) {
  8.         println 2.tacos     // outputs -> "2 tasty tacos"
  9. }

So, inside the use block, there is now (effectively) a new property on the Integer class, called tacos, that will return a string describing your delectable entree. This is a very powerful technique, and is very useful for developing your own expressive syntax.

One drawback to this technique is that you have to define where you are using it. Use can be extended into closures, but does not always extend into predefined methods.

  1. aClosure = { println 3.tacos }
  2.  
  3. use (TacoCategory.class) {
  4.  aClosure.call()  // outputs -> "3 tasty tacos"
  5. }
  6.  
  7. aClosure.call()  // Exception No such property: tacos for class: java.lang.Integer
  8.  
  9. // However, you can do this from Java (or Groovy):
  10. GroovyCategorySupport.use(TacoCategory.class, aClosure)  // outputs -> "3 tasty tacos"
  11.  
  12.  
  13. //  calling methods on a class:
  14. class A {
  15.         public String getTacos() {
  16.                 4.tacos  // has not been evaluated yet
  17.         }
  18. }
  19.  
  20. println new A().getTacos()   // Exception No such property: tacos for class: java.lang.Integer
  21.  
  22. // but you can do this:
  23. use(TacoCategory.class) {
  24.   println new A().getTacos() // outputs -> "4 tasty tacos"
  25. }

Groovy + Annotations + Aspects = annotated “use” clause

I was talking about Groovy Categories with Blaine Buxton, and was telling him that I did not like having the “use” block inside my DSL code, and wanted a more transparent approach. He suggested that perhaps an Annotation and an Aspect would do what I was looking for.

With the 1.1-Beta1 Release, Groovy has built in support for Java Annotations, and since Groovy compiles down to byte code, there is implicit support for Aspects. Putting these two things together allows us to create an annotation for a more powerful use:

  1. class AnnotatedObject {
  2.  
  3.   @Uses(category=[MeasurementCategory.class])
  4.   public String fourPoundsOfSomething(something) {
  5.     (4.lbs.of(something)).toString()   
  6.   }
  7. }

With a simple annotation, @Uses(category=[list of category classes]), we now can define them for any method we want, without having to put them into the method body.

Here is the Annotation code:

  1. package com.nimblelogic.groovy.dsl;
  2.  
  3. import java.lang.annotation.Inherited;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6.  
  7. @Inherited
  8. @Retention(RetentionPolicy.RUNTIME)
  9. public @interface Uses {
  10.   public Class[] category();
  11. }

And here is the Aspect code:

  1. package com.nimblelogic.groovy.dsl;
  2.  
  3. import groovy.lang.Closure;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.List;
  7.  
  8. import org.aspectj.lang.JoinPoint;
  9. import org.aspectj.lang.annotation.SuppressAjWarnings;
  10. import org.aspectj.lang.reflect.MethodSignature;
  11. import org.codehaus.groovy.runtime.GroovyCategorySupport;
  12.  
  13. public aspect UsesAspect {
  14.        
  15.      pointcut allMethods(): call(@Uses * *(..));
  16.    
  17.     @SuppressAjWarnings
  18.     Object around(): allMethods() {
  19.         List< class >  classes = getCategories(thisJoinPoint);
  20.  
  21.         Object result = null;
  22.         if ( classes.isEmpty() ) {
  23.             result = proceed();
  24.         } else {
  25.                 result =
  26.                         GroovyCategorySupport.use(classes,
  27.                             new Closure(thisJoinPoint.getTarget()) {
  28.                                 @Override
  29.                                 public Object call() {
  30.                                     return proceed();
  31.                                 }                         
  32.                             });
  33.         }      
  34.        
  35.         return result;
  36.         }
  37.    
  38.     @SuppressWarnings(“unchecked”)
  39.         private List< class > getCategories(JoinPoint thisJoinPoint) {
  40.         List< class > classes = new ArrayList< class >();
  41.        
  42.         // get class level categories (if any)
  43.         Class cl = thisJoinPoint.getTarget().getClass();
  44.    
  45.         addCategories((Uses) cl.getAnnotation(Uses.class), classes);
  46.        
  47.         // get method level categories (if any)
  48.         if ( thisJoinPoint.getKind().equals(JoinPoint.METHOD_CALL)) {
  49.             MethodSignature sig = (MethodSignature) thisJoinPoint.getSignature();
  50.             addCategories((Uses) sig.getMethod().getAnnotation(Uses.class), classes);
  51.         }
  52.  
  53.         return classes;
  54.     }
  55.    
  56.    
  57.     private void addCategories(Uses uses, List< class > classList) {
  58.         if ( uses != null ) {
  59.                 Class[] classes = uses.category();
  60.                 for(Class cl : classes)
  61.                     classList.add(cl);
  62.         }
  63.     }
  64. }

One thing to note when working with Annotations / Aspects in Groovy: you have to keep track of the build order. I struggled for a while to figure out why I was not seeing the annotation in my Groovy classes. It was because it had not been built yet! I ended up having to split my compilation into 4 parts:

  1. Build the Annotation
  2. Compile the Groovy code
  3. Compile my other Java code (just test code)
  4. Weave the Aspects

Design
General
Grails
Groovy
Java
Software Development
Speaking
Thought

Comments (4)

Permalink

Uncle Bob on XML

I’m trying to catch up to my overflowing Google reader, and have just seen Uncle Bob’s posting on XML “The Hidiocy of XML Languages“:

Look, writing in XML is hideous. It’s wordy, it’s error-prone, it’s arcane, it’s redundant, it’s redundant, it’s redundant, it’s… HIDEOUS! To make matters worse, we have been embedding OTHER languages INSIDE this horrible container. EGAD! YIKES! ZOUNDS! FORSOOTH! This is just plain nuts, stupid, idiotic, retarded, poo-poo-headed, silliness!

All I can say is AMEN!!! And it just gets better.

I’ve never been a fan of XML. Yes, it does have benefits as a data transfer mechanism, though even that is questionable. Take the ACORD standards as an example. This is the standard schema for defining interoperability standards for Insurance Company operations/transactions (Quotes, etc). Fair enough, this can be very useful for companies to work together. However, each insurance company has it’s own way of doing business, and may not use the schema in the same way. ie a Policy for this company (or even Line of Business) may not mean the same as for another. So, how interoperable is that?

XML sucks. Its better than binary, or — shudder — ASN.1, but it still sucks, and should not be used as a language. Thank you Uncle Bob for your rant! It makes me that maybe, just maybe, I’m not as insane as people think when I tell them that I hate writing logic in XML.

Design
General
Software Development
Thought

Comments (2)

Permalink

God is not Great debate

Reverend Al Sharpton, former presidential candidate (among many other things) and Christopher Hitchens, author of “God is not Great” had a very interesting discussion a couple of nights ago. A partial (though fairly accurate) transcript is available here, with the full audio recording available here. Its 1.5 hours long, and with such an interesting topic, it is really hard to concentrate on other tasks at hand.

Regardless of which side of the debate you stand on, there is something to think about.

Books
Thought

Comments (0)

Permalink

Using Groovy to monitor CruiseControl builds

So, I am starting up a new project, and wanted to have a more visible indicator of what my Continuous Integration builds were doing. I am sticking with CruiseControl for this project, even though I recently looked at Continuum, and must say that it is really nice. I probably will start using that more and more as time goes on. But there is also a Ruby version of CruiseControl in the works, so one never knows…

Anyway, for this project it is good ol’ CruiseControl. And, I wanted to monitor it. There are plenty of monitors out there, but I was looking for something in particular. I wanted a big visible sign that something went wrong. The CC server, a desktop PC that will also server as first-stage test server and DB, is sitting in the same area as my partner and I. So, we will be able to see the screen when something goes wrong. And it will provide a cool green glow when everything is alright.

I decided to write my own monitor, after seeing that CruiseControl has a Socket interface for publishing statuses.

While digging around in Groovy in Action (a fabulous book, BTW), I noticed that Groovy scripts can run in interactive mode, so one could write something as simple as this:

groovy -l port -e “System.out.println line”

And one has a simple command line monitor that will just dump the status to the console. Now, this is really no better than doing a:

tail -f cruisecontrol .log

Which it is rather boring… so I decided to use SwingBuilder.

My first experience with SwingBuilder was for my Groovy DSL talk a few weeks ago… I implemented a pseudo-LOGO interpreter on top of Groovy, using SwingBuilder to build my environment. It was the first time in a LONG time that I enjoyed working with Swing.

Here is the code for the monitor:

  1. import java.net.*
  2. import groovy.swing.SwingBuilder
  3. import java.awt.Color
  4. import javax.swing.WindowConstants as WC
  5.  
  6. class Listener {
  7.         def GRAY = new Color(123,123,123,123)
  8.        
  9.         def colorMap = [“Success” : Color.GREEN,
  10.                                “Failure” : Color.RED,
  11.                                “Fixed” : Color.YELLOW]
  12.        
  13.         def swing = new SwingBuilder()
  14.         def frame = swing.frame(title:‘Build Status’,
  15.                                            location:[0,0],
  16.                                            resizable:false,
  17.                                            defaultCloseOperation:WC.EXIT_ON_CLOSE,
  18.                                            background: GRAY) {
  19.                 boxLayout()
  20.                 vbox {
  21.                         panel(  id:‘canvas’, size:[300,600], background: GRAY ) {
  22.                                 vstrut(height:300)
  23.                                 hstrut(width:600)
  24.                         }
  25.             }
  26.         }
  27.                
  28.         def process(socket) {
  29.                 try {
  30.                         socket.inputStream.eachLine { line ->
  31.                                 println “received ‘${line}’ at “ < < new Date().toString()
  32.                                 swing.canvas.background = colorMap[(line =~ /^\w+/)[0]]
  33.                         }
  34.                 }
  35.                 catch(Exception e) {
  36.                         e.printStackTrace()
  37.                         swing.canvas.background = colorMap[“Failure”]
  38.                 }
  39.                 frame.toFront()
  40.         }
  41.        
  42.         def listen(port) {
  43.                 frame.pack()
  44.                 frame.show()
  45.                
  46.                 def server = new ServerSocket(port)
  47.                 while(true) {
  48.                         def socket = server.accept()
  49.                         Thread.startDaemon { process(socket) }
  50.                 }
  51.         }
  52. }
  53.  
  54. new Listener().listen(7600)

The code is fairly straightfoward… open up a ServerSocket listening on a port, waiting for a socket to connect…. when one does, the process method is called and the window’s color is changed to the appropriate color for the status.

Simple, and quick, it didn’t take too long to throw that together, and now I have a tool that can be reused for any other time I use CruiseControl.

Here are the results:

Success!
Screenshot

Failure :(
Failure

Fixed!
Fixed!

Agile
General
Groovy
Java
Software Development
Thought

Comments (0)

Permalink