Search code examples
mavenspring-roomaven-failsafe-pluginload-time-weavingintegration-testing

Roo and Failsafe integration tests: BeanConfigurerSupport issue


case: Roo application with integration tests autoganerated.

need: use PGSQL for deployment, HSQLDB for integration tests.

choice: spring-agent/spring-instrument & aspectjweaver in argLine in maven-failsafe-plugin configuration so as not to be coupled to a certain tomcat installation (which should have the required jars and Context configuration)

result:

BeanConfigurerSupport - BeanFactory has not been set on BeanConfigurerSupport: Make sure this configurer runs in a Spring container. Unable to configure bean of type [com.model.UserIntegrationTest]. Proceeding without injection.

I noticed that it uses classloader: WebappClassLoader

I tried also with the approach of changing the tomcat configuration and adding the required jars in it's libs but I couldn't make failsafe plugin collaborate with the remote tomcat.

Any idea?

Following are code snippets related to the issue. The easiest way to have a SSCCE is to get a spring roo example and try to execute the *IntegrationTest roo generated as integration tests with failsafe against a hsqldb for testing and some other db for deploy.

Part of pom.xml:

<properties>
    ...........
    <aspectj.version>1.8.2</aspectj.version>
<properties>

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.7</version>
    <configuration>
        <outxml>true</outxml>
        <complianceLevel>1.7</complianceLevel>
        <source>1.7</source>
        <target>1.7</target>
        <weaveWithAspectsInMainSourceFolder>true</weaveWithAspectsInMainSourceFolder>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <phase>process-sources</phase>
            <goals>
                <goal>compile</goal>
                <!-- use this goal to weave all your main classes -->
                <goal>test-compile</goal>
                <!-- use this goal to weave all your test classes -->
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.17</version>
    <configuration>
        <junitArtifactName>org.junit:com.springsource.org.junit</junitArtifactName>
        <!--see: https://issuetracker.springsource.com/browse/EBR-220-->
        <printSummary>false</printSummary>
        <redirectTestOutputToFile>true</redirectTestOutputToFile>
        <excludes>
            <exclude>${roo.aspect.test.files}</exclude>
            <exclude>${integration.test.files}</exclude>
        </excludes>
        <reuseForks>false</reuseForks>
        <forkCount>1</forkCount>
        <argLine>-javaagent:${settings.localRepository}/org/springframework/spring-agent/2.5.6.SEC03/spring-agent-2.5.6.SEC03.jar -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar -javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar</argLine>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.17</version>
    <configuration>
        <systemPropertyVariables>
            <integration-test.url>http://localhost:8080/${project.build.finalName}/</integration-test.url>
        </systemPropertyVariables>
        <junitArtifactName>org.junit:com.springsource.org.junit</junitArtifactName>
        <includes>
            <include>${integration.test.files}</include>
        </includes>
        <excludes>
            <exclude>${roo.aspect.test.files}</exclude>
        </excludes>
        <reuseForks>false</reuseForks>
        <forkCount>1</forkCount>
        <argLine>-javaagent:${settings.localRepository}/org/springframework/spring-agent/2.5.6.SEC03/spring-agent-2.5.6.SEC03.jar -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar -javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar</argLine>
    </configuration>
    <executions>
        <execution>
            <id>integration-test</id>
            <goals>
                <goal>integration-test</goal>
            </goals>
        </execution>
        <execution>
            <id>verify</id>
            <goals>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <url>${server.url}/manager/text</url>
        <server>TomcatServer</server>
        <path>/${project.name}</path>
    </configuration>
    <executions>
        <execution>
            <id>start-tomcat</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <configuration>
                <fork>true</fork>
            </configuration>
        </execution>
        <execution>
            <id>stop-tomcat</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>shutdown</goal>
            </goals>
        </execution>
    </executions>
</plugin> 

Part of applicationContext.xml where is defined the profile for IT:

<beans profile="integrationTests">

     <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
        id="itdataSource"> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:ittests;shutdown=true"/> <property
        name="username" value="sa"/> <property name="password" value=""/> <property
        name="testOnBorrow" value="true"/> <property name="testOnReturn" value="true"/>
        <property name="testWhileIdle" value="true"/> <property name="timeBetweenEvictionRunsMillis"
        value="1800000"/> <property name="numTestsPerEvictionRun" value="3"/> <property
        name="minEvictableIdleTimeMillis" value="1800000"/> </bean>

    <!--<jdbc:embedded-database id="itdataSource" type="HSQL" />-->
    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnitForIntegrationTests" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="HSQL" />
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="dataSource" ref="itdataSource" />
    </bean>
</beans>     

After updating the aspectj-maven-plugin to 1.7, instead of the messages I posted initially, I'm getting

[WARNING] advice defined in org.springframework.mock.staticmock.AbstractMethodMockingControl has not been applied [Xlint:adviceDidNotMatch]
    C:\Users\ckorakidis\.m2\repository\org\springframework\spring-aspects\3.2.6.RELEASE\spring-aspects-3.2.6.RELEASE.jar!org\springframework\mock\staticmock\AbstractMethodMockingControl.class:167

.......

[WARNING] this affected type is not exposed to the weaver: com.mbplc.cborms.db.UserRepository [Xlint:typeNotExposedToWeaver]
C:\workspace\poc\com\db\UserRepository_Roo_Jpa_Repository.aj:16

.....

[AppClassLoader@3972aa3f] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
2014-09-16 23:35:33,389 [main] DEBUG org.springframework.beans.factory.wiring.BeanConfigurerSupport - BeanFactory has not been set on BeanConfigurerSupport: Make sure this configurer runs in a Spring container. Unable to configure bean of type [com.model.UserIntegrationTest]. Proceeding without injection.

......

    classloader: WebappClassLoader
  context: /poc
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
ClassRealm[plugin>org.apache.tomcat.maven:tomcat7-maven-plugin:2.2, parent: sun.misc.Launcher$AppClassLoader@65450f1f]

    excludeUnlistedClasses: false
    JTA datasource: null
    Non JTA datasource: org.apache.commons.dbcp.BasicDataSource@70a3b90
    Transaction type: RESOURCE_LOCAL

Solution

  • I found a similar problem when I try to use Spring profiles in a Roo project.

    If you really need to run test with other DB config, What about to use Maven profiles isntead?

    By example:

    1. Modify you applicationContext.xml to create BasicDataSource using database.properties values (and remove the profile tag)
    2. Declare two maven profiles on pom.xml: one for test and another with final DB configuration.
    3. Configure resources tag on pom.xml to filter database.properties
    4. Modify database.properties and set values to pom properties

    This way, you can run integration test with HSQLB using the test profile and the other profile to package/run your application with the real DB without use Spring profiles.

    Good luck!