Tom O'Brien
Tom O'Brien

Reputation: 1831

ClassCastException when attempting to get MysqlDatasource from Tomcat BasicDataSource

My web application is trying to get a MysqlDataDatasource when I connect to my mysql database. My application is hosted on the Apache Tomcat 8.5 webserver.

However it throws this ClassCastException when I try to cast from my context.lookup:

java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp2.BasicDataSource
cannot be cast to com.mysql.jdbc.jdbc2.optional.MysqlDataSource

Here is the line where the cast is failing:

MysqlDatasource mysql_datasource =
    (MysqlDataSource) context.lookup("java:/comp/env/jdbc/MySQLDataSource");

This is my context.xml configuration:

<Resource name="jdbc/MySQLDataSource" auth="Container" type="javax.sql.DataSource"
    username="root" password="password" maxTotal="100" maxIdle="30" maxWaitMillis="10000"
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/pododdle"/>

This my web.xml configuration:

<resource-ref>
    <description>Pododdle DB Connection</description>
    <res-ref-name>jdbc/MySQLDataSource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

Anybody know what the problem is here, and how can i get my hands on this all important and most elusive com.mysql.jdbc.jdbc2.optional.MysqlDataSource? All help much appreciated!

PS: Previously I was hosting my application on the glassfish 4 server, and the following code was used to get the MysqlDatasource:

Datasource datasource = (DataSource) context.lookup("jdbc/MySQLDataSource");
MysqlDataSource mysql_datasource = datasource.unwrap(MysqlDataSource.class);

Upvotes: 0

Views: 175

Answers (1)

BobJiang
BobJiang

Reputation: 506

There are some doc about tomcat8 context. tomcat use Apache Commons DBCP pool by default.

So, when you call context.lookup("jdbc/MySQLDataSource") in tomcat, it will return BasicDataSource by default, can't cast it to MysqlDataSource directly.

That would be work if you want get a MysqlDataSource.(add a method to copy name/password/url... to you target DataSource and newInstance it)

void yourmethod(){
    //...
    BasicDataSource ds = (BasicDataSource)context.lookup("jdbc/MySQLDataSource");
    MysqlDataSource mysqlDs = unwrap(ds);
    //...
}

protected MysqlDataSource unwrap(BasicDataSource ds){
    MysqlDataSource mysqlDs = new MysqlDataSource();
    mysqlDs.setUser(ds.getUsername());
    mysqlDs.setPassword(ds.getPassword());
    mysqlDs.setURL(ds.getUrl());
    // copy more properties
    return  mysqlDs;
}

Upvotes: 2

Related Questions