Commons DBCP在OSGI环境中Cannot load JDBC driver class 'com.mysql.jdbc.Driver' 问题解决
在blueprint.xml中配置mysql的datasource,如下所示:
<bean id="dataSourceMySQL" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com. mysql.jdbc.Driver" />
<property name="url" value="jdbc: mysql://localhost:3306/cbmsys" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<!-- Expose DataSource as JNDI reference -->
<service id="cbmsysdb" ref="dataSourceMySQL" interface="javax.sql.DataSource">
<service-properties>
<entry key=" osgi.jndi.service.name" value="jdbc/cbmsysdb" />
</service-properties>
</service>
在OSGI环境运行后,系统报告: Cannot load JDBC driver class 'com.mysql.jdbc.Driver' , 而该Bundle已经增加了对com.mysql.jdbc的import,而且mysql jdbc connector也正常加载,出现该异常实在让人困惑。
后来通过资料查询发现,在OSGI环境下使用Commons DBCP创建DataSource时发生此错误的不在少数,问题在于DBCP在实例化com.mysql.jdbc.Driver时采用了class.forName,检查我所采用的Commons DBCP 1.4 Jar包中的MANIFEST.MF中的Import-package,如下所示:
我们发现其中并没有"com.mysql.jdbc",所以在加载mysql时会报告ClassNotFoundException。其实这也是理所当然的,因为作为DBCP,如何在build时就知道我们会使用哪种数据库的驱动呢?而要解决此问题,有两种方法:
1)直接修改DBCP的Manifest.mf,在Import-Package中增加"com.mysql.jdbc",如果你用oracle,可以加入oracle的jdbc driver名称。这种方法有些暴力,比较直接。
2)另一种方法是不采用class.forName,在blueprint中修改DataSource的配置,如下:
<bean id="mysqlDataSource" class="com.mysql.jdbc.jdbc2.optional.
MysqlConnectionPoolDataSource"> <property name="createDatabaseIfNotExist" value="true"/> <property name="url" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Commons-DBCP --> <bean id="dataSource" class="org.apache.commons.dbcp.datasources.
SharedPoolDataSource" lazy-init="false" destroy-method="close"> <property name="connectionPoolDataSource" ref="mysqlDataSource"/> <property name="maxActive" value="20"/> <property name="maxIdle" value="3"/> </bean> <!-- c3p0 --> <!-- not tested yet, but should work same way <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource"
lazy-init="false"> <property name="connectionPoolDataSource" ref="mysqlDataSource"/> <property name="maxPoolSize" value="15"/> <property name="minPoolSize" value="3"/> </bean> --> <!-- export the existing datasource bean into OSGi --> <osgi:service id="classificationDataSource" ref="dataSource"> <osgi:interfaces> <value>javax.sql.DataSource</value> </osgi:interfaces> </osgi:service>
在bundle中增加import "com.mysql.jdbc. jdbc2.optional",先创建“com.mysql.jdbc.jdbc2.optional. MysqlConnectionPoolDataSource”,然后在dbcp中配置"connectionPoolDataSource"属性进行初始化即可。