Cool Groovy aspect in Spring

I’ve been teaching a lot of Spring framework classes lately. In one of them, we have a unit on Aspect Oriented Program (AOP) in Spring. Spring provides all the necessary infrastructure to make AOP doable. You can define aspects using annotations, and Spring will auto-generate the necessary proxies to implement them.

As an example, the materials (written for Java, of course), presented an aspect similar to this:

package mjg.aspects;

import java.util.logging.Logger;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class PropertyChangeTracker {
    private Logger log = Logger.getLogger(PropertyChangeTracker.class.getName());
    
    @Before("execution(void set*(*))")
    public void trackChange(JoinPoint jp) {
        String method = jp.getSignature().getName();
        Object newValue = jp.getArgs()[0];
        log.info(method + " about to change to " + 
            newValue + " on " + jp.getTarget());
    }
}

For those who haven’t done AOP, or who haven’t done AOP in a while, an aspect consists of a pointcut and advice. The advice is what you want to do, and the pointcut is where you want to do it.

In this case, the pointcut is inside the @Before annotation. It states that the pointcut is before every method in the system that begins with set, takes a single argument (two dots would represent zero or more arguments — a single star is one argument) and returns void.

The advice is the trackChange method. Spring calls this method whenever the pointcut applies, and it supplies the JoinPoint argument from AspectJ. The join point provides context, because from it you can get the name of the method being called, its arguments, and a reference to the target object, as shown above.

This aspect logs properties that are about to change. Along with the Spring configuration file (which I’ll get to shortly), it demonstrates an aspect being applied in a very general way.

One of my students, however, had an obvious question. It’s all well and good to print out which set method is being called and on which object, but what would be really useful is to know what the value of the property was before the set method changed it. What’s the current value of the property?

The JoinPoint class doesn’t really have methods to determine that, unfortunately. The javadocs for AspectJ are located at Eclipse, of all places, if you want to take a look.

A friend of mine and I debated how we would go about figuring out the current value. Since we know the name of the setter method being invoked and we have a reference to the current object, some form of reflection and string manipulation would probably do the trick.

That’s when it hit me, though, that the job would be almost trivial in Groovy. Let me show you the answer and then talk about it. Here’s my Groovy aspect.

package mjg.aspects

import java.util.logging.Logger

import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before

@Aspect
class UpdateReporter {
    Logger log = Logger.getLogger(UpdateReporter.class.name)
    
    @Before("execution(void set*(*))")
    void reportOnSet(JoinPoint jp) {
        String method = jp.signature.name
        String property = (method - 'set').toLowerCase()
        def current = jp.target."$property"
        log.info "About to change $property from $current to ${jp.args[0]}"
    }
}

I called the aspect UpdateReporter. It defines the same pointcut as the PropertyChangeTracker. This time, though, it’s easy to figure out the current value of the property. I just subtract set from the name of the method and convert to lowercase, which gives me the property name. Then I invoke the get method by using the standard POGO convention that accessing the property invokes the getter. The string interpolation is just to make sure I evaluate the method rather than treat it as a string property of the class.

I now need a class with some set methods in it, so I made a POJO.

package mjg;

public class POJO {
    private String one;
    private int two;
    private double three;
    
    public String getOne() { return one; }
    public void setOne(String one) { this.one = one; }
    public int getTwo() { return two; }
    public void setTwo(int two) { this.two = two; }
    public double getThree() { return three; }
    public void setThree(double three) { this.three = three; }

    @Override
    public String toString() {
        return "POJO [one=" + one + ", two=" + two + ", three=" + three + "]";
    }
}

Here is the Spring bean configuration file, in XML.

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <aop:aspectj-autoproxy />

    <bean id="updater" class="mjg.aspects.UpdateReporter" />
    <bean id="tracker" class="mjg.aspects.PropertyChangeTracker" />	 
    <bean id="pojo" class="mjg.POJO" p:one="1" p:two="2" p:three="3"/>	
</beans>

The aop namespace contains the aspectj-autoproxy element, which tells Spring to pay attention to the @Aspect annotations and generate proxies as needed. Spring AOP applies at public method boundaries of Spring-managed beans, so I needed to add the POJO bean to the configuration file as well.

The final piece of the puzzle is to actually call the setter methods on the POJO, which I did with a test case. I used Spring’s JUnit 4 test runner to cache the application context.

