I am getting a seemingly inexplicable nullPointerException from a .jar file that is listed in the classpath as an export dependency.
The jar file consists of a database bean that works flawlessly when it is called inside of a normal main method POJO, but when I called the same jar file in a servlet, I get null pointers from the con.prepareStatement of whatever I call.
I thought that it might be a SQLException from the pool causing it, so I moved it to our VM server where it can talk directly to the database instance across its cloud environment, and I get the same error.
The bean consists of four additional dependent jar files: guava-16.0.1.jar(for weak referenced hashmaps), postgresql-9.3-1100.jdbc41.jar, tomcat-dbcp.jar, tomcat-jdbc.jar that are all wrapped up into a single jar file using FatJar for Eclipse, which is then imported into my servlet which is hosted in a Tomcat8 servlet container (also tested in Tomcat7 and TomEE).
The servlet code is as follows:
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);
}
}
The DBEngine looks like this:
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;
}
}
The tomcat-dbcp pool looks like this:
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;
}
}
And the stack trace:
[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)
I am at wits end here. Everything that I know about Java says that it should work, but it does not.
Edit:
This is the only other stack trace that Tomcat outputs:
javax.servlet.ServletException: Servlet.init() for servlet com.package.main.PrimaryEngine threw exception 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)