Search code examples
tomcat7apache-commons-dbcp

Configure DBCP inside of Tomcat


I am trying to inject DataSource into Servlet. Finally I've annotated datasource field with @Resource and some DBCP's BasicDataSource was injected there. But it has no configuration. No db url, no driver class, nothing. Naturally I got NullPointerException when trying to getConnection(). What am I doing wrong?

web.xml

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

    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>ua.test.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/serve</url-pattern>
    </servlet-mapping>
    <resource-ref>
        <res-ref-name>jdbc/MyDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <injection-target>
            <injection-target-class>ua.test.TestServlet</injection-target-class>
            <injection-target-name>dataSource</injection-target-name>
        </injection-target>
    </resource-ref>

</web-app>

context.xml

<?xml version='1.0' encoding='utf-8'?>

<Context>

    <Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource"
              maxActive="10" maxIdle="30" maxWait="10000"
              username="tomcat" password="tomcat" driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/test"/>

</Context>

Solution

  • Obviously no one gave a sh*t about my sorrow. So I will answer myself. Tomcat has it's own(probably modified) copy of Apache Commons DBCP under package org.apache.tomcat.jdbc, but also for some stupid reason includes original DBCP under org.apache.commons.dbcp package. What happens when I try to inject Datasource with @Resource annotation is Tomcat instanting Datasource from original package and injecting this instance to my field. To make Tomcat to use his own copy of DBCP I had to modify my context.xml as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <Resource name="jdbc/MyDB"
                  factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
                  auth="Container" type="javax.sql.DataSource"
                  maxActive="10" maxIdle="30" maxWait="10000"
                  username="tomcat" password="tomcat"  
                  driverClassName="com.mysql.jdbc.Driver"
                  url="jdbc:mysql://localhost:3306/test"/>
    </Context>
    

    Basicaly I just added this line:

    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    

    Thanks to everyone who knew the reason but ignored this question for so long time :-)