Core Spring Training course, day 4

The agenda for day 4 included a more in-depth look at Spring’s AOP facilities, its support for adding JMX management capability to Java classes, and its wrappers for remote object access. There was also a little unexpected extra.

Many of Spring’s features are implemented internally using its AOP (aspect-oriented programming) facility, so understanding AOP is a pretty important step toward understanding Spring as a whole. That being the case, Keith had covered a bunch of AOP concepts on day one, but today he got into the nitty gritty details as well as discussing how to use AOP for incorporating custom aspects into application code.

AOP basically involves wiring additional behavior into code after the fact, either at runtime or in a compilation step. Used well, it can reduce code clutter by getting rid of a lot of boilerplate plumbing code that has nothing to do with the actual functions being performed by a particular piece of application code. The reduction in clutter can make it much easier to read a piece of code and figure out what it does. (Like C++ operator overloading, though, it’s a tool that can be used for good or evil. Careless, inappropriate use of AOP can lead to code that’s difficult to debug and has mysterious performance characteristics.)

Prior to this class, every AOP article I’d read that tried to describe what AOP was good for pretty much boiled down to, “well, you can use it for logging.” Spring uses AOP for a lot more than that, though; all the declarative decorations you can add to Spring-managed classes (transactions, security, remoting, even performance monitoring and runtime hot-swap capability) are done using AOP. Spring’s AOP, which is applied at the method level (as opposed to something like IBM’s AspectJ, which can apply aspects at the field or line-of-code level) works by creating a proxy object that wraps the underlying POJO. Every time a method is invoked on the proxy, Spring looks through the list of “advisors” associated with that proxy. If any of them apply to the method, the code configured into the advisor is executed before, instead of, or after the underlying POJO method.

The creator of AspectJ is now working for Interface21, the company that does most of the core development of Spring, so Keith said we can expect an increasingly strong AOP story from Spring in the future.

Spring’s AOP can be configured programmatically (via “add aspect X to class Y” API functions) or via the normal Spring configuration files. Programmatic configuration has some pluses; it gives you refactoring support — if you rename a class, your IDE can automatically update the references — and can run in a standalone setting without any Spring configuration files or its application container. On the other hand, running in the Spring environment means none of the application code has to call Spring APIs, and if you use Spring’s auto-proxying capabilty, you can apply aspects to lots of places in your code with just a couple small configuration entries.

After we covered all the basics, the first two labs of the day involved adding a custom aspect to a simple test method to record how long the method took to run. Having written that aspect, it was possible to do performance monitoring of any method on any Spring-managed class in the application just by tweaking a config file, no code recompile necessary. Both the AOP labs were a reasonable mix of handholding and from-scratch coding; everyone finished each of them under an hour (about which more below.)

Once we were all done with the lab, Keith moved on to a more advanced feature of Spring AOP: “mixins,” which basically amount to adding multiple inheritance support to Java. Basically, you can configure Spring so that the proxies it creates to wrap around your classes implement not only all the interfaces your original class does, but also any other interfaces you choose, each of which delegates to another object of your choosing. As a simple example, Keith demonstrated adding an ID field to a business object that didn’t have an ID already, something like taking

public class BizObject {
    int a;
    public int getA() { return a; }
    public void setA(int a) { this.a = a; }
}

and

public interface HasAnId {
    public int getId();
    public void setId(int id);
}

and, by use of a proxy, ending up with client code that could do something like:

