JBoss EAP 7配置Oracle数据源后,通过代码获取数据库连接抛出java.lang.NullPointerException问题排查
问题排查与解决方案
嘿,我一眼就看到问题所在了——你的代码里犯了一个很典型的变量作用域错误!
首先,JBoss启动日志已经明确显示WFLYJCA0001: Bound data source [java:/jdbc/testOracleDS],这说明数据源已经成功绑定到JNDI树上,JNDI查找本身是没问题的。问题出在你的代码实现上:
核心问题:未正确赋值类成员变量
在init()方法中,你创建了一个局部变量anotherDataSource来接收JNDI查找的结果,但完全没有把这个值赋值给类的成员变量dataSource:
// 这里只是创建了局部变量,类成员dataSource依然是null DataSource anotherDataSource = InitialContext.doLookup("java:/jdbc/testOracleDS");
当doGet()方法执行时,类成员dataSource还是初始的null状态,调用dataSource.getConnection()自然就抛出NullPointerException了。
次要问题:finally块的空指针风险
另外,在finally块里直接调用conn.close()存在隐患:如果连接获取失败(比如前面的NPE导致conn还是null),这里会触发第二个NullPointerException,需要先判断conn是否非空再执行关闭操作。
修改后的完整代码
@WebServlet("/Index") public class Index extends HttpServlet { private static final long serialVersionUID = 1L; private DataSource dataSource; Connection conn = null; public Index() { super(); } public void init() throws ServletException { try { // 将查找结果赋值给类成员变量,而不是局部变量 dataSource = InitialContext.doLookup("java:/jdbc/testOracleDS"); } catch (NamingException e) { e.printStackTrace(); // 可以在这里抛出ServletException,让容器感知初始化失败 throw new ServletException("Failed to lookup data source", e); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { conn = dataSource.getConnection(); System.out.println("connection established"); response.getWriter().println("connection established"); } catch (Exception e) { e.printStackTrace(); response.getWriter().println("failed to establish connection: " + e.getMessage()); } finally { // 增加非空判断,避免conn为null时触发NPE if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
关键修改点总结
- 在
init()方法中,把JNDI查找结果赋值给类成员dataSource,覆盖局部变量的错误写法 - 在
finally块中增加conn != null的判断,避免二次空指针异常 - 可选优化:在init方法的catch块中抛出
ServletException,让容器感知数据源初始化失败,避免后续请求无意义的执行
内容的提问来源于stack exchange,提问作者user8373873
相关产品推荐
相关产品推荐

