Tomcat 8 WebコンテナーにWebアプリ(WAR)をデプロイしています。
WARの「/ WEB-INF/lib」ディレクトリには、次のjTDS JDBCドライバが含まれています。
<dependency org="net.sourceforge.jtds" name="jtds" rev="1.3.1" />
(ファイルは:jtds-1.3.1.jar
)。
これは、リソースがMETA-INF/context.xml
で定義されている方法です。
<Resource name="jdbc/jtds/sybase/somedb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sybase://localhost:2501/somedb"
username="someuser" password="somepassword"
/>
私のコードでは、 javax.sql.DataSource を通常の方法で取得します。
InitialContext cxt = new InitialContext();
if ( cxt == null ) {
throw new RuntimeException("Uh oh -- no context!");
}
DataSource ds = (DataSource) cxt.lookup( lookupName );
DataSourceオブジェクトds
が予期されたタイプであることを(印刷によって)さらに確認します。
org.Apache.Tomcat.dbcp.dbcp2.BasicDataSource
…しかし、それから接続を取得しようとすると:
Connection conn = ds.getConnection();
…次のトレースが表示されます。
Java.lang.AbstractMethodError
net.sourceforge.jtds.jdbc.JtdsConnection.isValid(JtdsConnection.Java:2833)
org.Apache.Tomcat.dbcp.dbcp2.DelegatingConnection.isValid(DelegatingConnection.Java:924)
org.Apache.Tomcat.dbcp.dbcp2.PoolableConnection.validate(PoolableConnection.Java:282)
org.Apache.Tomcat.dbcp.dbcp2.PoolableConnectionFactory.validateConnection(PoolableConnectionFactory.Java:359)
org.Apache.Tomcat.dbcp.dbcp2.BasicDataSource.validateConnectionFactory(BasicDataSource.Java:2316)
org.Apache.Tomcat.dbcp.dbcp2.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.Java:2299)
org.Apache.Tomcat.dbcp.dbcp2.BasicDataSource.createDataSource(BasicDataSource.Java:2043)
org.Apache.Tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.Java:1543)
何ができますか?
追加しなければならなかったことが判明:
validationQuery="select 1"
context.xml
のResource宣言内。
これは here と記述されています(ただし、validateQuery
のスペルが間違っています)。
JtdsConnection
の実装を掘り下げると、次のようになります。
/* (non-Javadoc)
* @see Java.sql.Connection#isValid(int)
*/
public boolean isValid(int timeout) throws SQLException {
// TODO Auto-generated method stub
throw new AbstractMethodError();
}
これは本当に奇妙です、おそらく AbstractMethodError はコンパイラーのみによってスローされ、実装されていないメソッドは nsupportedOperationException をスローするはずです。とにかく、次の PoolableConnection のコードは、context.xml
にvalidationQuery
が存在するかどうかによって、状況が変化する理由を示しています。 validationQuery
は、以下のメソッドのsql
String
パラメータの値として渡されます(null
を定義しない場合はvalidationQuery
)。
public void More ...validate(String sql, int timeout) throws SQLException {
...
if (sql == null || sql.length() == 0) {
...
if (!isValid(timeout)) {
throw new SQLException("isValid() returned false");
}
return;
}
...
}
したがって、基本的にvalidationQuery
が存在しない場合、isValid
の場合はJtdsConnection
の接続自体の実装が参照され、AbstractMethodError
が奇妙にスローされます。
私がこの問題に遭遇したとき、マーカスによる上記の答えは私にとってうまくいきました。 validationQuery設定がcontext.xmlファイルでどのように表示されるかの具体例を示すには、次のようにします。
<Resource name="jdbc/myDB" auth="Container" type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://SQLSERVER01:1433/mydbname;instance=MYDBINSTANCE"
username="dbuserid" password="dbpassword"
validationQuery="select 1"
/>
ValidationQuery設定は、db接続の各ドライバー設定に含まれます。したがって、context.xmlファイルに別のdbエントリを追加するたびに、この設定をドライバー設定に含める必要があります。
上記の答えはうまくいきます。スタンドアロンJavaアプリケーション用に設定している場合は、データソースに検証クエリを設定します。
BasicDataSource ds = new BasicDataSource();
ds.setUsername(user);
ds.setPassword(getPassword());
ds.setUrl(jdbcUrl);
ds.setDriverClassName(driver);
ds.setMaxTotal(10);
ds.setValidationQuery("select 1"); //DBCP throws error without this query