Monday, July 9, 2012

Introducing Pathfinder

I've been on a new assignment for the last couple of months, located in Center City Philadelphia. On the one hand, the commute is great: I can walk to the local train station, and have a quiet 25 minutes to read or work on the train. On the other hand, orienting my morning around the train schedule has thrown a monkey wrench into my blog posts. I have a dozen or more half-written ideas waiting to be cleaned up and published. I never realized how much post-production I normally do: adding links, tweaking the HTML once it's on Blogger, and whatnot. Did I mention that Septa doesn't have wifi on their trains? (score another point for Boston)

Instead, I've been working on Pathfinder, a tool to examine Java web apps and tell you the URLs that they handle. It was inspired by rake routes, a tool from the Ruby/Rails world. My current job has me enhancing legacy web-apps, and I think that knowing the classes associated with a URL is a good way to start learning a codebase. If I just had to deal with Spring, I could rely on STS; my goal for Pathfinder is to (eventually) handle all web frameworks, obsolete or not.

It's got a way to go. Right now it handles servlets, JSPs, and Spring apps, and the latter must use either SimpleUrlHandlerMapping or a component scan with @RequestMapping. But I think the basic design is solid and extensible, and will be updating it as I run into things that it can't handle.

I've learned an enormous amount about Spring while developing it. For a framework that espouses convention over configuration, I needed to handle an enormous number of special cases. For example, there are at least two default locations where you can save your Spring context files. And did you know that @RequestMapping actually takes an array of URLs?

Speaking of which, I also learned a lot about how annotations are stored in the classfile. It's easy to use reflection to access annotations on classes that are already loaded. But because of some code that I'd seen in a legacy Spring app, I didn't want to actually load the web-app. No problem, I thought, there are a bunch of libraries that already exist for working with classfiles.

As it turned out, not so much. My old standby, BCEL, has some code in the trunk to deal with annotations. But its last released version — from 2006 — doesn't handle them; they're just an “unknown” attribute type. The “new hotness,” ASM, does support annotations, but you wish it didn't: you have to decipher each annotation using a big if-else chain filled with instanceof.

Which brings me to the second introduction of this post: BCELX. The name stands for “BCEL extensions,” and it's built on top of BCEL. Right now it just handles class and method annotations; I'll add parameter annotations when I need them. And it doesn't handle nested annotations — I can't find an example of a nested annotation to build a testcase.

BCELX may expand beyond annotation parsing: it seems that there's a need out there for a simple tree-structured view of a Java classfile, and all the existing libraries are on the visitor wagon. I just have to figure out how to schedule it into my 25 minutes of quiet time each morning.

No comments: