Reputation: 6021
I'm trying to configure a stack of libraries through spring java @Configuration
.
On one of the tops of all I have a Spring Web Mvc application.
To configure the application I used an extension of the AbstractAnnotationConfigDispatcherServletInitializer
; from there I referenced another @Configuration
class for the underlying layers in the getRootConfigClasses()
method and, for the servlet container, I used the getServletConfigClasses()
method to reference an extension of the WebMvcConfigurationSupport
.
All works well (the web MVC part) until I need some beans from the underlying layers from classes instantiated at the WebMvcConfigurationSupport
level (interceptors, and so on); In those classes all the references to beans that should be initialized in the underlying layers (that are classes annotated with @Component
) with the @Autowired
annotation give me null
.
In another application on top of the same stack of layers (a service layer without MVC) all is working good.
Any suggestions?
EDIT
If I load a bean (via the @Bean annotation) from the root configuration class autowiring works.
If I load a bean (via the @Bean annotation) from the servlet (WebMvc) configuration class autowiring doesn't work.
It seems they're two different Spring contexts.
SOME CODE
The interceptor
package my.package.interceptor;
@Component
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {...}
The root config
package my.package;
@Configuration
@ComponentScan(
basePackageClasses={ UnderlyingLayersSpringConfiguration.class },
basePackages = {"my.package.interceptor"}
)
public class WebSpringConfiguration {...}
The MVC config
package my.package;
@Configuration
@EnableWebMvc
@ComponentScan(
basePackageClasses = WebSpringConfiguration.class,
basePackages = {"my.package.interceptor"},
includeFilters = @Filter(Controller.class) ,
useDefaultFilters = false
)
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private AuthenticationInterceptor authenticationInterceptor;
}
The web app initializer: 2 versions
Version 1
package my.package;
public class WebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer
implements WebApplicationInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { WebSpringConfiguration.class, WebMvcConfig.class };
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
}
Version 2
package my.package;
public class WebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer
implements WebApplicationInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { WebSpringConfiguration.class };
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebMvcConfig.class };
}
}
The error
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [my.package.interceptor.AuthenticationInterceptor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Upvotes: 0
Views: 2839
Reputation: 6021
I found the issue and I report the answer here, for future memory and to allow others to check this aspect of spring configurations when having the same problem.
The underlying layer's beans inherit from a structure of classes where spring @Profile
was used.
I was unable to load beans because on the topmost project I didn't specify a @Profile
, so no profile, no beans.
Quite simple, the time one considers it.
Hope this can help someone.
Upvotes: 1
Reputation: 43728
The root context and dispatcher servlet context are indeed two different contexts. The root context is the parent of the servlet context.
You probably did not specify the @ComponentScan
annotation on the class configuring the servlet context.
Upvotes: 0