Question

I am having a problem where the Spring WebApplicationContext appears to be ignoring the @Import annotation on a @Configuration-annotated config class in my web app. It is not a Spring MVC web app.

The problem occurs during processing of the contextInitialized event of a custom ServletContextListener which used to be able to successfully retrieve this bean when I was using XML configuration, but is now not finding this bean now that I have (apparently incorrectly) converted to the use of @Configuration-annotated classes.

The symptoms I see are:

  • During app startup, I see this output from the Spring framework:

INFO: No annotated classes found for specified class/package [org.imaginary.spring.config.Instrumented]

  • Later, when my contextInitialized() method is invoked and I call getBean(), I get a NoSuchBeanDefinition exception

My config classes are factored in such a way that I have, for example, two high-level config classes, one for a "Production" configuration, and another for an "Instrumented" configuration. These top-level config classes are themselves completely empty, but they make use the @Import annotation to (I'm hoping) bring in the relevant bean definitions for that kind of configuration.

For example, here is the Instrumented configuration class:

package org.imaginary.spring.config;

import org.imaginary.spring.config.instrumentation.InstrumentationDependencies;
import org.imaginary.spring.config.servlets.ServletDependencies;

@Configuration
@Import( {InstrumentationDependencies.class, ServletDependencies.class } )
public class Instrumented
{
}

...for the purposes of this example, here is the InstrumentationDependencies config class, defined in a different package:

package org.imaginary.spring.config.instrumentation;

@Configuration
public class InstrumentationDependencies
{
    @Bean
    public IEventSink eventSinkImpl()
    {
        return new InstrumentationEventSinkImpl();
    }
}

Here is (a stripped-down version of) the contextInitialized() method:

@Override
public void contextInitialized( ServletContextEvent ctxEvent )
{
    try
    {
        if (_publisher == null)
        {
            WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(ctxEvent.getServletContext());
            _eventSink = (IEventSink)springContext.getBean("eventSinkImpl");               
        }

        _eventSink.startReceiving();
    }
    catch ( Exception e )
    {
        // handle exception
    }
}

Here are the relevant entries from my web.xml:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
</context-param>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>org.imaginary.spring.config.Instrumented</param-value>
</context-param>

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
        <listener-class>org.imaginary.MyContextListener</listener-class>
</listener>

Any ideas what I have missed?

No correct solution

OTHER TIPS

In this case, there is nothing wrong with the Spring configuration classes or configuration. The problem was in fact a build issue - the config classes had been added to a package that wasn't getting included in the main web app jar, so the class files weren't present. I was surprised that there wasn't a NoClassDefFoundError exception thrown, as this error leaves the impression that the class exists, it just isn't annotated:

No annotated classes found for specified class/package [your.class.here].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top