Получение исключения нулевого указателя @Resource аннотации в Tomcat 7 - PullRequest
4 голосов
/ 24 октября 2011

Вот мой элемент Resource в 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"/> 

Вот моя ссылка на Resource в 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;

Когда я пытаюсь создать объект соединения, используя getConnection () на ds, я получаю исключение нулевого указателя во время выполнения:

    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");

Куда я не так?

Ответы [ 3 ]

7 голосов
/ 08 февраля 2012

Примечание. Tomcat поддерживает поддержку @Resource инъекции.Вы были действительно очень близки.

Проблема, которую вы использовали:

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

Это сработало бы:

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

Отмечу, что если бы вы использовали Apache TomEE (версия Tomcat, сертифицированная для JavaEE), оба варианта работали бы без изменений в context.xml

Кроме того, вы получаете CDI, EJB, JPA и другие вещи, упомянутые в некоторых других ответах.

Маленький сравнение здесь .

3 голосов
/ 24 октября 2011

Tomcat сам по себе не поддерживает @Resource инъекцию.Другими словами, контейнер сервлета не распознает эту аннотацию и не может ничего с ней сделать.Ручной поиск работает, потому что ресурс определен правильно.

Вам нужна некоторая структура внедрения зависимостей:

  • spring
  • CDI (часть веб-профиля JavaEE6)
  • EJB (часть веб-профиля JavaEE6, не совсем "DI framework")
0 голосов
/ 24 октября 2011

Здесь много чего происходит. Во-первых, вам не нужен ресурс-ref в вашем файле web.xml, если вы не позволите серверу приложений управлять источником данных. Это полезно, если вы используете что-то вроде IBM WAS или Apache Tomcat и задаете параметры источника данных в конфигурации вашего сервера. Если вы сделаете это, вы захотите сохранить ссылку на ресурс и добавить фабричный бин jndi:

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

По совпадению, я почти уверен, что ваша установка будет работать сейчас, если вы просто добавите этот компонент.

Исходя из того, что у вас есть, или если вы используете фабричный бин jndi, все, что вам нужно сделать, это автоматически связать боб оттуда:

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

Если вы хотите проверить состояние вашего компонента, вы всегда можете реализовать InitializingBean, что заставит вас реализовать afterPropertiesSet

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

Хотя 1 @ Autowired` должен пройти через исключение, если он не может автоматически подключаться по умолчанию.

Стоит также отметить, что лучше использовать конструктор:

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