Spring MVCのJson変換機能で@DateTimeFormatが無視される件の対処方法

以前に、Spring MVCJson変換機能について紹介しました。
Spring MVCでJSONデータを返すための手順 - 達人プログラマーを目指して
また、Springの型変換サービスについても以下で紹介しました。
SpringのJavaBeansアクセスAPIと型変換サービスは単独で利用しても利用価値が高いという事実 - 達人プログラマーを目指して
型変換では、@DateTimeFormatや@NumberFormatなどのアノテーションをBeanに付加することで、日付や数値のフォーマットが自動的に行われるようになっています。そうであれば、当然Json化する際にもこれらのアノテーションにより正しくフォーマットがされると期待してしまうのですが、現状Spring3.0.xでは
MappingJacksonHttpMessageConverter's ObjectMapper does not use ConversionService when binding JSON to JavaBean properties [SPR-6731] · Issue #11397 · spring-projects/spring-framework · GitHub
のバグがあり、Json化の際にこれらのアノテーションに従って正しくフォーマットしてくれません。Json化の日付フォーマットに関しては、Json化で内部的に利用しているJacksonというライブラリーの設定をすることで一応対処することもできます。
http://wiki.fasterxml.com/JacksonFAQDateHandling
http://wiki.fasterxml.com/JacksonFAQ#Custom_Serializers
しかし、せっかくSpring自身に型変換のしくみがあるのに、別々に設定しなくてはならないのはかなりいまいちです。この問題については、次のSpring3.1では修正される予定のようですが、とりあえず、暫定の対処方法を考えてみました。
まず、独自拡張された変換機能を動作させるために、以下の拡張クラスを作成します。*1

package com.github.ryoasai.springmvc.json;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.core.convert.ConversionService;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;

public class ExMappingJacksonHttpMessageConverter extends MappingJacksonHttpMessageConverter {

	private ConversionService conversionService;

	public ConversionService getConversionService() {
		return conversionService;
	}

	@Inject
	public void setConversionService(ConversionService conversionService) {
		this.conversionService = conversionService;
	}

	@PostConstruct
	public void init() {
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setSerializerFactory(
				new ConversionServiceSerializerFactory(conversionService));


		setObjectMapper(objectMapper);
	}
}

このクラスではConversionServiceの変換機能を呼び出すため独自のConversionServiceSerializerFactoryをJacksonのObjectMapperに設定しています。なお、Jackson自体はオブジェクト指向設計開放閉鎖原則の観点からは、かなり拡張が困難な設計となっていたため、ちょっと苦労したのですが、一応動作する例については以下を参照してください。
spring-mvc-exts/spring-mvc-exts at master · ryoasai/spring-mvc-exts · GitHub
あとは、以上のExMappingJacksonHttpMessageConverterをSpring MVCから使えるようにxmlの設定ファイルを以下のように記述します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc">

    <!-- Scans the classpath of this application for @Components to deploy as 
		beans -->
    <context:component-scan base-package="com.github.ryoasai.springmvc.example" />

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
	    <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
                <bean class="org.springframework.http.converter.ResourceHttpMessageConverter" />
                <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" />
                <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
                <ref bean="mappingJacksonHttpMessageConverter" />
	    </list>
        </property>
        <property name="webBindingInitializer">
            <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
                <property name="conversionService" ref="conversionService" />
                <property name="validator" ref="validator" />
            </bean>
        </property>
    </bean>

    <!-- @Controller の設定をします。 -->
    <!-- Configures the @Controller programming model -->
    <mvc:annotation-driven conversion-service="conversionService"/>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
    <bean id="conversionService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        
    </bean>
 
    <bean id="mappingJacksonHttpMessageConverter" class="com.github.ryoasai.springmvc.json.ExMappingJacksonHttpMessageConverter" />

    
    <!-- Configures the @Controller programming model -->
    <mvc:annotation-driven />

...
</beans>

これは独自の変換処理を追加するために、AnnotationMethodHandlerAdapterの宣言をしているのですが、単に独自のMessageConverterに差し替えるだけでで自動設定されるほとんどのBeanを明示的に宣言する必要があってかなり面倒です。これもSpring3.1では、以下のようにの子供のタグで追加のコンバーターが記述できるように改良される予定です。
Make it easier to add new Message Converters to AnnotationMethodHandlerAdapter [SPR-7504] · Issue #12161 · spring-projects/spring-framework · GitHub

*1:まだ、試していませんが、Keith Donald氏の方法だとBeanPostProcessorを使って初期化しています。こちらのほうが賢かったかもしれません。https://src.springframework.org/svn/spring-samples/mvc-ajax/trunk/