0

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?

Hoobajoob
  • 2,748
  • 3
  • 28
  • 33
  • First of all, make sure that the name of your configuration class is really `org.imaginary.spring.config.Instrumented`. – axtavt Dec 06 '13 at 17:51
  • Thank you - yes, I have verified that. The class is named Instrumented, and it is defined in the 'org.imaginary.spring.config' package. – Hoobajoob Dec 06 '13 at 17:53
  • @axtavt: any other suggestions? This is driving me kind of nuts. I can get this kind of configuration arrangement to work in a regular old application where I control the context creation, but I can't get this working in a web app setup. It seems pretty simple, so I must be missing something obvious. – Hoobajoob Dec 15 '13 at 16:32
  • 1
    Error message indicates that Spring was unable to load `org.imaginary.spring.config.Instrumented`. If class name is correct, it may be some kind of build process issue (class is not located in correct place) or classloading issue. – axtavt Dec 15 '13 at 17:02
  • I'd have thought there'd be a NoClassDefFound exception in that case, but I think you're right - I just tried changing the web.xml config to refer to a class that doesn't exist and I get the same error. Thank you for the tip - I'll try and track it down. – Hoobajoob Dec 15 '13 at 17:50
  • @axtavt: thanks, that was the issue – Hoobajoob Dec 15 '13 at 18:15

1 Answers1

4

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].

Hoobajoob
  • 2,748
  • 3
  • 28
  • 33