(In other cases I use Spock’s Spring capabilities to do the same thing with Spock tests, but that’s another story.)

package mjg;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@ContextConfiguration("/applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class POJOTest {
    @Autowired
    private POJO pojo;

    @Test
    public void callSetters() {
        pojo.setOne("one");
        pojo.setTwo(22);
        pojo.setThree(333.0);
        assertEquals("one", pojo.getOne());
        assertEquals(22, pojo.getTwo());
        assertEquals(333.0, pojo.getThree(),0.0001);
    }
}

The Spring test runner also injects the POJO into the test, which is convenient. Running the test then prints to the console (cleaned up a bit):

INFO: About to change one from 1 to one
INFO: setOne about to change to one on POJO [one=1, two=2, three=3.0]
INFO: About to change two from 2 to 22
INFO: setTwo about to change to 22 on POJO [one=one, two=2, three=3.0]
INFO: About to change three from 3.0 to 333.0
INFO: setThree about to change to 333.0 on POJO [one=one, two=22, three=3.0]

How cool is that? I love it when I find an application where Groovy makes life much easier than the Java alternatives. I have to admit that I was almost insufferably pleased with myself when I got this to work, though of course it’s all Groovy — and Spring’s very friendly relationship to it — that made it all possible.

By the way, what is that mjg package I keep using? Why, Making Java Groovy, of course. This example is going directly into the chapter on Groovy and Spring, so consider this a bit of a teaser. 🙂

SpringOne 2GX final thoughts

I wound up too busy to maintain my daily reports, but here are a couple of items I want to highlight as important take-aways from SpringOne 2GX. Rather than just recap sessions or dole out marketing-type praise, I’m going to focus on some things I learned that I didn’t necessarily expect.

  1. A lot of people who advocate Scala or Clojure over Groovy emphasize their scalability and features like immutable objects. Groovy’s @Immutable annotation takes care of the latter, and the gpars project handles the rest. You can use @Immutable right away. The gpars project is still pretty early in its lifecycle, but it’s going to be HUGE.
  2. By the way, despite the fact it looks like it’s pronounced “Gee-Pars” (and Paul King kept calling it that), I love the way Scott Davis kept referring to it as “jeepers” 🙂
  3. Twitter has reached “essential” status at conferences. This is the first conference I attended where I would have missed half of what was going on if I hadn’t been using my Twitter client the whole time (I use twhirl, btw, but I’m open to other possibilities). Most of the presenters (@glaforge, @graemerocher, @paulk_asert, @daveklein, @jeffscottbrown, @scottdavis99, @aalmiray, and several others that would come to mind if I thought harder about it) were continually tweeting good info. As a company, @ManningBooks did an excellent job, especially with their #hideandtweet game.
  4. As a totally unexpected (to me) underlying theme, the rise of non-relational databases is striking. Apparently, the major cloud providers (Google AppEngine, Amazon SimpleDB) have decided that relational simply doesn’t scale, so they’re going with “schemaless” solutions. I had no idea how significant that was until I heard enthusiastic support for the idea from the audience of one of the Amazon cloud computing sessions. I know a lot of DBAs who are in for quite a shock. So is Oracle, too, and that’s got to be a Good Thing.
  5. Like Grails recently and Ruby on Rails before that, the new Spring Roo project makes existing web development approaches look antiquated. Roo and Grails are siblings that will learn a lot from each other as they continue to grow. For example, Grails has an interactive console, but it isn’t nearly as cool as Roo’s. I’m sure that’ll change soon enough.
  6. The extraordinarily humility and friendliness of the Groovy and Grails core teams is charming. Everyone I met seems almost embarrassed to be having so much fun working on something they like so much. There’s none of the arrogance or elitism that characterizes so many other revolutionary groups, and they always go out of their way to help and answer questions. I love talking to them and really hope to be included as one of them some day.
  7. Speaking of that, sometimes timing is everything. I told Guillaume Laforge (Groovy team lead, for those who don’t know) that he was one of my personal heroes and nearly made him spit up his drink. Sorry, I didn’t get a picture. 🙂
  8. Griffon made several fans at the conference, especially among the existing Groovy people. I still think it’s a bit early for mainstream practice, but all the signs are favorable.
  9. October is definitely the right time to visit New Orleans.

