Latest Posts »
Latest Comments »
Popular Posts »

Concise EDSL Closures in Java

Written by Jevgeni Kabanov on May 19, 2008 – 11:43 am

This trick was pointed to me (without the ThreadLocal part) by Rein Raudjärv, who saw it used in jMock.

The problem with Java “closures” aka anonymous inner classes being a tad too ugly is a well known one, but this semi-solution seems to be quite unused. Although you can apply the same principle for many situations it’ll work best for embedded DSLs.

Let’s start by defining an EDSL intefrace:

JAVA:
  1. public interface DSL {
  2.  
  3.   DSL doSomething();
  4.   DSL doSomethingElse();
  5.   DSLPreClosure closure();
  6. }

As you can see we separated the actual closure application in a separate interface:

JAVA:
  1. public interface DSLPreClosure {
  2.   DSL apply(DSLClosure closure);
  3. }

The reason for that is that we want to use closures without defining a method in the anonymous inner class:

JAVA:
  1. public class Test {
  2.   public static void main(String[] args) {
  3.     new DSLImpl()
  4.       .doSomething()
  5.       .closure().apply(new DSLClosure() {{
  6.         dsl
  7.           .doSomething()
  8.           .doSomethingElse();
  9.       }})
  10.       .doSomethingElse();
  11.   }
  12. }

What happens is that we abuse a little used Java feature — initializers. If you put a block in the body of a class definition it will be executed right after the constructor. In our case we construct a new subclass of DSLClosure and immediately add an initializer:

JAVA:
  1. new DSLClosure() {
  2. //Initializer starts here
  3. {
  4. //Closure body goes here
  5. }
  6. //Initializer ends here
  7. };

Of course while this allows to execute a block of code with fewer symbols to write, we still need to somehow pass parameters. Note, that since the initializer executes inside the constructor call, it will be executed before the actual apply() method is called. Therefore we make use of the ThreadLocal class to pass the parameters inside the call:

JAVA:
  1. public class DSLImpl implements DSLWithClosure {
  2.   static final ThreadLocal curDSL =
  3.     new ThreadLocal();
  4.  
  5.   public DSL doSomething() {
  6.     //Do something…
  7.     return this;
  8.   }
  9.  
  10.   public DSL doSomethingElse() {
  11.     //Do something else…
  12.     return this;
  13.   } 
  14.  
  15.   public DSLWithClosure closure() {
  16.     curDSL.set(this);
  17.     return this;
  18.   }
  19.  
  20.   public DSL apply(DSLClosure closure) {
  21.     curDSL.set(null);
  22.     return this;
  23.   }
  24. }

Finally the DSLClosure exposes the ThreadLocal parameter as a protected field:

JAVA:
  1. public class DSLClosure {
  2.   protected DSL dsl =
  3.     (DSL) DSLImpl.curDSL.get();
  4. }

Of course, for the sake of correctness we should also allow nesting closure calls on the same thread, so we should use a stack inside ThreadLocal, but this is left as an exercise to the reader :)


Tags: ,
Posted in creative | 5 Comments »

5 Comments to “Concise EDSL Closures in Java”

  1. foo bar Says:

    This article needs a concrete example comparing this method to the standard functor closure.

  2. Jevgeni Kabanov Says:

    It’s not an article, it’s a blog post and what do you mean under standard functor closure?

    BTW, anonymity is not welcome on our blog.

  3. Christian Vest Hansen Says:

    I smell a wacky hack :)

    jMock kind of have its merits because they try to keep the wackyness to themselves, but I was still scratching my head when I read their tutorial.

    When I look at that api, I get a feeling that there’s too many rocks for the bugs to hide under. I’ve found that simpler code produce simpler bugs, so I think I’ll skip this one and wait with closures until Java 7 when we hopefully get a more clear-cut syntax for the concept.

  4. Jevgeni Kabanov Says:

    Christian: It is highly unlikely that closures will go to Java 7 with the current state of affairs. For the reasons check out this: http://getahead.org/blog/joe/2008/05/19/big_question_for_sun.html .

  5. Christian Vest Hansen Says:

    “highly unlikely” sounds exagerated in my ears :) Last I looked, the closures group on openjdk.org looked live and kicking. They have a good road map that extends till august and expecting to produce a final prototype. If I remember correctly, Java 7 is scheduled for release at beginning of next year. To me, this looks like an entierly reasonable timeframe for getting closures in Java 7. I got my fingers crossed.

Leave a Comment

Additional comments powered by BackType