简体   繁体   中英

JNDI Can't Create a JDBC Connection on Tomcat 6

I'm getting this error when I try to view the page:

SQLException: Cannot create JDBC driver of class '' for connect URL 'null'

I have the following /WEB-INF/web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
    <display-name>WSwartzendruber.net</display-name>
    <description>Personal Website</description>
    <!-- Servlet stuff -->
    <servlet>
        <servlet-name>PostgresTest</servlet-name>
        <servlet-class>PostgresTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>PostgresTest</servlet-name>
        <url-pattern>/servlets/postgrestest</url-pattern>
    </servlet-mapping>
    <!-- JNDI -->
    <resource-ref>
        <description>PostgreSQL Data Source</description>
        <res-ref-name>jdbc/db_website</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>

I have this in /META-INF/context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
    <Resource name="jdbc/db_website" auth="Container" type="javax.sql.DataSource" driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/db_website" username="website"/>
</Context>

And here is the test code:

import java.io.*;
import java.sql.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;
import org.wswartzendruber.website.access.*;

public class PostgresTest extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        response.setContentType("text/plain");

        try
        {
            Context initialContext = new InitialContext();
            Context context = (Context)initialContext.lookup("java:comp/env");
            DataSource dataSource = (DataSource)context.lookup("jdbc/db_website");
            Connection connection = dataSource.getConnection();
            NewsCategory[] newsCategory = NewsCategory.getNewsCategories(connection);

            connection.close();
        }
        catch (NamingException e)
        {
            response.getWriter().println("ERROR: We have naming problems!");
        }
        catch (SQLException se)
        {
            response.getWriter().println("ERROR: SQLException: " + se.getMessage());
        }
        catch (AccessException ae)
        {
            response.getWriter().println("ERROR: AccessException: " + ae.getMessage());
        }
    }
}

I'm at a loss for what the issue is. I already have /usr/share/tomcat-6/lib/postgresql-8.4-702.jdbc4.jar in place. Moving it to /WEB-INF/lib makes no difference. It seems to me that it can see the resource entry in WEB-INF/web.xml, but that it can't pull the details from META-INF/context.xml. Assigning a password there also seems to make no difference.

I'm up for whatever you guys have.


Update : here is the full stacktrace:

Sep 19, 2010 7:01:36 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet PostgresTest threw exception
java.io.IOException: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
    at PostgresTest.doGet(PostgresTest.java:23)
    at javax.servlet.http.HttpServlet.service(Unknown Source)
    at javax.servlet.http.HttpServlet.service(Unknown Source)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
    at org.apache.catalina.core.StandardWrapperValve.invoke(Unknown Source)
    at org.apache.catalina.core.StandardContextValve.invoke(Unknown Source)
    at org.apache.catalina.core.StandardHostValve.invoke(Unknown Source)
    at org.apache.catalina.valves.ErrorReportValve.invoke(Unknown Source)
    at org.apache.catalina.core.StandardEngineValve.invoke(Unknown Source)
    at org.apache.catalina.connector.CoyoteAdapter.service(Unknown Source)
    at org.apache.jk.server.JkCoyoteHandler.invoke(Unknown Source)
    at org.apache.jk.common.HandlerRequest.invoke(Unknown Source)
    at org.apache.jk.common.ChannelSocket.invoke(Unknown Source)
    at org.apache.jk.common.ChannelSocket.processConnection(Unknown Source)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(Unknown Source)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:636)
Caused by: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
    at PostgresTest.doGet(PostgresTest.java:17)
    ... 17 more
Caused by: java.lang.NullPointerException
    at org.postgresql.Driver.parseURL(Driver.java:567)
    at org.postgresql.Driver.acceptsURL(Driver.java:412)
    at java.sql.DriverManager.getDriver(DriverManager.java:268)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
    ... 20 more

The "caused by"/"root cause" part of the exception contains information about why it has failed. You should not print only the exception message and ignore the remnant of the exception detail. You should throw the entire exception or at least print the entire stacktrace.

A quick fix: replace your try by

try {
    Context initialContext = new InitialContext();
    Context context = (Context)initialContext.lookup("java:comp/env");
    DataSource dataSource = (DataSource)context.lookup("jdbc/db_website");
    Connection connection = dataSource.getConnection();
    NewsCategory[] newsCategory = NewsCategory.getNewsCategories(connection);
    connection.close();
} catch (Exception e) {
    throw new ServletException(e);
}

And retry. The whole stacktrace should show up in the server's default error page. Or if you have customized the error page that it doesn't show the trace, then look in the server logs, it's there as well.


Update as per the comment: You could just add ServletException to the throws clause. According to the stacktrace, the resource in context.xml is correctly located, the driver is correctly loaded, but the URL has not been passed in as if it's not been specified in the <Resource> .

Are you sure that you're supplying the <Resource> you think you're supplying? Don't you have another <Resource> with the same name, but without an url in Tomcat/conf/context.xml ?

是的,我也遇到了这个问题。如果我将该段放入tomcat / conf / context.xml,它可以工作。我不知道为什么

Add context.xml in WebRoot/META-INF folder and put

<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/ecms" auth="Container" type="javax.sql.DataSource"
    maxActive="100" maxIdle="30" maxWait="10000"
    username="root" password="root123#" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/ecms"/>

In web.xml page write

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

Form a new java class and write

package com.common;

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.sql.DataSource;

public class DataSourceq {

    public Connection dbc() throws NamingException, SQLException, ServletException{
        try {
            InitialContext initialContext = new InitialContext();
            Context context = (Context)initialContext.lookup("java:comp/env");
            //The JDBC Data source that we just created
            DataSource ds = (DataSource) context.lookup("jdbc/ecms");
            Connection connection = ds.getConnection();
            return connection;
        }

        catch (Exception e) {
            throw new ServletException(e);
        }
    }
}

Create object for your Data source Class and call

DataSourceq dq = new DataSourceq();
Connection con =  dq.dbc(); 

And Execute your Query It will Work Sucessfully

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM