Andrea Colleoni Andrea Colleoni - 7 months ago 41
Java Question

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)}

Answer

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.

Comments