【问题标题】:Getting null pointer exception @Resource annotation in tomcat 7在tomcat 7中获取空指针异常@Resource注释
【发布时间】:2011-12-14 07:07:46
【问题描述】:

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

<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"/> 

这是我在 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>

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

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

当我尝试在 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)

但是,如果我使用 initialContext 进行查找,则应用可以正常工作。

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

我哪里错了?

【问题讨论】:

    标签: java tomcat jdbc annotations datasource


    【解决方案1】:

    这里发生了很多事情。首先,您不需要 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>
    

    巧合的是,我很确定如果您只需添加这个 bean,您的设置现在就可以工作了。

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

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

    如果您想验证 bean 的状态,您始终可以实现 InitializingBean,这将强制您实现 afterPropertiesSet

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

    虽然1@Autowired`如果默认不能自动装配应该通过异常。

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

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

    【讨论】:

    • 请注意,您正在使用 Spring 注释,该操作可能会或可能不会使用。 (自动装配 @Resource 它不是独立 Tomcat 支持的,自动装配通常由 JEE 应用程序服务器提供)
    • 感谢您的回复。但我没有为我的应用程序使用 spring 框架。我在 JavaEE 中做这件事,我的后端逻辑是用 Java 类编写的。能否请您指导我如何在 JavaEE 中做到这一点?
    【解决方案2】:

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

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

    • 弹簧
    • CDI(JavaEE6 网络配置文件的一部分)
    • EJB(JavaEE6 Web 配置文件的一部分,不完全是“DI 框架”)

    【讨论】:

    • 奇怪的是,它在 Tomcat 6 中工作得很好,而在 Tomcat 7 中却中断了。知道为什么会这样吗?
    • @BjörnPollex 我也从 Tomcat 6 升级到了 Tomcat 7,@Resource 停止工作。你找到解决办法了吗?
    • @PanuHaaramo:抱歉,我从未找到可移植的解决方案(适用于 Tomcat 6 和 7 的解决方案)。如果我没记错的话(这已经有一段时间了),我们最终还是因为其他原因而坚持使用 Tomcat 6。
    • Tomcat 确实支持 Tomcat 管理的类中的 @Resource 注解。在这些类中,JSP-s、Servlet、过滤器等。但 Srinivas 试图将资源注入自己的 DAO 类(它不是由 Tomcat 管理的)。我想就是这样。
    • 参见 Java EE 5 教程,表 3-1“WebComponentsThatAcceptResourceInjections”
    【解决方案3】:

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

    问题是你使用的:

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

    这会奏效的:

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

    我会注意到,如果您使用的是 Apache TomEE(Tomcat 的 JavaEE 认证版本),那么在您的 context.xml 没有任何更改的情况下,两者都可以正常工作

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

    comparison here

    【讨论】:

    • 这对您来说适用于 Tomcat 7 吗?它在 Tomcat 6 中工作,但在我升级到 Tomcat 7 时停止工作。
    • 我在使用 Weld 的 Tomcat 8 上,这是正确的答案。
    • 救生员只需简单地使用@autowired
    猜你喜欢
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多