Sunday, June 30, 2013

Spring MVC - Migrating to Jackson 2

This does not really require a blog entry - migrating from Jackson 1.9.x to Jackson 2.x is extremely simple with Spring MVC 3.1+ based applications. The only thing that needs to be done is to replace the 1.9.x jar with Jackson 2.x jar, with the following new entry in a maven pom.xml file (assuming a maven project)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.2.0</version>
</dependency>

This is pretty remarkable considering the fact that the core Jackson package names have now been refactored from
"org.codehaus.jackson" to "com.fasterxml.jackson".


So how does this Spring MVC handle such migrations internally -

Spring MVC uses a component called a HttpMessageConverter as a strategy interface to convert the request body to an object representation, and to convert the response object representation to a serialized form to be sent back as a response.

Spring MVC registers a series of HttpMessageConverters to handle request bodies, this happens by default when the MVC is activated, typically using a xml Spring bean definition file this way:

<mvc:annotation-driven />

Or, when using new Java Config style of bean definition:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="mvcsample.web", 
 includeFilters=@Filter(type=FilterType.ANNOTATION, value=Controller.class))
public class WebConfig {

}


In both cases, a check for the presence of Jackson2 libraries is made by scanning for well-known classes within the jackson2 library:

private static final boolean jackson2Present =
  ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", aClassLoader) &&
    ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", aClassLoader);

and assuming Jackson 2.x libraries are present, an appropriate HttpMessageConverter is registered:

if (jackson2Present) {
 messageConverters.add(new MappingJackson2HttpMessageConverter());
}

If there happen to be both the 1.9.x jars and the 2.x jars of Jackson in the classpath, then preferentially the 2.x HttpMessageConverter is registered before the 1.9.x HttpMessageConverters.

This way Spring MVC seamlessly handles the upgrade of Jackson libraries

Wednesday, June 19, 2013

Spring MVC Error handling flow

There are broadly three ways of handling an exception flow using Spring MVC, the objective being to intercept any application exception and present a friendly and informative view back to the user.

1. Using error-page tag in web.xml file:

This is a servlet specs driven approach, where the exceptions that bubble up from the application are intercepted based on either the HTTP response code or the exception type and the handler for the exception is specified using the location sub-tag this way:

<error-page>
    <error-code>500</error-code>
    <location>/500</location>
</error-page>
<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/uncaughtException</location>
</error-page>

If it is a Spring MVC based app, and if the intent is for a Spring MVC view to present the message, then a location should ideally be a Spring controller which can show the content and this can be done for the 2 locations above purely using Spring MVC configuration:

<mvc:view-controller path="/500" view-name="500view"/>
<mvc:view-controller path="/uncaughtException" view-name="uncaughtexception"/>


2. Registering a HandlerExceptionResolver:


HandlerExceptionResolver(s) are responsible for mapping the exception to views, the simplest approach is to register a SimpleMappingExceptionResolver that can map exception types to view names. The following is a way to register SimpleMappingExceptionResolver using Spring xml bean definition(based on Roo samples):

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" p:defaultErrorView="uncaughtException">
 <property name="exceptionMappings">
  <props>
   <prop key=".DataAccessException">dataAccessFailure</prop>
   <prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
   <prop key=".TypeMismatchException">resourceNotFound</prop>
   <prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
  </props>
 </property>
</bean>

OR using Java Configuration based bean definition:

@Bean
public HandlerExceptionResolver handlerExceptionResolver() {
 SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
 exceptionResolver.setDefaultErrorView("uncaughtException");
 Properties mappings = new Properties();
 mappings.put(".DataAccessException", "dataAccessFailure");
 mappings.put(".NoSuchRequestHandlingMethodException", "resourceNotFound");
 mappings.put(".TypeMismatchException", "resourceNotFound");
 mappings.put(".MissingServletRequestParameterException", "resourceNotFound");
 exceptionResolver.setExceptionMappings(mappings );
 return exceptionResolver;
}


3. Using @ExceptionHandler

This is my preferred approach and there are two variations to using the @ExceptionHandler annotation.

In the first variation, @ExceptionHandler can be applied to the level of a controller class in which case the exceptions raised by the same controller @RequestMapped methods are handled by the @ExceptionHandler annotated methods.

@Controller
public class AController {
    @ExceptionHandler(IOException.class)
    public String handleIOException(IOException ex) {
      return "errorView";
    }
}

In the second variation of @ExceptionHandler, the annotation can be applied to ALL controller classes by annotating a method of @ControllerAdvice annotated class:

@ControllerAdvice
public class AControllerAdvice {
    @ExceptionHandler(IOException.class)
    public String handleIOException(IOException ex) {
      return "errorView";
    }
}


These essentially are the approaches to handling application exceptions in Spring MVC applications.

Monday, June 10, 2013

Google guava "live" transformation - forcing an eager transformation

One of the utility classes provided by Google Guava Library, Lists, has a utility method to transform lists of one type to another. The interesting feature of this transformation is that the transformation is "live", in the sense that any changes to the source list is visible in the destination list. This is done by doing the transformation only on demand by applying a transformation on request.

This is best shown with an example:

Account a1 = new Account(1, "business", "num1");
Account a2 = new Account(2, "business", "num2");
Account a3 = new Account(3, "business", "num3");

List<Account> list = Lists.newArrayList(a1, a2, a3);

List<Integer> ids = Lists.transform(list, new Function<Account, Integer>() {
 @Override 
 public Integer apply(Account input) {
  return input.getId();
 }
});

assertThat(ids, contains(1, 2, 3));

a2.setId(12);
assertThat(ids, contains(1, 12, 3));


Here a list of "Account"(s) is being transformed to a list of its corresponding ids. Any change in the id of the original objects is reflected in the transformed list.

Now, there are situations where an eager transformation may be desired - for eg. needing to cache the transformed list, or serializing the transformed list. The way to force an eager transformation is to make a copy of the lazy list, using another utility method provided by the Lists class:

Lists.newArrayList(ids)