This is a followup question of Spring + Jackson + joda time: how to specify the serialization/deserialization format?.
When I was writing the final version of the code, for the first time I wrote it as follows: (only relevant portion is shown)
@Configuration
public class WebMvcConfiguration
{
@Bean
public WebMvcConfigurerAdapter apiWebMvcConfiguration()
{
return new ApiWebMvcConfiguration();
}
public class ApiWebMvcConfiguration extends WebMvcConfigurerAdapter
{
public ApiWebMvcConfiguration()
{
log.debug("### ApiWebMvcConfiguration");
}
@Bean
public UserInterceptor userInterceptor()
{
return new UserInterceptor(false);
}
@Override
public void addInterceptors(InterceptorRegistry registry)
{
log.debug("### addInterceptors");
registry.addInterceptor(userInterceptor())
.addPathPatterns("/api/user/**");
}
}
private static final Log log =
LogFactory.getLog(WebMvcConfiguration.class);
}
There is no @EnableWebMvc, since the default @EnableWebMvc class of Spring Boot is used.
Notice that userInterceptor bean is in the WebMvcConfigurerAdapter class, which is also a bean.
When I've run the application, following error occured:
(class pathnames of my classes were replaced to '...' by myself)
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...WebMvcConfiguration$ApiWebMvcConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [...WebMvcConfiguration$ApiWebMvcConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1021)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:609)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at ...Application.main(Application.java:17)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [...WebMvcConfiguration$ApiWebMvcConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
... 14 more
Caused by: java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
at java.lang.Class.getConstructor0(Class.java:2810)
at java.lang.Class.getDeclaredConstructor(Class.java:2053)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
... 15 more
Then I changed ApiWebMvcConfiguration class to a static inner class.
Application was started 'normally', but ApiWebMvcConfiguration class was instantiated twice. That is, "### ApiWebMvcConfiguration" was printed twice. And accordingly, "### addInterceptors" was printed twice.
Then, when UserIntercepter's code ran, it failed because of null @Autowired JdbcTemplate. That is, @Autowired was not working for the object. (JdbcTemplate was successfully @Autowired in other objects)
So, I changed the code to the final version as shown in Spring + Jackson + joda time: how to specify the serialization/deserialization format?, that is, UserIntercepter bean was pulled out of ApiWebMvcConfiguration, the problem was gone.
Is this correct behaviour?
Should @Bean not be nested?