Java jar依赖项空指针

Java jar依赖项空指针,java,postgresql,tomcat,servlets,jar,Java,Postgresql,Tomcat,Servlets,Jar,我从类路径中作为导出依赖项列出的.jar文件中得到了一个似乎无法解释的nullPointerException jar文件由一个数据库bean组成,当它在一个普通的主方法POJO中被调用时,它可以完美地工作,但是当我在一个servlet中调用同一个jar文件时,我从调用的con.prepareStatement中得到空指针 我认为这可能是池中的一个SQLException导致的,所以我将它移动到我们的VM服务器,它可以在云环境中直接与数据库实例通信,我得到了相同的错误 bean由四个额外的依赖j

我从类路径中作为导出依赖项列出的.jar文件中得到了一个似乎无法解释的nullPointerException

jar文件由一个数据库bean组成,当它在一个普通的主方法POJO中被调用时,它可以完美地工作,但是当我在一个servlet中调用同一个jar文件时,我从调用的con.prepareStatement中得到空指针

我认为这可能是池中的一个SQLException导致的,所以我将它移动到我们的VM服务器,它可以在云环境中直接与数据库实例通信,我得到了相同的错误

bean由四个额外的依赖jar文件组成:guava-16.0.1.jar(对于弱引用的hashmaps),postgresql-9.3-1100.jdbc41.jartomcat dbcp.jartomcat jdbc.jar,它们都使用FatJar for Eclipse封装到一个jar文件中,然后将其导入到托管在Tomcat8 servlet容器中的我的servlet中(也在Tomcat7和TomEE中测试)

servlet代码如下所示:

 import java.io.IOException;
 import java.io.PrintWriter;

 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;

 import com.package.DBEngine;

