Dynamic subclass APIs make Java seem young again

At JavaZone 2010 I will be giving a lightning talk on APIs that use dynamic subclasses. These APIs make it possible to do things in Java that seem like pure magic. Here are some ideas of what you can get from these APIs and a look under the hood, so you really understand what’s going on.

Mockito – “the best Java library named after a summery drink”

Mocking is a hotly debated subject within testing camps. I think a lot of the arguments come against mocking (beyond overuse…) come down to the fact that the last generation of mocking libraries left a lot to be desired. A desire that has been fulfilled by Mockito.

I will leave the examples at a minimum, but here’s an example from code I actually use a lot. Mocking the servlet API:

For those of you who’ve struggled with jMock or it’s ilk, you may notice the concise syntax used to specify behavior (“when(…).thenReturn()”) and the fact that you don’t have to set up expectations before exercising the code.

LambdaJ – “making Java beautiful and incomprehensible”

LambdaJ pretty much starts with the realizations that waiting for new language features like closures may prove to be a very long wait indeed. Furthermore, anonymous inner classes may technically be used to simulate closures, but they are so ugly that not even a mother could love them.

Let’s look at an example: Finding the name of every member of the Simpsons family who’s older than 8, in order of age.

In plain Java:

More modern languages are way ahead of Java. Here’s Ruby:

The rather simple request is simple to express. Yay!

Java 7 may make this better.

All in all, not a bad contender. What about LambdaJ:

It’s not perfect, but it has one thing to recommend it: This works with standard, everyday Java, today! There’s no special compilation crap. No other language. Nothin. Just plain old Java.

(Thanks to Mario Fusco for improving the example with LamdbaJ 2.3 syntax)

What’s going on

Both LambdaJ and Mockito use a tricky sleight-of-hand: Generate a dynamic subclass which records its method invocations for later use. Creating such an API is in principle easy, although my implementation leave a lot! of details unimplemented.

So: We want invocations on the generated class to be template/mock objects to be saved:

This magic is surprisingly easy to implement with CgLib:

This creates a subclass of the template class (in this case: Person). But every method in Person is overridden by calling the invocation handler. Which simply saves what method was called.

This makes it possible to implement a prototype of LambdaJ’s collect method:

This is a gross simplification. LambdaJ handles many aspects that my prototype simple ignores: Chained method calls, multithreading, method arguments, and multiple invocations on the same line.

The future of Java

Maybe the future of Java isn’t extending the language. Maybe the future of Java isn’t replacing the language with Scala. Maybe the future of Java is smart people discovering smarter ways of using what’s already there. My hat off to Mario Fusco, Szczepan Faber and everybody who’s contributed to LambdaJ or Mockito.

Come to my talk at JavaZone to learn more!

Copyright © 2010 Johannes Brodwall. All Rights Reserved.

About Johannes Brodwall

Johannes is Principal Software Engineer in SopraSteria. In his spare time he likes to coach teams and developers on better coding, collaboration, planning and product understanding.
This entry was posted in English, Java. Bookmark the permalink.
  • Mario Fusco

    Hi Johannes,

    I am Mario Fusco. First of all thanks a lot for your interest in lambdaj.

    As for your examples maybe it worth to mention that you could make some of them more readable by using the lambdaj fluent interface collections, introduced with the release 2.3, as it follows:

    with(theSimpsons)
    .retain(having(on(Person.class).getAge(), gt(8)))
    .sort(on(Person.class).getAge())
    .extract(on(Person.class).getName());

    Do you think it makes sense?

    Cheers,
    Mario

  • http://www.johannesbrodwall.com/ Johannes Brodwall

    Hi, Mario

    Thanks a lot for the comment, for LambdaJ and for the suggested improvement. I’ve incorporated it in the article.

    I like the fluent interface collections. Putting the “startpoint” in the middle, instead of at the beginning of the expression, bothered me about the examples.

    By the way, how do you like my suggestion for a slogan for LambdaJ?

  • Bjorn

    I saw your talk at Javazone, very nice :)
    Thought I’d give a quick-and-slightly-hackish version of this example using Google Guava

    List theSimpsons = Lists.newArrayList();

    System.out.println(Joiner.on(“, “).join(Ordering.from(new Comparator() {
    public int compare(Person a, Person b) {
    return a.getAge() – b.getAge();
    }
    }
    }).sortedCopy(Iterables.filter(theSimpsons, new Predicate() {

    public boolean apply(Person input) {

    return input.getAge() > 8;
    }
    }))));

    Also there is a small error in your Comparator implementation, the compare(…) signature returns int not void

  • http://www.johannesbrodwall.com/ Johannes Brodwall

    Thank you for the nice comment and thanks for pointing out the problem with compare(). I’ve fixed the code now.

    The Guava code is nicer than the pure Java-code, but I think I’ll always prefer a straight up foreach-loop over anonymous inner classes.

  • http://qmsconsultants.com/NABH.html NABH

    I really appreciate your post and you explain each and every point very well.Thanks for sharing this information.And I’ll love to read your next post too.
    Regards:
    NABH