javaspringspring-mvcautowired

Can not assign ServletContext spring 3


I am trying to use servletcontext.getRealPath in my Util class to load a file resource (Not part of unit testing) but it does not work.

I tried both to use "implements ServletContextAware":

@Component
public class Utils implements ServletContextAware{
    private ServletContext servletContext;

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;

        System.out.println("**** "+servletContext);
    }
}

Which throws NPE since servletcontext is not assigned by spring.

And the @Autowired route:

@Component
public class Utils{

    @Autowired
    private ServletContext servletContext;

Which throws NoSuchBeanDefinitionException when tomcat is being starting:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.servlet.ServletContext] found for dependency: expected at le
ast 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

I am adding the my initialization code in case I am doing something wrong which prevents Spring to inject the right bean.

public class WebAppInitializer implements WebApplicationInitializer {

    private static Logger LOG = LoggerFactory.getLogger(WebAppInitializer.class);

    @Override
    public void onStartup(ServletContext servletContext) {
        WebApplicationContext rootContext = createRootContext(servletContext);

        configureSpringMvc(servletContext, rootContext);

        FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", CORSFilter.class);
        corsFilter.addMappingForUrlPatterns(null, false, "/*");

//        configureSpringSecurity(servletContext, rootContext);
    }

    private WebApplicationContext createRootContext(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();

//        rootContext.register(CoreConfig.class, SecurityConfig.class);
        rootContext.register(CoreConfig.class);
        rootContext.refresh();

        servletContext.addListener(new ContextLoaderListener(rootContext));
        servletContext.setInitParameter("defaultHtmlEscape", "true");

        return rootContext;
    }

CoreConfig.class:

@Configuration
public class CoreConfig {

    @Bean
    public CaptionFixture createCaptionFixture() {
        return new CaptionFixture();
    }

    @Bean
    public Utils createUtils () {
        return new Utils();
    }
}

Utils is the class with the servlet context.

I have looked at the suggested answers: here and here and it didnt work.


Solution

  • The issue is that you are calling refresh() without a ServletContext being registered, so none is available when the beans are initialized.

    Get rid of this call

    rootContext.refresh();
    

    The ContextLoaderListener will take care of calling refresh(). The constructor javadoc explains what happens when the ApplicationContext passed as an argument isn't refreshed:

    If the context has already been refreshed or does not implement ConfigurableWebApplicationContext, none of the above will occur under the assumption that the user has performed these actions (or not) per his or her specific needs.