@WebServlet("/PrimaryEngine")
public class PrimaryEngine extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private DBEngine db;

  public void init(ServletConfig config) throws ServletException{
     super.init(config);
     db = new DBEngine();
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     response.setContentType("text/html;charset=UTF-8");
     PrintWriter out = response.getWriter();
     if(request.getParameterMap().containsKey("op")){
        out.println("Getting data...");
        String test = db.DBdebug();
        out.println(test);
        return;
     }

  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     doGet(request, response);
  }

}
DBEngine如下所示:

 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;

 import com.google.common.collect.MapMaker;
 import com.sun.istack.internal.logging.Logger;

 public class DBEngine {

      private Pool pool = null;
      private Connection con = null;
      private PreparedStatement ps = null;

      //-------------------------------------------
      public DBEngine(){
           this.pool = new Pool();
           this.con = pool.getConnection();
           this.ps = null;

      }

      //---------------------------------------------------
      // Begin subsidiary functions/methods
      //---------------------------------------------------
      public String DBdebug(){

           try {
                String ps = "SELECT table_name FROM information_schema.tables";
                PreparedStatement ps2 = con.prepareStatement(ps);
                ResultSet rs = ps2.executeQuery();

                if(rs.next()){
                     return "Success";
                } else return "Fail";

           } catch (SQLException e) {
                e.printStackTrace();
           }

           return null;
      }

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

 import org.apache.tomcat.jdbc.pool.DataSource;
 import org.apache.tomcat.jdbc.pool.PoolProperties;

 public class Pool {

 private static DataSource datasource = null;

 //--------------------------------------------------
 // Sets up the database connection pool
 //--------------------------------------------------
 public Pool() { 

      PoolProperties p = new PoolProperties();
    p.setUrl("jdbc:postgresql://*URL*:5432/*databasename*");
    p.setDriverClassName("org.postgresql.Driver");
    p.setUsername("*someUserName*");
    p.setPassword("*somePassword*");
    p.setJmxEnabled(true);
    p.setTestWhileIdle(false);
    p.setTestOnBorrow(true);
    p.setValidationQuery("SELECT 1");
    p.setTestOnReturn(false);
    p.setValidationInterval(30000);
    p.setTimeBetweenEvictionRunsMillis(30000);
    p.setMaxActive(75);
    p.setMaxIdle(75);
    p.setInitialSize(10);
    p.setMaxWait(10000);
    p.setRemoveAbandonedTimeout(60);
    p.setMinEvictableIdleTimeMillis(30000);
    p.setMinIdle(10);
    p.setLogAbandoned(true);
    p.setRemoveAbandoned(true);
    p.setRemoveAbandonedTimeout(60);
    p.setAbandonWhenPercentageFull(60);
    p.setJdbcInterceptors(
      "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"+
       "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
    datasource = new DataSource();
    datasource.setPoolProperties(p);

 }

 //-------------------------------------------------------
 // Closes an open datasource
 //-------------------------------------------------------
 public synchronized void closeDatasource() {
      try {
           datasource.close();
      } catch (Exception e) {
           e.printStackTrace();
      }
 }

 //--------------------------------------------------------
 // Get a connection
 //--------------------------------------------------------
 public Connection getConnection() {
      try {
           return datasource.getConnection();
      } catch (SQLException e) {
           e.printStackTrace();
           return null;
      }
 }
tomcat dbcp池如下所示:

 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;

 import com.google.common.collect.MapMaker;
 import com.sun.istack.internal.logging.Logger;

 public class DBEngine {

      private Pool pool = null;
      private Connection con = null;
      private PreparedStatement ps = null;

      //-------------------------------------------
      public DBEngine(){
           this.pool = new Pool();
           this.con = pool.getConnection();
           this.ps = null;

      }

      //---------------------------------------------------
      // Begin subsidiary functions/methods
      //---------------------------------------------------
      public String DBdebug(){

           try {
                String ps = "SELECT table_name FROM information_schema.tables";
                PreparedStatement ps2 = con.prepareStatement(ps);
                ResultSet rs = ps2.executeQuery();

                if(rs.next()){
                     return "Success";
                } else return "Fail";

           } catch (SQLException e) {
                e.printStackTrace();
           }

           return null;
      }

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

 import org.apache.tomcat.jdbc.pool.DataSource;
 import org.apache.tomcat.jdbc.pool.PoolProperties;

 public class Pool {

 private static DataSource datasource = null;

 //--------------------------------------------------
 // Sets up the database connection pool
 //--------------------------------------------------
 public Pool() { 

      PoolProperties p = new PoolProperties();
    p.setUrl("jdbc:postgresql://*URL*:5432/*databasename*");
    p.setDriverClassName("org.postgresql.Driver");
    p.setUsername("*someUserName*");
    p.setPassword("*somePassword*");
    p.setJmxEnabled(true);
    p.setTestWhileIdle(false);
    p.setTestOnBorrow(true);
    p.setValidationQuery("SELECT 1");
    p.setTestOnReturn(false);
    p.setValidationInterval(30000);
    p.setTimeBetweenEvictionRunsMillis(30000);
    p.setMaxActive(75);
    p.setMaxIdle(75);
    p.setInitialSize(10);
    p.setMaxWait(10000);
    p.setRemoveAbandonedTimeout(60);
    p.setMinEvictableIdleTimeMillis(30000);
    p.setMinIdle(10);
    p.setLogAbandoned(true);
    p.setRemoveAbandoned(true);
    p.setRemoveAbandonedTimeout(60);
    p.setAbandonWhenPercentageFull(60);
    p.setJdbcInterceptors(
      "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"+
       "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
    datasource = new DataSource();
    datasource.setPoolProperties(p);

 }

 //-------------------------------------------------------
 // Closes an open datasource
 //-------------------------------------------------------
 public synchronized void closeDatasource() {
      try {
           datasource.close();
      } catch (Exception e) {
           e.printStackTrace();
      }
 }

 //--------------------------------------------------------
 // Get a connection
 //--------------------------------------------------------
 public Connection getConnection() {
      try {
           return datasource.getConnection();
      } catch (SQLException e) {
           e.printStackTrace();
           return null;
      }
 }
和堆栈跟踪:

[ajp-nio-8009-exec-3] org.apache.catalina.core.StandardWrapperValve.invoke Allocate exception for servlet com.package.engine.main.PrimaryEngine
 java.lang.NullPointerException
 com.package.DBEngine.<init>(DBEngine.java:##)
 com.package.main.PrimaryEngine.init(PrimaryEngine.java:26)
 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)
 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
 org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:799)
 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:651)
 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575)
 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
 java.lang.Thread.run(Thread.java:722)
[ajp-nio-8009-exec-3]org.apache.catalina.core.StandardWrapperValve.invoke为servlet com.package.engine.main.PrimaryEngine分配异常
java.lang.NullPointerException
DBEngine.(DBEngine.java:###)
com.package.main.PrimaryEngine.init(PrimaryEngine.java:26)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:799)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:651)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
run(Thread.java:722)
我在这里束手无策。我对Java的所有了解都表明它应该可以工作,但事实并非如此

编辑:

这是Tomcat输出的唯一其他堆栈跟踪:

javax.servlet.ServletException:servlet com.package.main.PrimaryEngine的servlet.init()引发异常 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509) org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:799) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:651) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:722)

基于Luiggi关于不在类中手动创建数据源的输入和使用JNDI数据库池的建议,我能够使下面的解决方案起作用。 我的改编主要基于以下链接:

片段:Tomcat 8.0、postgresql jdbc驱动程序、DBEngine bean、servlet

dbenginebean由三个类组成:dbEngine.java、Pool.java和SQLPS.java(一个SQL语句库),它们都打包到一个jar文件中,导入servlet并标记为类路径导出依赖项

调用bean的servlet如下所示:

 package com.engine.main;

 import java.io.IOException;
 import java.io.PrintWriter;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.concurrent.ConcurrentMap;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import sslog4java.LogLevel;
 import sslog4java.Logger;
 import com.google.gson.Gson;
 import com.DBbean.DBEngine;

 @WebServlet("/PrimaryEngine")
 public class PrimaryEngine extends HttpServlet {
      private static final long serialVersionUID = 1L;
      private DBEngine db = null;

      private static String filePath = "";
      private static String fileName = "";
      Logger fLogger = null;

      public void init(ServletConfig config) throws ServletException{
           super.init(config);
           ServletContext scxt = config.getServletContext();
           filePath = scxt.getRealPath("/WEB-INF") + "\\logs\\";
           fileName = "loggerFileName";
           fLogger = new Logger(filePath, fileName, LogLevel.DEBUG);
           try {
                // passed the servlet context into the DBengine for the pool to use
                db = new DBEngine(new InitialContext(), fLogger);
           } catch (SQLException | NamingException e) {
                e.printStackTrace();
           }
      }

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           PrintWriter out = response.getWriter();
           if(request.getParameterMap().containsKey("param") && request.getParameter("param").equals("paramValue")){
                test = db.DBdebug();
                out.println(test);
                return;
           }
      }
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           doGet(request, response);
      }
 }
 package com.DBbean;

 import java.sql.Connection;
 import java.sql.SQLException;
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.sql.DataSource;

 public class Pool {

      Context ctx;

      public Pool(Context context){
           ctx = context;
      }


     public Connection getConnection() {

           try {
                DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/postgres4" );
                return ds.getConnection();
           } catch (SQLException | NamingException sne) {
                sne.printStackTrace();
                return null;
           }
     }
 }
dbEngine.java看起来像:

 package com.DBbean;

 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
 import javax.naming.Context;
 import sslog4java.Logger;
 import com.google.common.collect.MapMaker;

 public class DBEngine {

      private Pool pool = null;
      private Connection con = null;
      private Logger fLogger;

      public DBEngine(Context initCtx, Logger logr) throws SQLException{
           this.fLogger = logr;
           // passed the servlet context into the Pool.java
           this.pool = new Pool(initCtx);
           this.con = pool.getConnection();
      }

      public String DBdebug(){

           Connection conn = pool.getConnection();

           try {
                String ps = SQLPS.debugSQL;
                PreparedStatement ps2 = conn.prepareStatement(ps);
                ResultSet rs = ps2.executeQuery();

                if(rs.next()){
                     return "Success";
                } else return "Fail";

           } catch (SQLException e) {
                e.printStackTrace();
           }

           return null;
      }
 }
而Pool.java看起来像:

 package com.engine.main;

 import java.io.IOException;
 import java.io.PrintWriter;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.concurrent.ConcurrentMap;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import sslog4java.LogLevel;
 import sslog4java.Logger;
 import com.google.gson.Gson;
 import com.DBbean.DBEngine;

 @WebServlet("/PrimaryEngine")
 public class PrimaryEngine extends HttpServlet {
      private static final long serialVersionUID = 1L;
      private DBEngine db = null;

      private static String filePath = "";
      private static String fileName = "";
      Logger fLogger = null;

      public void init(ServletConfig config) throws ServletException{
           super.init(config);
           ServletContext scxt = config.getServletContext();
           filePath = scxt.getRealPath("/WEB-INF") + "\\logs\\";
           fileName = "loggerFileName";
           fLogger = new Logger(filePath, fileName, LogLevel.DEBUG);
           try {
                // passed the servlet context into the DBengine for the pool to use
                db = new DBEngine(new InitialContext(), fLogger);
           } catch (SQLException | NamingException e) {
                e.printStackTrace();
           }
      }

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           PrintWriter out = response.getWriter();
           if(request.getParameterMap().containsKey("param") && request.getParameter("param").equals("paramValue")){
                test = db.DBdebug();
                out.println(test);
                return;
           }
      }
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           doGet(request, response);
      }
 }
 package com.DBbean;

 import java.sql.Connection;
 import java.sql.SQLException;
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.sql.DataSource;

 public class Pool {

      Context ctx;

      public Pool(Context context){
           ctx = context;
      }


     public Connection getConnection() {

           try {
                DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/postgres4" );
                return ds.getConnection();
           } catch (SQLException | NamingException sne) {
                sne.printStackTrace();
                return null;
           }
     }
 }
我不得不将这些行添加到$CATALINA_HOME/conf/context.xml中:

<Resource
name="jdbc/postgres4"
auth="Container"
type="javax.sql.DataSource"
maxActive="8"
maxIdle="8"
driverClassName="org.postgresql.Driver"
url="*URL*"
username="*UserName*"
password="*Password*"
/>

下面是$CATALINA_HOME/conf/web.xml的代码行:

<resource-ref>
<description>postgreSQL Datasource</description>
<res-ref-name>jdbc/postgres4</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

postgreSQL数据源
jdbc/postgres4
javax.sql.DataSource
容器

postgresql jdbc jar进入$CATALINA_HOME/lib

它看起来不像
DBEngine
中的任何东西,控制器可以抛出
NullPointerException
。您是否向我们展示了所有内容?好吧,您应该使用JNDI获得一个
DataSource
,但您是手动创建的。我想这是您的主要问题。您的问题似乎是当您手动创建
数据源时,您不应该这样做。请参阅此Q/A以了解如何在tomcat中设置数据库连接:如果在
con.prepareStatement
上出现
NullPointerException
,则表示
con
为null,这意味着
Pool.getConnection()
中存在错误。向我们展示堆栈跟踪。@Luiggi:为什么它在我的本地测试POJO中工作?是不是因为没有使用与Web服务器相关的部分导致它崩溃和烧毁?