【发布时间】:2020-10-08 19:29:12
【问题描述】:
我正在尝试使用 @Resource 注释从 Tomcat 8.5.56 注入 DataSource,但是当我运行代码时,我得到 NullPointerException。
注意:使用InitialContext 获取DataSource 仍然可以正常工作。
context.xml中的资源定义:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/postgres" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/contact_directory"
username="username" password="password" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/>
</Context>
用于测试的 servlet:
@WebServlet(name = "TestController", urlPatterns = "/test")
public class TestController extends HttpServlet {
//this also doesn't work
//@Resource(lookup="java:/comp/env/jdbc/postgres")
@Resource(name="jdbc/postgres")
private DataSource dataSource;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String query = "SELECT ... FROM ..."; //here goes the query text
try(Connection connection= dataSource.getConnection();
Statement statement=connection.createStatement();
ResultSet resultSet= statement.executeQuery(query)) {
//some actions with resultSet
} catch (Exception e) {
e.printStackTrace();
}
}
}
错误代码(错误行为Connection connection= dataSource.getConnection()):
java.lang.NullPointerException
at com.nevermind.controller.TestController.doGet(TestController.java:41)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:615)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1627)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
使用InitialContext 的类可以正常工作:
public class DatabaseUtil {
public static DataSource getDataSource() {
DataSource ds=null;
try {
InitialContext cxt = new InitialContext();
ds = (DataSource) cxt.lookup( "java:/comp/env/jdbc/postgres" );
} catch (NamingException e) {
e.printStackTrace();
}
return ds;
}
}
注意: 我看过很多指南和类似的问题,但没有具体的解决方案。
一些答案有类似的解决方案 (Tomcat 7 Datasource injection mechanism),但在我的情况下,它仍然不起作用。
有人说Tomcat>6不支持@Resource注解(Getting null pointer exception @Resource annotation in tomcat 7),但是下一个回答说支持。
我很困惑可能是什么问题?
【问题讨论】:
-
你可以使用spring boot吗?是否可以打印您的 InitialContext 示例的 ds 以验证它是否为空?
-
我成功地使用了
@Resource(name = "jdbc/MyDbName")的Tomcat 8.5.56(在$CATALINA_BASE/conf/context.xml中有<Resource>条目)。但是,设置似乎与问题中的设置没有任何不同(除了我使用的是 MySQL)。第 41 行 (TestController.java:41) 的 null 是什么? -
@AndreiYusupau 经过 2 天的研究,我找到了解决方案。添加我的答案。
-
@AndreiYusupau 添加了我的答案。请检查。
-
在 context.xml 中拥有资源是不够的。您需要在您的
web.xml中有一个resource-ref
标签: java postgresql tomcat jakarta-ee