Search code examples
javaspringjunitwebspherejndi

Running JUnit tests that depend on resources defined in WebSphere


I've written some unit tests that reference classes that reference other classes that have dependencies on JDBC resources that are defined in WebSphere. The unit tests in question don't actually trigger any database reads or writes, but the classes they refer to are created by Spring and the Spring config file tries to inject the JDBC resources into them. Spring fails, with this error message:

2013-07-31 13:46:17,008:could not load the application context
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [myApplication.xml]: Invocation of init method failed; nested exception is javax.naming.ServiceUnavailableException: Could not obtain an initial context due to a communication failure. Since no provider URL was specified, the default provider URL of "corbaloc:iiop:[email protected]:2809/NameService" was used.  Make sure that any bootstrap address information in the URL is correct and that the target name server is running.  Possible causes other than an incorrect bootstrap address or unavailable name server include the network environment and workstation network configuration. [Root exception is org.omg.CORBA.TRANSIENT: java.net.ConnectException: Connection refused: connect:host=myMachineName.myCompany.com,port=2809  vmcid: IBM  minor code: E02  completed: No]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(AccessController.java:224)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)

The definition of the dataSource bean is simple:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/dataSource" />
</bean>

How can I get Spring to correctly connect to WebSphere JNDI even when the unit test is run outside of the application container?


Solution

  • though not connecting to the WebSphere instance, when looking at JNDI resources, you can always use SimpleNamingContextBuilder from the org.springframework.mock.jndi package. This allows you to build an object (say a DataSource with your own direct binding to the remote JNDI service) then bind it to a 'mock' JNDI service for injection into the Spring Application Context at test time.

    to do this, you'll need to do it in the @BeforeClass (static) of a JUnit Test to ensure that the JNDI bindings are available before the App context starts up. (so the App context can find something when it looks up jdbc/dataSource)

    i wouldn't recommend connecting another server if you're going to use this in a Continuous Integration environment, but if you're looking at doing just a 'one-off, manual test' you could try something like the following;

    @BeforeClass
    public static void beforeClass() throws Exception {
    
        Properties properties = new Properties();
        //build your properties to the remove class
        Context context = new InitialContext(properties);
        //look up your dataSource
        DataSource ds = (DataSource) context.lookup("");
        //now build the simple
        SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
        builder.bind("jdbc/dataSource", ds);
    
    }