An Autowired handler for Spring MVC

Disclaimer: I’m no Java expert. This is my first commercial project in Java, but I thought that this was so useful I had to share.

To the best of my knowledge Spring MVC resolves arguments to request handlers (@Controller methods annotated with @RequestMapping) using what is essentially a large switch statement based on type/argument-name, etc. When it encounters one of our own beans it will make a best attempt and instantiate for us a new instance using the default constructor (if present!). This article does an excellent job of explaining the internals.

This poses a problem when we want resolve an object either a) without a default constructor or b) with a graph of Spring IoC dependencies (@Autowired fields, etc). After searching for a while I came across one article explaining why this was a good idea and how it would look in practice, but alas no code… however it looked too good to pass-up, so with the help of this article I implemented a customer web argument resolver with accompanying annotation. Here is the class:

public class AutowiredHandlerAnnotationArgumentResolver extends WebApplicationObjectSupport implements HandlerMethodArgumentResolver {

 @Override
 public boolean supportsParameter(MethodParameter paramMethodParameter) {
  return contains(paramMethodParameter.getParameterAnnotations(), AutowiredHandler.class);
 }

 private boolean contains(Annotation[] parameterAnnotations, Class<AutowiredHandler> clazz) {
  for (Annotation annotation : parameterAnnotations) {
   if (clazz.isInstance(annotation)) {
    return true;
   }
  }
  return false;
 }

 @Override
 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
    NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
  WebApplicationContext ctx = getWebApplicationContext();
  return ctx.getBean(parameter.getParameterType());
 }
}

And here the annotation:

@Target(java.lang.annotation.ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutowiredHandler {
}

You will of course need to import all the correct packages, as they were omitted for brevity (otherwise we’d be here all night). Once they’re in place you simply register the argument resolver under the mvc:annotation-driven node of dispatcher-servlet.xml:

<mvc:annotation-driven>
 <mvc:argument-resolvers>
  <bean
  class="co.uk.package.AutowiredHandlerAnnotationArgumentResolver" />
 </mvc:argument-resolvers>
</mvc:annotation-driven>

… although part of me wishes you didn’t have to register anything anywhere, but there you go. After paying homage to the Spring XML gods you have all the power of the IoC dependency resolution framework simply by annotating an argument with the AutowiredHandler:

@RequestMapping(value = { "/exit", "/logout" }, method = RequestMethod.GET)
public String ourHelloWorldHandler(@AutowiredHandler HelloWorldService service, Model model,
 HttpSession session) {
 // use service...
}

The development effort essentially resolved around finding the right base class in order to get easy access to IoC (via inherited getApplicationContext), reflecting to find the annotation and implementing the correct interface. Simples.

We frequently use it for resolving classes that have their own dependency tree that are only required for the handler method in question. I hope it proves useful to others out there.

C

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s