NullPointerException在mochahost共享服务器上部署时获取连接

时间:2011-11-10 08:28:01

标签: java mysql spring nullpointerexception

我刚刚将我在上运行的 Spring应用程序移动到mochahost上的共享Web托管服务器,我看到了以下异常(截断)根本原因:

root cause

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adDaoImpl': Injection of autowired dependencies failed; nested exception is java.lang.NullPointerException
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
(truncated)

以下:

root cause

    java.lang.NullPointerException
        com.adsense.connection.MySqlDBPooling.getConnection(MySqlDBPooling.java:28)
        com.adsense.dao.impl.AdDaoImpl.setDataSource(AdDaoImpl.java:21)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        java.lang.reflect.Method.invoke(Method.java:597)
        org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
(truncated)

AdDaoImpl.java

@Repository
public class AdDaoImpl implements AdDao{

    Connection conn;

    @Autowired
    public void setDataSource(){
        try{
            conn = (new MySqlDBPooling()).getConnection();
        }catch(SQLException e){
            e.printStackTrace();
        }
    }

    ...
    ...
}

MySqlDBPooling.java

package com.adsense.connection;

import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.*;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

public class MySqlDBPooling implements ServletContextListener{

    private static DataSource ds;

    public MySqlDBPooling(){
    }

    public void contextInitialized(ServletContextEvent sce){
        try{
            Context envCtx = (Context)(new InitialContext()).lookup("java:comp/env");
            ds = (DataSource)envCtx.lookup("jdbc/AdSenseDB");
            System.out.println((new StringBuilder("MySqlDBPooling is set to ")).append(ds.toString()).toString());
        }catch(NamingException e){
            e.printStackTrace();
        }
    }

    public Connection getConnection() throws SQLException{
        return ds.getConnection(); // getting NullPointerException here
    }

    public void contextDestroyed(ServletContextEvent servletcontextevent){
    }
}

context.xml中

<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true" version="5.0">
    <Resource 
       name="jdbc/AdSenseDB"
       auth="Container"
       type="javax.sql.DataSource"
       removeAbandoned="true"
       removeAbandonedTimeout="30"
       maxActive="300"
       maxIdle="300"
       maxWait="1000"
       username="<username here>"
       password="<password here>"
       driverClassName="com.mysql.jdbc.Driver"
       url="jdbc:mysql://localhost:3306/adsense_adsense"/>
</Context>

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Adsense</display-name>
  <listener>
    <listener-class>com.adsense.connection.MySqlDBPooling</listener-class>
  </listener>
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.jpg</url-pattern>
    <url-pattern>*.jpeg</url-pattern>
    <url-pattern>*.png</url-pattern>
    <url-pattern>*.gif</url-pattern>
    <url-pattern>*.ico</url-pattern>
  </servlet-mapping>
</web-app>

有些观点:

  1. 我已将我的jar(包括mysql-connector-java-5.1.10.jar)放在/ WEB-INF / lib中。在localhost上,mysqlconnector放在tomcat libs中。但由于这是一个共享服务器,我无法访问tomcat库。 WEB-INF / lib可能是mysql连接器的错误位置。

  2. WEB-INF / lib可能是放置lib的错误位置。在我在Amazon Web服务器上运行的其他应用程序(与此无关),我已将所有库放在tomcat libs文件夹中。

  3. 在context.xml中,我甚至将url更改为jdbc:mysql://domain.com:3306 / adsense_adsense即将localhost替换为实际域名,但这没有帮助。

  4. 在MySqlDBPooling.java中,如果ds为null,为什么它之前没有抛出NullPointerException

  5.   

    System.out.println((新的StringBuilder(“MySqlDBPooling”设置为   “))附加(ds.toString())的toString());

    在服务器启动期间执行(MySqlDBPooling类作为web.xml中的侦听器添加)

    感谢您的关注。

    詹姆斯

    编辑:

    在我按照@JB Nizet的建议(使用Spring获取数据源)更新MySqlDBPooling.java后,它工作了:

    package com.adsense.connection;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    
    public class MySqlDBPooling implements ServletContextListener{
    
        private static DriverManagerDataSource ds;
    
        public MySqlDBPooling(){
        }
    
        public void contextInitialized(ServletContextEvent sce){
            try{
                ds = new DriverManagerDataSource();
                ds.setDriverClassName( "com.mysql.jdbc.Driver");
                ds.setUrl( "jdbc:mysql://localhost:3306/adsense_adsense");
                ds.setUsername( "USERNAME");
                ds.setPassword( "PASSWORD"); 
                System.out.println("Datasource is: "+ds.toString());
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
        public Connection getConnection() throws SQLException{
            return ds.getConnection();
        }
    
        public void contextDestroyed(ServletContextEvent servletcontextevent){
        }
    }
    

3 个答案:

答案 0 :(得分:2)

如果在context.xml中声明了一个DataSource,Tomcat会尝试使用自己的类加载器实例化它,而不是webapp的类加载器。因此WEB-INF / lib中的驱动程序jar不在其类路径中,并且无法加载驱动程序。

您没有及早看到NPE的原因是JNDI查找可能会因NamingException而失败。您应该在部署时在日志中看到此异常的堆栈跟踪。

由于您使用的是Spring,因此您可以从Spring创建DataSource(使用独立的连接池),而不是让Tomcat创建它。见http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#jdbc-datasource

答案 1 :(得分:0)

您的dataSourcenull,可能是班级重装了

答案 2 :(得分:0)

很简单,你在new MySqlDBPooling()上进行了AdDaoImpl。看到web.xml中已经配置了MySqlDBPooling,我的猜测是类加载器没有加载命名上下文,或者永远不会读取Context.xml。调试并查看在调用contextInititated时是否实例化数据源是一个步骤。