Bezdepbonusu7Программирование: статьи и ответы

Вопрос

NullPointerException получает соединение при развертывании на общем сервере mochahost

Автор вопроса: JamesОтветов: 3

Я только что переместил свое приложение Spring, которое отлично работает на локальном хосте, на общий сервер веб-хостинга на mochahost, и я вижу приведенное ниже исключение (усеченное) в основной причине :

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)

АдДаоИмпл.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){
    }
}

Контекст.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>

веб.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. Я поместил свои банки (включая mysql-connector-java-5.1.10.jar) в /WEB-INF/lib. На локальном хосте mysqlconnector помещается в библиотеки tomcat. Но так как это общий сервер, у меня нет доступа к библиотекам tomcat. WEB-INF/lib может быть неподходящим местом для коннектора mysql.

  2. WEB-INF/lib может быть неподходящим местом для размещения библиотек. В другом моем приложении (не связанном с этим), работающем на веб-сервере Amazon, я поместил все библиотеки в папку tomcat libs.

  3. В context.xml я даже изменил URL-адрес на jdbc:mysql://domain.com:3306/adsense_adsense, т.е. заменил localhost на фактический домен, но это не помогло.

  4. В MySqlDBPooling.java, если ds имеет значение null, почему он не вызывал исключение NullPointerException ранее в

System.out.println((new StringBuilder("MySqlDBPooling имеет значение ")).append(ds.toString()).toString());

который выполняется во время запуска сервера (класс MySqlDBPooling добавлен в качестве слушателя в web.xml)

Спасибо за внимание.

Джеймс

РЕДАКТИРОВАТЬ:

Это сработало после того, как я обновил MySqlDBPooling.java, как было предложено (получить источник данных с помощью Spring) @JB Nizet, чтобы:

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){
    }
}
  • Он ясно говорит, что ваш DataSource ds не создается, и вы вызываете getConnection() для нулевой ссылки. Sandeep Pathak 10.11.2011
  • Я думаю, проблема здесь ds=(DataSource)envCtx.lookup(jdbc/NepalAdzDB); Sandeep Pathak 10.11.2011
  • Да, экземпляр DataSource ds не создается, я понимаю это, потому что ds.getConnection генерирует исключение NullPointerException. Это очень просто. Но почему ds оказывается нулевым? Дело в том, что он отлично работает на локальном хосте. Тогда почему проблема на стороннем сервере? Я думаю, что есть что-то делать с JAR. James 10.11.2011

javaspringnullpointerexception

Ответы

Ответ 1 · рейтинг 2 · JB Nizet

Если вы объявляете DataSource в context.xml, Tomcat пытается создать его экземпляр, используя собственный загрузчик классов, а не загрузчик классов веб-приложения. Таким образом, jar драйвера в WEB-INF/lib не находится в его пути к классам, и драйвер не может быть загружен.

Причина, по которой вы не видите NPE раньше, заключается в том, что поиск JNDI, вероятно, завершается с ошибкой NamingException. Вы должны увидеть трассировку стека этого исключения в журнале во время развертывания.

Поскольку вы используете Spring, вы можете создать DataSource из Spring (используя автономный пул соединений) вместо того, чтобы позволить Tomcat создать его. См. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#jdbc-datasource

Ответ 2 · jmj

Ваш dataSource равен null, возможно, класс был перезагружен загрузчиком классов

Ответ 3 · Buhake Sindi

Это просто, вы делаете new MySqlDBPooling() на AdDaoImpl. Видя, что MySqlDBPooling уже настроен в web.xml, я предполагаю, что контекст именования не загружается загрузчиком классов или Context.xml никогда не читается. Отладка и проверка того, создается ли источник данных при вызове contextInititated, будет шагом.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы