Andrea Colleoni
Andrea Colleoni

Reputation: 6021

Spring Web Mvc configuration initialization

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

Answers (2)

Andrea Colleoni
Andrea Colleoni

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

Henry
Henry

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

Related Questions