JUNITからDataSourceを利用するためには
やることは、
1. 自前でinitialcontextを作成して、JNDIにbindしてあげる。
JNDIへのbindingには、TomcatのNamingを利用するので、いつもの通り、pom.xmlに記述して取得する。
DataSourceの取得といったらconnectionの取得なので、ついでにcommons-dbcpを利用してconnection poolingするようなつくりにする。
pom.xml
<dependency> <groupId>tomcat</groupId> <artifactId>naming-java</artifactId> <version>5.0.28</version> <scope>test</scope> </dependency> <dependency> <groupId>tomcat</groupId> <artifactId>naming-factory</artifactId> <version>5.5.23</version> <scope>test</scope> </dependency> <dependency> <groupId>tomcat</groupId> <artifactId>naming-resources</artifactId> <version>5.5.23</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>[1.,)</version> <scope>test</scope> </dependency>
そうしたら、Google-guiceでDataSourceにBindするようにAbstractModuleを記述する。
ここでは、test用として自前でJNDIにbindするconfigureTestを追加で作成している。
public abstract class AbstractDataSourceModule extends AbstractModule { /** * commons-dbcpのプロパティを取得します。 * * @return */ abstract protected Properties getProperties(); /** * JNDI名称を取得します。 * * @return */ abstract protected String getJndiName(); protected void configureTest() { final String jndiNamePrefix = "java:/comp/env/"; String absoluteJndiName = jndiNamePrefix + getJndiName(); try { // commons-dbcpによるdataSourceの生成 DataSource dataSource = BasicDataSourceFactory.createDataSource(getProperties()); // Contextの生成 System.setProperty( Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory"); System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming"); InitialContext ic = new InitialContext(); ic.createSubcontext("java:"); ic.createSubcontext("java:/comp"); ic.createSubcontext("java:/comp/env"); ic.createSubcontext("java:/comp/env/jdbc"); ic.bind(absoluteJndiName, dataSource); // Bind IntialContext bind(Context.class).toInstance(ic); // Bind DataSource bind(DataSource.class) .annotatedWith(Names.named(getJndiName())) .toProvider( JndiIntegration .fromJndi(DataSource.class, absoluteJndiName)); bind(DataSource.class).toProvider( JndiIntegration.fromJndi(DataSource.class, absoluteJndiName)); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NamingException e) { throw new RuntimeException(e); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void configure() { final String jndiNamePrefix = "java:/comp/env/"; String absoluteJndiName = jndiNamePrefix + getJndiName(); try { InitialContext ic = new InitialContext(); // Bind IntialContext bind(Context.class).toInstance(ic); // Bind DataSource bind(DataSource.class) .annotatedWith(Names.named(getJndiName())) .toProvider( JndiIntegration .fromJndi(DataSource.class, absoluteJndiName)); bind(DataSource.class).toProvider( JndiIntegration.fromJndi(DataSource.class, absoluteJndiName)); } catch (NamingException e) { throw new RuntimeException(e); } catch (Exception e) { throw new RuntimeException(e); } } }
AbstractDataSourceModuleを継承してOracle用のパラメーター設定をサブクラスに定義する。
public class OracleDataSourceModule extends AbstractDataSourceModule { Object[][] dbcpProperties = { { "driverClassName", "oracle.jdbc.pool.OracleConnectionPoolDataSource" }, { "url", "jdbc:oracle:thin:@127.0.0.1:1521:orcl" }, { "username", "ELLECTRA" }, { "password", "PASSWORD" }, { "initialSize", "30" }, { "maxActive", "100" }, { "maxIdel", "30" }, { "maxWait", "500" } }; String jndiName = "jdbc/hoge"; @Override protected String getJndiName() { return jndiName; } @Override protected Properties getProperties() { Properties properties = new Properties(); for (Object[] prop : dbcpProperties) { properties.put(prop[0], prop[1]); } return properties; } }
さらにテスト用でconfigureTest()でconfigureするように書き換える。
public class OracleDataSourceModuleTest extends OracleDataSourceModule { @Override protected void configure() { configureTest(); } }
これで、前回のTestRunnerを利用すれば、ModuleにOracleDataSourceModuleを指定していも、JUnit時は、OracleDataSourceModuleTestが呼ばれる。
こういう暗黙的ルールは良いのか悩みどころです。