@Configuration not working as expected

Hi!
Sorry to disturb you, but I have a problem I can’t solve.
Maybe you can give me a tipp.
I prepared a Servlet with your class „ru.xpoft.vaadin.SpringVaadinServlet“:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
    <display-name>Vaadin Widget Test Application</display-name>
    <!-- Spring -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>
    <!-- Vaadin servlet -->
    <servlet>
        <servlet-name>Vaadin Sample Application</servlet-name>
        <servlet-class>ru.xpoft.vaadin.SpringVaadinServlet</servlet-class>
        <init-param>
            <param-name>beanName</param-name>
            <param-value>testvaadinUI</param-value>
        </init-param>
        <init-param>
            <param-name>systemMessagesBeanName</param-name>
            <param-value>DEFAULT</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Vaadin Sample Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Vaadin Sample Application</servlet-name>
        <url-pattern>/VAADIN/*</url-pattern>
    </servlet-mapping>
    <context-param>
        <description>Vaadin production mode</description>
        <param-name>productionMode</param-name>
        <param-value>false</param-value>
    </context-param>
</web-app>

and the following root-context:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
    <context:annotation-config />
    <context:component-scan base-package="com.example.testvaadin" />    
    <import resource="classpath:/my-context.xml" />    
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:/locales/messages" />
        <!-- Do not use System Locale file as default. Windows & Linux could have 
            different default locale -->
        <property name="fallbackToSystemLocale" value="false" />
    </bean>
    <bean class="ru.xpoft.vaadin.VaadinMessageSource" />
</beans>

As you can see, I’m importing a context from another Project ("classpath:/my-context.xml“).
my-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <context:component-scan base-package="de.thilker" />
</beans>

In the Project exists a @Configuration-Class called ConfigExample3:

package de.thilker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConfigExample3 {
    @Bean
    public User3 getUser() {
        System.out.println("GET_USER3");
        return new User3();
    }
}

When I start the tomcat-server I got an exception:

Feb 20, 2015 1:25:53 PM org.apache.catalina.core.StandardContext listenerStart
SCHWERWIEGEND: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: Cannot load configuration class: de.thilker.ConfigExample3
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:395)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:259)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:126)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4710)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5135)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: class de.thilker.ConfigExample3$$EnhancerBySpringCGLIB$$54c1dfc0 is not an enhanced class
    at org.springframework.cglib.proxy.Enhancer.setCallbacksHelper(Enhancer.java:621)
    at org.springframework.cglib.proxy.Enhancer.registerStaticCallbacks(Enhancer.java:594)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:131)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:100)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:385)
    ... 17 more

The Class ConfigExample3 is not being enhanced.
So the whole App is not working.
Do you know a solution, or the reason?

BTW:
When I run my classes via JUnit-Test everything works:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/my-context.xml" })

I tried many things.
For example, loading the context directly in the web.xml:

   <!-- Spring -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml,
        classpath:/my-context.xml</param-value>
    </context-param>

Same result.
Can’t imagine that it should be impossible to use @Configuartion in a multimodule/multi-jar environment.
Would be interesting what you think.
Many thanks in advance!
Thorsten

PS If you need more infos or source code, don’t hesitate to ask.

Is there a reason you are mixing XML-based and annotation-based Spring configuration?

We have a (working) multi-module project that is purely annotation-based, and multiple modules have their own configuaration classes so that solution is definitely not impossible.

Spring will scan classpath for classes implementing org.springframework.web.WebApplicationInitializer. In you initialization class you can have for example

@Override public void onStartup(final ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.setConfigLocation("de.thilker"); servletContext.addListener(new ContextLoaderListener(appContext)); servletContext.addListener(new RequestContextListener()); } After that Spring will scan package de.thilker for classes annotated with @Configuration which can reside in any module as long as they are in the same package. Of course you can define several config locations, or even use several WebappInitializer classes.

An example configuration class:

[code]
package de.thilker;

@Configuration
@ComponentScan(basePackages = “com.example.testvaadin”)
@Profile({“!test”})
public class MyConfiguration {

/**
 * @return
 */
@Bean
public User3 user() {
    System.out.println("GET_USER3");
    return new User3();
}

/**
 * @return
 */
@Bean
public MessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename("classpath:locales/messages");
    messageSource.setFallbackToSystemLocale(false);
    return messageSource;
}

}
[/code]As you can see that class is annotated with @Profile which is very handy when defining separate configuration classes for different environments.

In your test class you can have

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @ActiveProfiles({"test"}) public class MyTest { } The test will not be configured with the previous configuration class due to @ActiveProfiles annotation value.