To externalize data binding initialization, you can provide a custom implementation of theEncouraged by this citation I registered my own bean along the usual <mvc:annotation-driven />WebBindingInitializer
interface, which you then enable by supplying a custom bean configuration for anAnnotationMethodHandlerAdapter
, thus overriding the default configuration.
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer" ref="MyWebBindingInitializer" />
</bean>
<bean class="[...].DefultWebBindingInitializer" id="MyWebBindingInitializer" />
At this point I've encountered first problem - the order of beans registration matters in the above case - first registered handler will be used. This is reasonable, one AnnotationMethodHandlerAdapter is registered by Spring while processing <mvc:annotation-driven /> and one by me. First registered wins :)I've moved my bean before <mvc:annotation-driven /> and started enjoying its work. After few days I was preparing some functionality returning one value from the handler method, which should be converted automagically to JSON response (see my posts: JSON - Jackson to the rescue and JSON - Jackson Serialization Narrowed). To my surprise, usual configuration didn't worked, I started digging through my own and Spring Framework code, and found the reason (which in fact can be also deduced from mvc:annotation-driven documentation) - my own bean didn't registered the same message converters as parser responsible for processing mvc:annotation-driven (AnnotationDrivenBeanDefinitionParser) and especially one needed by me: MappingJacksonHttpMessageConverter.
At this point I had few possibilities to solve this problem, I could for example register appropriate message converter myself, but I decided to go a different way, because solving the problems generated ourselves, is worse than avoiding those problems :)
I've prepared BeanPostProcessor implementation correcting the one property required by me:
public class MVCConfigurationPostProcessor implements BeanPostProcessor {
private WebBindingInitializer webBindingInitializer;
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AnnotationMethodHandlerAdapter) {
((AnnotationMethodHandlerAdapter) bean).setWebBindingInitializer(webBindingInitializer);
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) {
this.webBindingInitializer = webBindingInitializer;
}
}
Then I've corrected my Spring configuration to:<bean class="[...].MVCConfigurationPostProcessor">
<property name="webBindingInitializer" ref="MyWebBindingInitializer" />
</bean>
<bean id="MyWebBindingInitializer" class="[...].DefultWebBindingInitializer" />
<mvc:annotation-driven />
Finally I was able to enjoy both AnnotationMethodHandlerAdapter using my own WebBindingInitializer and JSON conversion working correctly :).
Oh, so you have blog...
ReplyDeleteBTW, you may want to have a look at flexjson, I really like it: http://flexjson.sourceforge.net/
Cheers,
Blog is definitely too big word ;) I heard that people write their Blogs for the Fortune and Glory ;) - I don't think this blog will bring me Fortune, maybe at least a little bit of Glory ;) - I rather treat it like a bunch of yellow cards, on which I can write my thoughts ;)
ReplyDeleteThanks for the FlexJSON link, have you used it with the Spring Framework maybe?
greetings for you, and Prozz, if he is still somewhere around :)
Another work around is to give assign your custom handler with an order property of a lower value i.e higher property than the one registered by the .
ReplyDeleteThe DispatcherServlet picks your handler first. The order of beans in the config file matters when they have the same priority
Similar if not same problems still exist in Spring MVC 4 :(
ReplyDelete