I had a very good time at the conference and am already looking forward to the next one.

SpringOne 2GX Day 1

… or day 2, by the official count. Today was the first full day of sessions, though, so I’m counting from 1.

From now on, I can only comment on the sessions I attended. There were many parallel sessions I wish I could have gone to, but until I get one of those cool Time Turner like Hermione Granger had in the third Harry Potter movie, I still have to operate synchronously. I’ll just make some comments about each here.

Since the conference is a combined one, I decided I should try to attend some Spring sessions as well as Groovy/Grails/Griffon ones. The first session I went to was “Overview of the Spring 3.0 Web Stack,” given by Keith Donald. This was a major overview, with some discussion of Spring MVC, Spring JavaScript, Spring Web Flow, Spring Faces, Spring Security, and even Spring BlazeDS Integration. That’s obviously way more that can be covered in one session, so a lot of the slides were really pointers to other presentations given later in the conference.

That said, after the introductory material he spent a fair amount of time on the new REST support in Spring MVC 3.0. I’ve been working with Spring 2.5 for some time, and I’ve played with the new MVC annotations like @Controller and @Service, but I hadn’t seen the RESTful ones yet.

To give us an idea what’s coming, Keith went over parts of the new sample application for Spring MVC 3.0, yet another version of their PetClinic app. For those interested in looking at it, the svn repository for the RESTful PetClinic is here. Feel free to check it out.

Keith spent a fair amount of time on ways to do the URL mapping, the new validator framework, and the new formatters that replace custom property editors. This isn’t the right post for a detailed discussion, so I’ll refer you to SpringSource for more details. The slides suggested the link http://www.springsource.org/web , but that site didn’t exist when I tried to go there. Still, there’s tons of documentation on all the projects at the base URL.

It turned out there wasn’t time for much information about the other areas, but I did note that Spring JavaScript is really a spring-enabled front end on dojo, which is pretty cool.

(I can’t help automatically going, “Pain … does not exist … in this dojo!” Hopefully Spring JavaScript is also painless.)

It also turns out that the amount of configuration to get Spring Security working has been reduced dramatically. That can only be good news.

In the end, I’d say that Spring definitely lived up to its “Swiss Army Chainsaw” reputation, but I liked a lot of what I saw.

(I especially liked the introduction to Spring Roo that I saw later. See below for that.)

The next talk I attended was “Introduction to Griffon” by Danno Ferrin. I was torn there, because I really wanted to go see Paul King talk about Spring and web services, but I knew most of what Paul was going to say already. Besides, I can probably harass him with questions about the rest (no pun intended) tomorrow. 🙂

I do know something about Griffon. It started off as an offshoot of the Grails project, with the same value proposition: bring ease of development and convention over configuration to desktop development. I’ve had long email exchanges with Andres Almiray about Swing development, especially with Groovy’s SwingBuilder and working on and off the Event Dispatch Thread, which I’ve written about here a few times. I’ve only run the basic demos on Griffon, though, and hadn’t seen it presented in any official way yet.

Griffon is all about enforcing MVC architecture with desktop apps. It looks and feels a lot like Grails, but there are important differences. The project is only at version 0.2 (and only a beta for that at the moment), so it’s really early. Still, the basics of “MVC groups” (Danno wanted a better term for them, but I kind of like that one), event handling, deployment, and more are already in place.

The deployment story rocks, by the way. You can export your app as a jar file, as an applet, or even as a Java Web Start application automatically, and it’ll help you digitally sign the jars. That’s really cool. The whole technology is pretty slick, actually. It’s pretty much the only framework for desktop apps I know, though I believe there are a few in development. I suggest that anyone interested in desktop development (and there are far more people like that than most developers think) to check it out at its home page.

By the way, Danno had a great line that I just have to use in the future. He said at some point in the presentation he might have to switch from Bob Ross mode to Julia Child mode, meaning he wasn’t necessarily going to have enough time to paint in front of us, but rather would have to pull completed meals out of the oven. I knew exactly what he meant. 🙂

My feeling about Griffon is that it’s great, but it’s still very early in the development cycle and the documentation isn’t sufficient yet for actual work by people who aren’t closely involved in the project. On the other hand, Danno, Andres, and James Williams (not here) are all co-authors on the upcoming “Griffon in Action” book from Manning. I suspect that book will be as important to future Griffon developers as “Groovy in Action” was (and is) to Groovy developers.

