Hatena::ブログ(Diary)

ウエンのITスペシャリストへの道〜虎の巻〜 このページをアンテナに追加 RSSフィード

2009-06-21 ディフェンスはわざと隙を作って、相手を仕留めるところに誘導します

[][]Tomcat6.x系でDataSourceを使用してDBにアクセスしてみた。

ネットでいろいろ探しながらDataSourceを使用しました。

環境は以下です。

Eclipse3.4

Tomcat6.0.20


Tomcat5.x系の解説が多いので、それを見ながら実装しましたが、

以下のエラーがずっと解決できませんでした。

org.apache.tomcat.dbcp.dbcp.SQLNestedException:
Cannot create JDBC driver of class '' 
for connect URL 'null'

今日やっと解決できました。

結論、Tomcatのバージョンで配置するファイルの場所が違うことに気づきました。

「百聞は一見にしかず!!」ということで早速紹介します。

では今日の材料は以下になります。

<一人前>
Servlet・・・・1つ
Dto・・・・1つ
Web.xml・・・・少々
画面・・・・少々
Context.xml・・・・一つ

では吟じて見たいと思います。

吟じます!!

まずServletを書きます。

全体は以下のようになります。

package jp.net.damePg;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class DataSourseServlet extends HttpServlet {

	private Connection con = null;
	
	@Override
	public void init() throws ServletException {
		try {
			InitialContext ic = new InitialContext();
			DataSource ds = (DataSource)ic.lookup("java:comp/env/damePg");
			con = ds.getConnection();
		} catch (NamingException e) {
			// InitialContext生成時に例外発生
			e.printStackTrace();
		} catch (SQLException e) {
			// コネクション取得時に例外発生
			e.printStackTrace();
		}
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		if (con != null) {
			try {
				Statement st = con.createStatement();
				ResultSet rs = st.executeQuery("SELECT * FROM TEST");
				List list = new ArrayList();
				while(rs.next()) {
					Dto d = new Dto();
					d.setId(rs.getInt(1));
					d.setName(rs.getString(2));
					list.add(d);
				}
				req.setAttribute("SQLResult", list);
				rs.close();
				st.close();
				req.getRequestDispatcher("result.jsp").forward(req, resp);
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				try {
					con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		} else {
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		}
	}
}

GenericServletで実装されているinitをOverrideします。

そのなかでConnectionを取得するコードを書いています。

Connectionを取得しているのは以下です。

InitialContext ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("java:comp/env/damePg");
con = ds.getConnection();

Connectionを取得するという責務は、DriverManagerを使用するのと同じです。

少し解説しておきます。

lookupの引数java:comp/env/までは決まりです。

その後の「damePg」は後に記述するWeb.xmlとContext.xmlと一致しないといけません。


次にWeb.xmlです

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>datasourseTest</display-name>

	<servlet>
		<servlet-name>test</servlet-name>
		<servlet-class>jp.net.damePg.DataSourseServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>test</servlet-name>
		<url-pattern>/test</url-pattern>
	</servlet-mapping>
	
	<resource-ref>
		<res-ref-name>damePg</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
</web-app>

通常のアプリケーション作成に加えて以下が必要になります。

<resource-ref>
	<res-ref-name>damePg</res-ref-name>
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
</resource-ref>

res-ref-nameはServlet、lookupの引数java:comp/env/の後に記述した内容と同じものを記述します。

res-authはContainerかApllicationを選択できます。

今回はオーソドックスにContainerを使用します。

では次にContext.xmlです。

ここが一番肝心です。

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource 	name="damePg"
		auth="Container" 
		type="javax.sql.DataSource"
               	maxActive="100" 
		maxIdle="30" 
		maxWait="10000"
               	username="ユーザー名" 
		password="パスワード" 
		driverClassName="org.gjt.mm.mysql.Driver"
              	url="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>
</Context>

「name」「auth」「type」はWeb.xmlで記述した内容と同じものを記述します。

続いて以下を記述します。

username・・・MySQLユーザ名

password・・・MySQLパスワード

driverClassName・・・DriverManagerを使用するときClass.forNameの引数に指定するのと同じもの

url・・・DriverManagerを使用するときDriverManagerのgetConnectionの第一引数に指定するのと同じもの


そしてContext.xmlをMETA-INF直下に配置します

20090621144552

Tomcat5.x系はServer.xmlに記述する方法がネットにはたくさんありますが

それではTomcat6.x系はExceptionが発生します。


後は普通にWebアプリケーションを開発するようにすればOK!!

ためしに動作させてみます。

まず、以下のようにDBに値を登録します。

20090621144553

その後、Servletにリクエストすると・・・・

20090621144551

出力しました。

あると思います!!

せっかくなのでこんな実験をしてみました。

mainメソッドで呼び出せるかどうかです。

以下のコードを実行します。

package jp.net.damePg;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.InitialContext;
import javax.sql.DataSource;

public class DatasourceMain{

	public static void main(String[] args) {
		
		try {
			InitialContext context = new InitialContext();
			DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/datasource");
			Connection con =  ds.getConnection();
			Statement st = con.createStatement();
			ResultSet rs = st.executeQuery("select * from test");
			while (rs.next()) {
				System.out.println(rs.getInt("id"));
				System.out.println(rs.getString("name"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

すると以下の例外が発生しました。

javax.naming.NoInitialContextException: 
Need to specify class name in environment or system property,
or as an applet parameter,
or in an application resource file:
java.naming.factory.initial

DataSourcceはWebアプリケーションしか使用できないのですね。

松坂大輔の不調の原因は制球力だと思うdamePGでした。

き 2012/08/23 19:49 ありがとうございます!すごくわかりやすくてとても助かりました!

KK 2012/11/01 17:06 5.5系と同じ設定をして、同じエラーを出したので、非常に参考になりました。

ただ、server.xmlに記載しても、できましたよ。(5.5系までとは、設定方法が違いますが。)

1.server.xmlに、Contextの設定をして、その中に、context.xmlと
同じ設定を入れる。(通常は、非推奨ですがWTP環境下なら、いいのではないかと。)

2.Tom側にContextの設定ファイルを作成し、その中にcontext.xmlの内容を記載する。 (多分、これが推奨な気がします。)

当ページのこの方法だと、アプリにDBの接続先を固有でもってしまうので、モジュール作成時のミスがふえてしまうのでは?と思いますが。。。(Mavenのプロファイルを使うとかすれば、いいのでしょうが)

どどすこどどすこ 2014/12/30 16:34 5.5系の情報を参照しながら実験していてうまくいかなくてイライラしてました。
助かりました。ありがとうございます。

nonamenoname 2016/12/31 03:10 Thanks, information.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証