Search code examples
springjndispring-test

Spring testing framework - JNDI resource


I am toying a bit with Spring testing framework, but I have one problem. Normally when application is deployed on Tomcat we have

<Resource
       name="jdbc/sqliteDS"
       auth="Container"
       type="javax.sql.DataSource"
       maxActive="4"
       maxIdle="2"
       username="x"
       maxWait="5000"
       driverClassName="org.sqlite.JDBC"
       password="x"
       url="jdbc:sqlite:/home/xxx/db.sqlite"/> 

</Context>

in Tomcat context.xml,

<resource-ref>
    <description>sqlite DataSource</description>
    <res-ref-name>jdbc/sqliteDS</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

in web.xml and

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/comp/env/jdbc/sqliteDS" />
</bean>

in data-context.xml for getting data source, but how can I emulate JNDI resource for Spring test framework, because now during the initialization I am getting errors that data source is not found, and he is right.

Also, it would be great if one can do that without writing another .xml file.


Solution

  • I had to deal with this question a while ago, and I didn't find a suitable solution, but a workaroud which implies another xml file :

    First you create a Spring configuration file defining your JNDI infos (jndi.xml) :

    <beans
      xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
      <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@server:port:instance" />
        <property name="username" value="user" />
        <property name="password" value="pwd" />
      </bean>
    </beans>
    

    Then a static class to bind your JNDI variable :

    public class Initialize {
        public static void initializeJndi() throws Exception {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("jndi.xml");
            SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
            builder.bind("java:comp/env/jdbc/foo", applicationContext.getBean("dataSource"));
            builder.activate();
        }
    }
    

    Then in your test class, you add the following :

        @BeforeClass
        public static void initJndi() throws Exception {
            Initialize.initializeJndi();
        }
    

    So that when you load your Spring main configuration file, the JNDI resource is accessible.

    Maybe this is not the best way to do it but it surely works.

    By the way, having a specific configuration file seems to be a good idea because you may not want to run your unit test on the final database. Doing so is more considered as integration testing than unit testing.

    Hope it helps,

    Mouwah