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

Java 在mochahost共享服务器上部署时获取连接的NullPointerException,java,mysql,spring,nullpointerexception,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.

我刚刚将在本地主机上运行良好的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>

您的
dataSource
null
,可能是类加载器重新加载了类

这很简单,您正在
上执行一个
新的MySqlDBPooling()
。看到MySqlDBPooling已经在
web.xml
中配置,我的猜测是类加载器没有加载命名上下文,或者
Context.xml
从未被读取。调试和查看在调用
contextinitated
时是否实例化了数据源将是一个步骤。

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

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


因为您使用的是Spring,所以可以从Spring创建数据源(使用独立的连接池),而不是让Tomcat创建它。请参见

它清楚地表明您的数据源ds没有被实例化,您正在对空引用调用getConnection()。我认为问题在于ds=(数据源)envCtx.lookup(“jdbc/NepalAdzDB”);是的,数据源ds没有得到实例化,我得到了,因为ds.getConnection正在抛出NullPointerException。这很简单。但为什么ds是空的呢?问题是,它在本地主机上运行良好。那么第三方服务器上到底有什么问题?我认为这与JAR有关。仔细阅读问题:他已经这样做了,尽管他使用了一个新的MySqlDBPooling,但ds字段是一个静态字段。它就在那里。MySQLDBPooling类在服务器启动时执行,并填充数据源对象。稍后,在autowire for connection期间,会再次调用MySQLDBPooling的另一种方法getConnection(),以从数据源对象获取连接。在本地主机上一切正常。该问题仅出现在第三方托管服务器(mochahost)上。在这种情况下,我可以在配置文件中的某个位置定义lib文件夹的路径吗?好的,不可以。您必须将jar放在tomcat的lib目录中。但我使用共享托管,无法访问tomcat目录。您认为还有什么其他选项是可能的呢?我在回答中写道:使用DBCP或其他池实现,将池的jar与DB驱动程序一起放入WEB-INF/lib,并使用Spring创建数据源。+1,因为答案是“使用Spring的JDBC层时,您可以从JNDI获取数据源,也可以使用Spring发行版中提供的实现配置自己的数据源。后者对于web容器之外的单元测试非常方便。“如果没有您的回答,我将无法找到它。我希望这一切顺利。测试。。。
<?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>
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){
    }
}