I'm currently attempting to read a MS SQL Server database table using Tomcat/JNDI. I can read from the table without issue if I manually hardcode the datasource into my Java source, but when I attempt to load the datasource using JNDI, I get a ClassNotFoundException:
java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerConnectionPoolDataSource
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1420)
org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
TestServlet.doGet(TestServlet.java:53)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
I don't expect to see this since I have Microsoft's JDBC driver (sqljdbc4.jar) stored in Tomcat's lib directory (not the app's WEB-INF/lib) and since it works fine when I hardcode the DataSource into my Java source code. Does anyone have any ideas why this is happening or know of anything else that has to be specified to get Tomcat to add the lib directory to the classpath when using JNDI resources?
context.xml:
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
<Resource name="jdbc/dspr" auth="Container" type="javax.sql.DataSource"
username="<USERNAME OMITTED>"
password="<PASSWORD OMITTED>"
driverClassName="com.microsoft.jdbc.sqlserver.SQLServerConnectionPoolDataSource"
url="<URL OMITTED>"
validationQuery="select 1"
/>
</Context>
TestServlet.java (doPost() code):
PrintWriter out = response.getWriter();
try {
// Servlet fails with a ClassNotFoundException when this block is
//used rather than the block below
InitialContext initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/dspr");
// =========
// Servlet works when this is uncommented and the above block is commented out
//SQLServerConnectionPoolDataSource ds = new SQLServerConnectionPoolDataSource();
//ds.setURL("<URL OMITTED>");
//ds.setUser("<DATABASE USER OMITTED>");
//ds.setPassword("<DATABASE PASSWORD OMITTED>");
// =========
Connection c = ds.getConnection();
Statement s = c.createStatement();
boolean good = s.execute("select * from DS.test_table1");
System.out.println("** QUERY GOOD? " + good);
ResultSet rs = s.getResultSet();
while (rs.next()) {
String col = rs.getString("col1");
String val = rs.getString("val1");
System.out.println(col + " | " + val);
}
c.close();
} catch (NamingException e) {
throw new ServletException(e);
} catch (SQLException e) {
throw new ServletException(e);
}
out.write("hello");
out.close();
As it turns out, I was using com.microsoft.jdbc.sqlserver.SQLServerConnectionPoolDataSource
as the driver class name. It is, in fact, com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
. Aka - PEBCAK.