Debug deep dive into doDispatch() in Spring MVC

I’ve been stuck at home with sick kids so I just decided to take a debugging deep dive into the doDispatch() method of Spring MVC’s dispatcher servlet (DispatchServlet, the so-called “front controller“). Since this is my blog and I get to write whatever I want no matter how trivial, I thought I’d share two impressions, each of which are informed by a lack of sleep.

One impression: is Spring’s strength also its weakness?

I think of Spring as coming of age in era of enterprise Java when many competing frameworks were trying to be all things to all people. Spring beat J2EE in some early battles because it successfully appealed to all audiences while not imposing too much heavyweight configuration for most enterprise developers, which probably comes as a surprise to new today’s new developers. These days, developers are either annoyed or intimidated by its flexibility.

Its flexibility remains awesome, however. As an application developer, you can customize a HandlerMapping object, HandlerAdapter, HandlerExceptionResolver, ViewResolver, LocaleResolver, LocaleContextResolver, ThemeResolver, MultipartResolver, and a FlashMapManager. Just take a look at the DispatchServlet itself. It invokes the strategy pattern to use stategy objects on nine major configuration options:

Some of this annoyance and intimidation (and of course, I get both annoyed and intimidated too) comes from Spring’s impenetrable naming scheme. In its pursuit of being all things to all web developers, something like HandlerAdapter is so vague that it’s meaningless the first time you see it. And that’s easy compared to something like DelegatingFilterProxy or SerlvetInvocableHandlerMethod (which is a class, BTW). Spring has precise, but intricate and opaque (to the average developer) naming conventions.

So I guess my point on this impression is that I wish there was something like Spring Lite MVC that didn’t make me think about all these configuration options; I’m thinking of a light implementation that simply let me write some @RequestMapping decorated classes and some JSPs and call it a day. If I want to go further, I will.

Maybe Spring Boot will cure my worries, but is it too “opinionated” to build a simple MVC-CRUD-based web app without learning what the Spring folks’ “opinion” is?

Second impression: is Spring’s flexibility leaving optimization on the table?

Obviously, flexibility implies (requires?) a performance trade off. And if you’ve worked with Spring MVC, you know that a big part of its power is its ability to resolve a web request to @RequestMapping annotations you’ve used to decorate your controllers–without having to write XML. What you might not realize is (a) how deep in the stack trace you are and (b) that Spring MVC performs as if it’s the first time it’s ever seen your application for every single request. The first problem comes from Spring’s verbosity and their designers’ OO elegance. I’ll defer that issue to them.

It seems to me that the second issue could be solved with a little real world caching though. In mapping a simple request, say to “/” from a web browser, Spring MVC goes through a fairly tortured and exhaustive reflection-informed search of all annotations of all your classes for the right @RequestMapping mapping to a given request — every time! While that might only be a few dozen or a few hundred loops in any given Spring MVC solution, it still seems wasteful to me. Wouldn’t a simple @Cacheable annotation fix this — at least in part? Of course, if I’ve overlooked something and I’m wrong on this point, please let me know!

IRC cheat sheet

I’ve been trying to spend more time on IRC because if feels like I’m close to the bare metal, even if I’m actually just helping some computer science student do his homework. However, I’m kind of embarrassed to say that I don’t remember all the IRC commands I used to know way back when. In fact, I’m a little disappointed that I didn’t find a let’s-get-back-to-internet-basics-and-off-the-proprietary-web-like-Twitter flight to IRC.

Since I unequivocally lack the time or the persona to spark any IRC 2.0 movements, here’s just a quick cheat sheet for the few moments I do have to be on IRC on any given day. I’m /michaelrice on Freenode, BTW; when I’m on, I’m always in the #java channel.

/join #<channel> – duh, even twenty years won’t let you forget that one.

/me <does something witty> – as in, “/me rolls his eyes” will show up as *michaelrice rolls his eyes

/ignore <nickname> – for that defamatory harasser that you can’t find a proper jurisdiction to initiate suit for or ask a judge for a TRO; yeah, that guy (or girl, but that’s not a problem I personally have out there on the net, especially on IRC, but I thought I should write it down just in case)

/msg NickServ IDENTIFY <password> – when you have a registered nick, like I do, you send your password to “login” with this command. Luckily, Freenode will remind you how to do this when you first logon:

nickserv-password

UPDATE: As I spent some time on the #freenode channel, I put this on Twitter:

real-internet-is-irc

Sometimes I think it’s the little things like this

… that contribute to people thinking that Java is your dad’s (or mom’s) language of choice. This is the link to subscribe to Java Magazine (trademark designation and all).

javamagazine-subscription

I.e., why would I have to say I want to subscribe when I clearly clicked on some call to action link that said, “Subscribe to Java Magazine.” I won’t even talk about the fact that the Oracle link provided by a YouTube video published yesterday has the wrong link. Or maybe I just did. Whatever.

Do you ever think that it’s time to take the Java VM and language out of Oracle and the JCP’s hands?

Big improvements coming to license-check

In looking at my old license-check project on Github, I’m embarrassed to say I haven’t done much in the last nine months. However, I’ve been working on some big improvements over the past few weeks. While the changes aren’t released into Maven Central yet, I think you’ll enjoy them when they are (probably under version 0.5.4).

For me, the biggest change is that the code is a lot more stable and much improved. My initial cut through the code was largely experimental as I thought through how to traverse the Aether dependencies for the license attribute and how to convert them into something readable. Now that I have a better grasp on how the whole process should work, I’m hardening the code and trying to make it a little more elegant (in my opinion, of course).

For you, I think you’re going to like the reporting from the plugin much better. Here’s an example report for a standard Spring MVC application connected to Mongo:

2014-03-18 license-check screen cap

I need to add some relatively complex unit testing related to Maven plugins as well as maybe some Guava enhancements before I release a new version. Still, I hope this piques your curiosity.

In case you ever need to host static content from CXF, try this before jumping off a bridge

For some odd reason, you may find that you really, really want to host some static content on your CXF server. Maybe you want to do something like host Swagger or IO Docs side by side with your REST API and you don’t feel like setting up a whole new service.

And if you’re like me, you’ve already shot yourself in the foot because you bound your RESTful service to the root of your Tomcat webapp. For example, your CXF servlet is bound to http://localhost:8080/petsore/* but you now want http://localhost:8080/petstore/docs/ to host your documentation, and CXF thinks your docs are an API endpoint.

You made your life complicated and set it up like this too, didn’t you?

And maybe you’ve tried to read the impenetrable documentation on the Apache CXF site with its maddening language about servlet initialization params relating to “redirects.” I debugged deep into the CXF sourcecode to figure what’s really going on. You need to start with CXF’s AbstractHTTPServlet.java.

Now that I’ve said all that, let me get to the bottom line. All you really need to do is make sure you’ve added two initialization params to your web.xml:

In my configuration, I had the Swagger docs under the src/main/webapps folder in my Maven project, so your mileage may vary depending on your configuration.

Good luck out there.