java 在tomcat 7中获取空指针异常@Resource注解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7878835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:47:57  来源:igfitidea点击:

Getting null pointer exception @Resource annotation in tomcat 7

javatomcatjdbcannotationsdatasource

提问by Srinivas

Here is my Resource element in context.xml ::

这是我在 context.xml 中的 Resource 元素 ::

<Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
              url="jdbc:oracle:thin:@localhost:1521:XE"
              username="hr" password="hr" maxActive="20" maxIdle="10"
              maxWait="-1"/> 

Here is my Resource reference in web.xml:

这是我在 web.xml 中的资源参考:

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

I then use @Resourceannotation in my code:

然后@Resource我在我的代码中使用注释:

      @Resource(mappedName = "jdbc/myoracle")
        DataSource ds;

When I try to create connection object using getConnection() on ds, I get a null pointer exception during runtime:

当我尝试在 ds 上使用 getConnection() 创建连接对象时,在运行时出现空指针异常:

    Oct 24, 2011 12:18:21 PM org.apache.catalina.core.StandardWrapperValve invoke
    INFO: java.lang.NullPointerException
        at jdbc.patientDaoImpl.get_patients(patientDaoImpl.java:248)
        at org.apache.jsp.index2_jsp._jspService(index2_jsp.java:92)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:223)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)

But if I lookup using initialContext the app works fine.

但是如果我使用 initialContext 查找应用程序工作正常。

    Context initContext = new InitialContext();
    Context envContext  = (Context)initContext.lookup("java:/comp/env");
    DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");

Where am I going wrong?

我哪里错了?

采纳答案by Bozho

Tomcat itself does not support @Resourceinjection. In other words, the servlet container does not recognize that annotation and can't do anything with it. Manual lookup works, because the resource is defined properly.

Tomcat 本身不支持@Resource注入。换句话说,servlet 容器无法识别该批注,也无法对其进行任何操作。手动查找有效,因为资源定义正确。

You need some dependency-injection framework:

你需要一些依赖注入框架:

  • spring
  • CDI (part of the JavaEE6 web-profile)
  • EJB (part of the JavaEE6 web-profile, not exactly a "DI framework")
  • 春天
  • CDI(JavaEE6 web-profile 的一部分)
  • EJB(JavaEE6 web-profile 的一部分,不完全是“DI 框架”)

回答by David Blevins

Note Tomcat doessupport @Resourceinjection. You were really really close.

注意 Tomcat确实支持@Resource注入。你真的很亲近。

The issue was you used:

您使用的问题是:

  • @Resource(mappedName = "jdbc/myoracle")
  • @Resource(mappedName = "jdbc/myoracle")

This would have worked:

这会奏效:

  • @Resource(name = "jdbc/myoracle")
  • @Resource(name = "jdbc/myoracle")

I'll note that had you been using Apache TomEE (the JavaEE certified version of Tomcat), both would have worked with no changes to your context.xml

我会注意到,如果你一直在使用 Apache TomEE(Tomcat 的 JavaEE 认证版本),两者都不会改变你的 context.xml

Plus you get CDI, EJB, JPA and other things mentioned in some of the other answers.

此外,您还会获得 CDI、EJB、JPA 和其他一些答案中提到的其他内容。

Small comparison here.

比较在这里

回答by hisdrewness

There are a lot of things going on here. First off, you don't need a resource-ref in your web.xml unless you're going to let the application server manage the data source. This is useful if you use something like IBM WAS, or Apache Tomcat, and specify the data source parameters in your server config. If you do this, you'll want to keep the resource ref, and add a jndi factory bean:

这里发生了很多事情。首先,除非您打算让应用程序服务器管理数据源,否则您的 web.xml 中不需要资源引用。如果您使用 IBM WAS 或 Apache Tomcat 之类的东西,并在服务器配置中指定数据源参数,这将非常有用。如果你这样做,你会想要保留资源引用,并添加一个 jndi 工厂 bean:

<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName"><value>java:comp/env/jdbc/myOracle</value></property>
</bean>

Coincidentally, I'm pretty sure your set up will work now if you simply add this bean.

巧合的是,如果您简单地添加这个 bean,我很确定您的设置现在可以工作。

From what you have now, or if you use a jndi factory bean, all you have to do is autowire the bean from there:

根据您现在拥有的,或者如果您使用 jndi 工厂 bean,您所要做的就是从那里自动装配 bean:

@Autowired
@Qualifier("myDataSource")
DataSource dataSource;

If you would like to verify the state of your bean, you could always implement InitializingBeanwhich will force you to implement afterPropertiesSet

如果你想验证你的 bean 的状态,你总是可以实现InitializingBean这将迫使你实现afterPropertiesSet

@Override
public void afterPropertiesSet() throws Exception {
    Assert.notNull(dataSource);
}

Although 1@Autowired` should through an exception if it can't autowire by default.

尽管 1@Autowired` 应该在默认情况下无法自动装配时通过异常。

It's also worth noting that it's a better paradigm to use a constructor:

还值得注意的是,使用构造函数是一个更好的范例:

@Autowired
public MyClass(@Qualifier("myDataSource") DataSource dataSource) {
   this.dataSource = dataSource;
}