- PR -

TomcatのJNDI DatasourceをJava Appliactionから取得する方法

1
投稿者投稿内容
hypergori
会議室デビュー日: 2004/01/20
投稿数: 19
投稿日時: 2004-11-29 11:20
こんにちは、お世話になっております。
JNDI初心者です。

すこし広い言い方になりますが、
別のVMで動いているJava Applicationのプログラムから
tomcatで設定されているDatasourceを取得する方法って
あるのでしょうか?

目的は、JNDIの勉強です。
あとは、JNDIを使用してDBUNITのテストケースを書きたいからです。
(tomcatがJNDIサーバーになればいいなとの期待があります。)

現在 tomcat上では、DBCPを使用した
WEBアプリが動いていて。そこでは、server.xmlとweb.xmlに
設定した内容でコネクションがとれて元気に動いています。
こんな感じで,簡単にとれました。
InitialContext initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:/comp/env");
ds = (DataSource) envCtx.lookup("jdbc/oradb");

ですが、tomcatのサイトにいくと
"Tomcat 5 は、その下で動作する Web アプリケーションに対して
JNDI InitialContext の実装を提供します"。
じゃあ当然 別VMのアプリは無理なんだあ。というかJNDIの仕組み
ってなんだろということで
SUNのJNDIのtutorialを読んだんですが、抽象的で分かりませんでした。

ここを読め!とかありましたら教えていただけると幸いです。

よろしくお願いします。

uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-11-29 11:40
Tomcatは外部にネーミングサービスのインタフェースを公開していませんが、ネーミング
サービスを公開しているアプリケーションサーバ(たとえばWebLogic)なら可能です。
ローカルでWebLogicを起動しておいて、Eclipseからデータベースにアクセスするクラスの
単体テストなどを実際に行っています。
hypergori
会議室デビュー日: 2004/01/20
投稿数: 19
投稿日時: 2004-11-29 12:05
返信ありがとうございます。
やはりtomcatでは できないんですね。

DBUnit実行時にだけ そのコンテキストが取れれば
よいのですが。APサーバーを使用しないという方法は可能なんでしょうか?

例:DBUNITのテストケースメソッドの1つ
testEmployeeUpdate001() throws Exception{

1. JNDIへのDatasource登録(tomacatで使用している
  "java:/comp/env"の"jdbc/oradb" へ
  のDatasource登録.コンテナのEmulationになるのかも。)

2.DAO インスタンス化(コンストラクターで、
  tomcatのJNDI登録からDatasourceを取得している。
  これはDAOコードを変更しないことになります。)

//DAOのテスト対象メソッド呼出
 //期待値とかのDataSet取得して Assert色々
}

 上記1番 が可能かというところなのですが、いかがでしょうか。
koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2004-11-29 14:47
試してないですが、MockObjectsのMockContextを使い、単体テスト実行時には
通常と別のMockDataSourceを使わせるようにするというのはどうでしょうか。

MockObjectsのMockContextの使い方についてはここに書いてあります。
http://weblogs.java.net/blog/simongbrown/archive/2003/11/using_mock_nami.html
ここが、MockObjectsのサイトです。
http://www.mockobjects.com/FrontPage.html

Contextが返すMockDataSourceですが、これはJDBCを直接使って取得するConnectionを
返すように設定しておけば、DataSourceを使う側は今までどおり動作すると思います。
自分で試してないのでアレですが(^^;。

ちなみに、DBUnitを使う場合は、同じテーブルやビュー等を持つデータベースを複数用意して
開発者ごとに使い分けることが推奨されています(http://www.dbunit.org/bestpractices.html)。
また、私個人の経験では、機能テストや総合テスト用のデータベースも別途用意した方が
いいです。

以上の点を考えると、データベースを使い分ける意味でもこの方法は効果的ではないかと
思います。
teto
ベテラン
会議室デビュー日: 2002/07/31
投稿数: 61
投稿日時: 2004-11-29 15:42
以前私は下記のようなコードでDBCPを直接操作しDataSouceを生成してDBTestに使用
しました。オラクルですが参考までに。

コード:
public DataSource getDataSouce() throws Exception{
  Class.forName("oracle.jdbc.driver.OracleDriver");
  ObjectPool connectionPool = new GenericObjectPool(null);
  /*プロパティからDBのURI「jdbc:oracle:thin:user/pass@host:1521:sid」を取得しConnectiFactoryを生成*/
  ConnectionFactory connectionFactory = 
    new DriverManagerConnectionFactory(ApplicationConfig.getString("test.db.uri"),null);
  PoolableConnectionFactory poolableConnectionFactory = 
    new PoolableConnectionFactory(
      connectionFactory,connectionPool,null,null,false,false
    );
  return new PoolingDataSource(connectionPool);
}

hypergori
会議室デビュー日: 2004/01/20
投稿数: 19
投稿日時: 2004-11-29 16:12
koeさん、tetoさん

返信ありがとうございます。

自己解決しました。Junitのサイトに、私がまさに欲していた
JARがおいてありました。
http://www.junit.org/news/extension/index.htm#JNDI

JUnit JNDI DataSource helper package
です。すぐに動きました。

TO:koeさん
DBUNIT時には、DBUNIT専用のDBでテストしています。
tomcatをサーバーにしようとしていたのは、
DBを使わないということではありませんでした。言葉足らず失礼しました。
(tomcatだったらデータソースをくれるJNDIサーバーに簡単に
 なってくれるかなと思ったので)

TO:tetoさん
じつは、全てのDAOの親のDAOのコンストラクターで、こんなこと↓をしているので

InitialContext initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:/comp/env");
ds = (DataSource) envCtx.lookup("jdbc/oradb");

データソースの取得のロジックについては、触れない状況だったんです。
(TestCodeからDatasourceをDAOに渡すという方法はとれなかった)

JAVARAnCHのライブラリーを使用すると
好きなJNDI名でDatasourceを登録できるので、可能でした。

この場合だと、前述のpseudoコードですと、

testEmployeeUpdate001() throws Exception{

//JNDIへのDatasource登録
if(JNDIUnitTestHelper.notInitialized()){
JNDIUnitTestHelper.init("testlib/jndi_unit_test_helper.properties");

//DAO インスタンス化(コンストラクターで、
  JNDI登録からDatasourceを取得する。Datasourceは、
  親クラスからDAO内部でGET。

//DAOのテスト対象メソッド呼出
 //期待値とかのDataSet取得して Assert色々
}

そして、プロパティファイル
jndi_unit_test_helper.properties
に、
com.javaranch.unittest.helper.sql.pool.JNDIName=java:/comp/env/jdbc/oradb
って書いておく。

/以上



[ メッセージ編集済み 編集者: hypergori 編集日時 2004-11-29 20:11 ]
teto
ベテラン
会議室デビュー日: 2002/07/31
投稿数: 61
投稿日時: 2004-11-30 10:59
引用:
じつは、全てのDAOの親のDAOのコンストラクターで、こんなこと↓をしているので



そんな気がしてました。
DataSouceの生成はDAOよりDAOFactoryが行うべきことですね。

それはともかく、「JUnit JNDI DataSource helper package」なんて便利なものあるのですね、既存アプリでJNDIに依存しまくっているクラスのテストに便利かも
しれません。

1

スキルアップ/キャリアアップ(JOB@IT)