** update: James’s last name is Williams, of course. Also, he’s not a co-author on the book. He is a core committer on the Griffon project. **

The next talk I attended was Paul King’s presentation of “Industrial Strength Groovy.” As he explained, some of the reluctance to adopt Groovy that he finds in the business world is a fear that they won’t be able to use the tools they already adopted and really like. Paul went through a range of tool categories showing how that wasn’t the case.

He discussed lots of testing tools, including mocks like MockFor (built into Groovy), GMock, and EasyMock; injection with Spring or Guice; code coverage with Cobertura; build tools like Ant, Gant, GMaven, and Gradle, Hudson continuous integration, and lots more.

Here’s the best part, at least as far as you, the outside reader, is concerned. You can see all of Paul’s slides on SlideShare.

As an aside, I’m of the opinion that anything Paul writes is great. He has an excellent introductory tutorial for Groovy online in PDF form. He’s also a co-author on GinA (Groovy in Action), which doesn’t surprise me at all.

For the next talk I switched back to the Spring side and attended “Introduction to Spring Roo” by Ben Alex. Ben founded the Roo project, and as it turned out he also founded the Spring Security project. That’s quite a resume. He’s also an outstanding presenter. He doesn’t go for rah-rah tricks or false enthusiasm. Instead he has a very friendly, comfortable, low-pressure style that I find quite appealing. He reminds me a lot of Jason Rudolph that way, or even Guillaume Laforge.

I’d heard of Spring Roo, but didn’t know any details. My original thought was, “oh no, not another Java framework,” but decided to give Roo a try.

Let me just say flat out that I was very impressed. Roo’s best feature (okay, best is a strong term — one of its best features) is that it operates as an interactive command-line application with lots of help and hints available. You start up Roo at the command line (or in STS), type “hint”, and it tells you what it’s expecting next. Just keep hitting the TAB key to get more suggestions.

Essentially what Roo is about is building and configuring a Maven project with lots of AspectJ code generation to modify the source. It felt a lot like Grails, but using Java instead, and most of the code generation affected what happens at compile time rather than at run time. For example, it automatically generates getters and setters and toString() methods for domain objects. It generates the same sort of dynamic finders that Grails has, though you have to choose to add them. It automatically configures Spring JavaScript to do form validation. It uses the JSR 303 bean validation annotations to enforce what it wants. It configures databases for you, too.

I couldn’t help but feel that the Grails framework has been highly influential inside SpringSource. I can only assume that’s partly because Graeme Rocher is now one of their employees (after they bought G2One). At any rate, this was the first Java-based framework that I thought could provide serious competition to Grails. I still like Grails partly because I really like Groovy, and I think it’s always easier to implement anything in Groovy than in Java. Also, Grails has about 300 plugins at the moment, that do basically everything. But if you’re committed to Java, Roo looks like a great alternative. You can download it at the project page at SpringSource.

I only had a couple of criticisms. One was that you can replay your Roo scripts, which is cool, but there’s no way to automatically record them as you go. Expect that to change, since everybody seemed to want it.

The other came from the fact that I downloaded Roo while Ben was talking and was running the app along with him. Then, when typed

roo> perform eclipse

to generate an Eclipse project, I did the same and had to wait about 15 minutes (literally — that’s an estimate) while the underlying Maven engine downloaded the Internet. When I went to test the app in Tomcat, I exited Roo and typed “mvn tomcat:run” and waited again for tons more downloads, even though I have both Tomcat 6 and Tomcat 5.5 on my hard drive already. Finally, when I tried out the Selenium support (another great feature, btw) and ran “mvn selenium:selenese” I had to wait again as Maven did its thing. They all worked, and the delays all had to do with Maven rather than Roo, but yikes nevertheless.

Right now Roo is at version 1.0.0.RC2 and should be at GA some time in December, and that one will include docs. Until then it’s mostly blog posts and the associated forums. I’m definitely going to try Roo, though, when it’s ready.

This post has already gone on too long, so I think I’ll leave it at that. I’m enjoying the conference and am looking forward to more presentations tomorrow.

%d bloggers like this: