1

I'm using tomcat + spring. When use following config:

<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
    <property name="url" value="url" />
    <property name="username" value="user" />
    <property name="password" value="pass" />
</bean>

I'm able to obtain connection. But when I try use Tomcat's CP as follows:

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
    <property name="url" value="url" />
    <property name="username" value="user" />
    <property name="password" value="pass" />
</bean>

I got nested root cause exception: java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Driver

The only change I'm making is rename class which is responsible for creating data source. Why this happen? How to solve that?

UPDATE - STACK TRACE

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.sql.SQLException: com.ibm.db2.jcc.DB2Driver
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
root cause

java.sql.SQLException: com.ibm.db2.jcc.DB2Driver
    org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:254)
    org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)
    org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:702)
    org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:634)
    org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:488)
    org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:144)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:127)
    spring.controller.ReviewController.getReviewById(ReviewController.java:25)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
root cause

java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Driver
    java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    java.security.AccessController.doPrivileged(Native Method)
    java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    java.lang.Class.forName0(Native Method)
    java.lang.Class.forName(Class.java:270)
    org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:246)
    org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)
    org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:702)
    org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:634)
    org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:488)
    org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:144)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:127)
    spring.controller.ReviewController.getReviewById(ReviewController.java:25)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
abc
  • 2,371
  • 3
  • 25
  • 36
  • did you have jdbc jar file ready in lib folder? – BMW Apr 10 '14 at 09:44
  • @BMW I must have it in lib, otherwise 1st config would not work... – abc Apr 10 '14 at 09:47
  • no, they are belong to different jars – BMW Apr 10 '14 at 09:50
  • @BMW Yes they do, but I use eclipse which after configuration of server adds tomct/lib by default. I'm 100% sure Tomact's CP is on class path. It's not saying that my CP missing but driver - yes? But it cannot missing since, 1st config works. – abc Apr 10 '14 at 10:00
  • My thoughts. By any change Tomcat's CP ignores lib folder? – abc Apr 10 '14 at 10:02
  • by default, tomcat-dbcp.jar is in lib folder, but not jdbc. that's why I ask you to have it ready first. you can download it from oracle. http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html – BMW Apr 10 '14 at 10:03
  • @BMW I need Oracle JDBC driver to use IBM's db2? Am I missing something? It's first time I'm using DB2, usually I using vendors driver. If this just miss spell, then I have `com.ibm.db2.jcc.DB2Driver` in WEB-INF/lib since commons cp works, problem is only with Tomcat's CP. – abc Apr 10 '14 at 10:08

3 Answers3

2

I assume that in your application in configuration one you have the following jars in your WEB-INF\libfolder

  1. commons-dbcp.jar
  2. jt400.jar

(Or maybe some version of that).

Now when using option 2 this is a problem as I assume that the class org.apache.tomcat.jdbc.pool.DataSource comes from a jar in the tomcat\lib folder and not from the WEB-INF\lib folder. As the org.apache.tomcat.jdbc.pool.DataSource is loaded by the system classloader instead of the web application classloader it cannot see the classes from jars in the WEB-INF\lib directory.

So either drop your jt400.jar in the tomcat\lib directory OR include the tomcat-jdbc.jar in your WEB-INF\lib folder.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • actually it works... to be honest I do not understand why. I do not have commons-dbcp, but have tomcat-dbcp (which as far as I know is basically the same) in tomcat/lib tomcat-jdbc is there as well. So this is very strange that one CP see driver while second do not. Anyway props for answer. – abc Apr 10 '14 at 11:15
  • Didn't notice the `org.apache.tomcat.dbcp.dbcp.BasicDataSource` that was ignored due to the `BasicDataSource` for which I assumed you used plain DBCP. Tomcat by default uses the tomcat-jdbc impl for its datasources, so it probably will also be eagerly loaded in the system classloader, as opposed tot he tomcat-dbcp one. – M. Deinum Apr 10 '14 at 11:23
  • Maybe that's how it works. Thanks once again for solving problem the way I wanted. – abc Apr 10 '14 at 11:25
0

The problem is that you have set a new connection pool that will be used for obtaining connections. The new code of the new connection pool needs to be on the classpath. Have you added that dependency to the project?

EDIT

What version of tomcat are you using? Also could you post your full stacktrace?

geoand
  • 60,071
  • 24
  • 172
  • 190
  • Could you be more specific. Dependency to DB2 driver or Tomcat's CP? I use Tomcat, so CP must be on classpath. DB2 driver is on class path as well since 1st config (using common cp) works. – abc Apr 10 '14 at 09:49
  • 7.0.42 some random text, to meet requirements of comment length – abc Apr 10 '14 at 09:55
  • With that version the tomcat connection pool should be present in lib. – geoand Apr 10 '14 at 09:58
0

It's seems like you cannot create data source using Tomcat's CP via Spring (maybe it's due to Tomcat's CP use some factory pattern). My current walk around looks like follows:

  1. Define Tomcat's DBCP as JNDI resource
  2. Load JNDI resource into Spring, more info here

See also accepted answer since it solve problem in the way it was stated in original question.

Community
  • 1
  • 1
abc
  • 2,371
  • 3
  • 25
  • 36