Announcement Announcement Module
Collapse
No announcement yet.
Overriding bean definition for bean 'dataSource' Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Overriding bean definition for bean 'dataSource'

    I'd like to be able to unit test my database during build. For this I have chosen the H2 database, as this should support DB2, which I'm currently using in production.

    But I run into this error when running my tests:
    Code:
    30-04-2012 09:28:57 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
    30-04-2012 09:28:57 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
    INFO: Overriding bean definition for bean 'dataSource': replacing [Generic bean: class [org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext.xml]] with [Root bean: class [org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
    ...
    All of my tests are fine and they should work with my H2 database as you'll see below (which is loaded later, this is the first logged in the console). As seen it loads applicationContext.xml, then it overrides the "dataSource" bean, which is defined as:
    Code:
    <bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    	<constructor-arg>
    		<bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    			<property name="driverClass" value="org.h2.Driver" />
    			<property name="url" value="jdbc:h2:mem:salgdb;MODE=DB2;DB_CLOSE_DELAY=-1" />
    		</bean>
    	</constructor-arg>
    </bean>
    If I debug (e.g. through Eclipse) I can see that the url is substituted with "jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1", and I guess this is done by Spring when it overrides my "dataSource" bean.

    If I create a break point and append ";MODE=DB2" (as defined by H2) all of my tests execute as expected (I use some DB2 specific SQL which doesn't work with the normal H2 base).



    So, how do I fix this? Any ideas? E.g. why does it substitute the data source?

    Here is my test, and as you can see I only load one application context:
    Code:
    ... //imports
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:applicationContext.xml"})
    public class AdvisorServiceDaoImplTest extends AbstractTransactionalJUnit4SpringContextTests {
    
        ...//setup
    
        @Test
        public void getAdvisor() throws Exception {
            //call db2 specific sql method
    		assertEquals("1234567890", (advisorServiceDao.getAdvisor("123").getSsn()));
        }
    }

  • #2
    Depending on the spring version I would simply factor out the datasource and load the appropriate configuration. If you are on Spring 3.1 use profiles to load/activate the correct datasource.

    The logging suggest that you also are using the jdbc namespace somewhere in your configuration, remove that.

    Comment


    • #3
      I'm using Spring 3.1, but I cannot see how profiles will help me...

      What do you mean by:
      The logging suggest that you also are using the jdbc namespace somewhere in your configuration, remove that.

      Comment


      • #4
        I'm using Spring 3.1, but I cannot see how profiles will help me...
        That way you don't have to override a datasource depending on the selected profile the correct datasource is loaded. I suggest a read of the reference guide especially the part explaining profiles.

        What I mean by the jdbc namespace is exactly as stated there. Your logging indicates that you are using the jdbc namespace to instantiate an embedded datasource. Your logging indicates that your definition is overridden (again) by the use of that namespace (that is the component that instantiates the EmbeddedDatabaseFactoryBean ).

        Comment


        • #5
          I'm already using profiles on the part that is running in production, but the unit test is contained with its own application context... So I still cannot see how that helps me in this case.

          I'm not sure as to what you mean by jdbc namespace. Where should I look?

          Here is my application context:
          Code:
          <?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:jdbc="http://www.springframework.org/schema/jdbc"
          	xmlns:jee="http://www.springframework.org/schema/jee"
          	xsi:schemaLocation="
          		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd 
          		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
          	">
          
          	<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
          		<constructor-arg>
          			<bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
          				<property name="driverClass" value="org.h2.Driver" />
          				<property name="url" value="jdbc:h2:mem:salgdb;MODE=DB2;DB_CLOSE_DELAY=-1" />
          			</bean>
          		</constructor-arg>
          	</bean>
          	
          	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          		<property name="dataSource" ref="dataSource" />
          	</bean>
          	 
          	<bean id="advisorServiceDao" class="impl.AdvisorServiceDaoImpl">
          		<property name="dataSource" ref="dataSource" />
          	</bean>
          
          	<jdbc:embedded-database id="dataSource" type="H2">
          		<jdbc:script location="classpath:sql/create_schemas.sql"/>
          		<jdbc:script location="classpath:sql/create_tables.sql"/>
          		<jdbc:script location="classpath:sql/create_test_data.sql"/>
          	</jdbc:embedded-database>
          
          </beans>

          Comment


          • #6
            And what are you testing if you use a seperate configuration?! You should be reusing as much as possible not invent new configuration files for testing...

            However as I stated and now see in your config you are using the jdbc name space (jdbc:embedded-database) to configure an embedded database. That is overridding your configuration. Use either one but not both.

            Comment


            • #7
              Originally posted by Marten Deinum View Post
              And what are you testing if you use a seperate configuration?! You should be reusing as much as possible not invent new configuration files for testing...
              I know, but just started on profiles yesterday - so I'm going that way. My current code base have my conf placed in another project adjacent to this, so I have a little work there. Right now I just want to fix this.

              Originally posted by Marten Deinum View Post
              However as I stated and now see in your config you are using the jdbc name space (jdbc:embedded-database) to configure an embedded database. That is overridding your configuration. Use either one but not both.
              Thanks a lot. I would never have figured that out
              Last edited by sunlock; May 2nd, 2012, 01:52 AM.

              Comment

              Working...
              X