MyBizObj obj = something();
log.debug(\"object \" + ((HasAnId)obj).getId() + \" has value \" + obj.getA());

It wasn’t demonstrated, but I assume you could also do something like

public interface MyBizObjWithId extends MyBizObj, HasAnId { }

and configure the proxy to implement that new interface, so you could call all the mixed-in methods without any casting.

Another advanced use of Spring’s proxy-based AOP is to allow hot-swapping of target objects. For example, say you have a POJO that’s pretty expensive to create (needs to establish a database connection, etc.) Instead of using that object directly, you can use it via a proxy, and have Spring get the instances of the object from a pool using a factory class. From the client code’s point of view, it gets to keep a long-term reference to what it thinks is the POJO, but calls to the methods on that object will cause actual underlying objects to be pulled from a pool, possibly blocking if the pool is empty at the time. (And setting that up in the Spring configuration is a matter of adding one extra attribute to the description of the POJO!)

JMX was the next topic of discussion. Keith started out with an overview of what JMX is and what it’s used for (in short: monitoring and runtime tweaking of code, much like a software analog of SNMP.) It’s very useful, but unfortunately, writing a solid JMX management class (called an MBean) is really a pain using the standard JMX APIs. It’s enough of a hassle that most people don’t bother with it even when it would provide useful functionality.

Java 5 has built-in JMX support — in fact, it ships with a JMX monitoring console, and the JVM itself exposes a bunch of MBeans for monitoring memory and CPU usage, garbage collection statistics, and other stuff. Other packages have JMX support too; for example, Hibernate has a statistics-gathering MBean, and app servers like JBoss and WebLogic make heavy use of JMX for their internal configuration.

Unfortunately, we didn’t get any JMX labs; the PCs in the training facility were configured with old Windows installations, and the Java 5 JMX monitor requires access to a filesystem with better access-control mechanisms than FAT32 has. But Keith hooked the projector up to his personal laptop and we were at least able to see demos of all this stuff in action.

As you might expect, Spring hides all the complexity of the JMX API. Any Java class can be exposed as an MBean by configuring Spring to create a JMX proxy for it. You can control which methods and attributes are exposed to management clients either via Spring configuration or using Java 5 annotations, which the Spring JMX proxy factory can look for and obey.

There’s also corresponding support for simple-to-write JMX clients; once again, you just ask Spring to give you back an JMX proxy that implements whatever business interface your remote bean uses, and Spring takes care of all the underlying details.

Unfortunately, there isn’t yet any support for JMX’s notification mechanism (where an MBean can push data to clients that are monitoring it) but Keith said that’d show up in the future since it’s very useful to lots of people.

The JMX discussion led straight into Spring’s remoting support, because the two look very similar. As with JMX, you tell Spring to wrap remote accessibility around a plain Java object, and it takes care of all the details. With no client or server code changes, you can change from Java RMI to XML-over-HTTP (Burlap) to Spring’s own remoting protocol; Keith showed us sample configurations for exposing the same object over a variety of protocols. Remote object access is dead simple with Spring in the picture.

Of course, some people are already using EJBs for remote object access; Spring provides some helper methods to make EJBs play nice and to give them access to Spring services. For example, if your stateless session bean extends AbstractStatelessSessionBean, you get lots of helper methods for free and Spring can do dependency injection into your EJB. Spring’s transaction management and EJB’s container-managed transactions can work together, though it’s typically recommended to choose one or the other.

On the EJB client side, the picture is better; accessing a remote EJB is just like any other form of Spring remoting, and you never have to muck with local vs. remote interfaces, home interfaces, or anything like that. Just supply the business interface that your EJB implements, and Spring’s remoting framework will do all the work to set up the EJB call, including runtime bytecode generation to make a new interface that throws all the proper RemoteExceptions.

The remoting lab wasn’t EJB-based, though; we added remote accessibility to a business class and wrote a client app to talk to it. Nothing too complex, just a good hands-on application of the stuff we’d been hearing about.

Remoting was supposed to be the last item on the agenda. However, we got a little more than that: Colin Sampaleanu gave us a walk-through of the Acegi “contacts” demo, to help make up for the abbreviated coverage of Acegi on day 3. The contacts demo is both good and bad. It’s good because it shows off just about everything Acegi can do. But that’s also why it’s bad — you’re left with the impression that Acegi is even more complex to use than it actually is. I’d say it’s a good demo of Acegi’s power but less great as a tool for coming up to speed.

Acegi has a bunch of interesting features that Colin walked through. For example, among the other security constraints you can set on a resource (anonymous vs. logged in, user must have a certain role, etc.) you can say things like, “This resource is only accessible on a secure channel.” If you set that on a web page and the user hits the page with regular HTTP, the framework will automatically spit out a redirect to send the user over to an HTTPS version. You might mark the rest of your site as only accessible on a non-secure channel, in which case the user would be redirected back to HTTP after finishing with the secure part of the site. None of that logic has to be coded into the controllers or the views/JSPs.

For getting users and roles, the built-in JDBC authentication provider is pretty nice. It will pull login names and passwords from configurable columns on a configurable table, optionally applying encryption (configurable, of course!) to the password to support sites that store MD5 hashes or something similar instead of plaintext passwords.

There is also support for ACLs that can be applied to resources at any level of granularity; for example, you can grant permission to individual users to call individual methods on a Spring-managed class. But more typically ACLs are used to control access to web pages or to change what’s displayed on a given page, and there are a bunch of built-in JSP tags to do conditional displays based on the user’s security information.

You can replace pretty much any aspect of Acegi with user-supplied code by implementing the appropriate interfaces, of course, so it’s likely to be suitable for a wide variety of projects just because any application-specific security needs can be accounted for by plugging in new code.

I was much happier with the course’s coverage of Acegi by the time Colin finished. I’m glad they did that extra presentation — it pretty much eliminated my one major substantive complaint about the course.

Actually, with that Acegi thing off the list, the only other major annoyance I had with the class was the other students. A couple of the people in front of me spent much of the lecture time browsing the web on their lab PCs, which, since I was behind them, meant lots of distracting animated ads pulling my attention away from the presentation. (Why you’d bother going to a course like this if you’re going to sit around reading used-car ads, I don’t know. Maybe they were forced to take it by their bosses. ) I spent a lot of the lecture leaned way back in my chair so the monitor next to me blocked my view of the offending students’ screens.

The other complaint I have, though there’s really nothing the instructors could have done about it, is that the labs took too long for some people to finish. A couple of us usually finished in a quarter to a third as much time as the slowest people took. I sure would not have complained if two of the students in particular had decided to play hooky — we could have had several additional hours of discussion/lecture time over the course of the four days, or, better still, more challenging lab assignments. (That one of the slow people was also one of the web browsers made it even more annoying — gee, guy, maybe if you’d paid attention to the presentation you wouldn’t be so lost!) But like I said, I don’t fault the instructors for that; up to a certain point you just have to teach the students you’ve got.

One nice thing about this course was that since we were dealing with open-source tools, Keith was able to hop directly to the source code for a lot of the stuff he was telling us about, so we could see exactly how it all worked. (Spring’s source code is very well documented internally, too!) I appreciated that, and it’s something you wouldn’t get from, say, a BEA training course.

All in all, I found the course very informative, and I will be able to immediately apply a bunch of what I learned. Well worth the time and money and I’m glad I went!

Leave a Reply