Можно ли избавиться от этой дополнительной аннотации @Resource для DataSource, управляемого Websphere?

У меня есть приложение EJB, использующее модуль сохраняемости OpenJPA из WebSphere 8.5. DataSource настраивается в WebSphere со следующими параметрами:

  • Имя: MYAPP_001
  • Имя JNDI: jdbc/MYAPP/DS001
  • Псевдоним проверки подлинности, управляемый компонентом: MYAPP_001.
  • Псевдоним конфигурации сопоставления: (нет)
  • Псевдоним проверки подлинности, управляемый контейнером: (нет)
  • Формат java:comp/env/ представляет собой ссылку на ресурс, поэтому вы должны каким-то образом определить его. У вас есть несколько вариантов, чтобы не определять фиктивный источник данных:

Блок сохраняемости настроен так:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
       http://java.sun.com/xml/ns/persistence/persistence
@PersistenceContext(name = "myapp")
private EntityManager em;
0.xsd" version="2.0"> <persistence-unit name="myapp" transaction-type="JTA"> <jta-data-source>java:comp/env/jdbc/MYAPP/DS001</jta-data-source> <class>...</class> <properties> ... </properties> </persistence-unit> </persistence>

Теперь я импортирую его в EJB:

@PersistenceContext(name = "myapp")
private EntityManager em;

Проблема в том, что при следующей конфигурации источник данных не может быть разрешен:

Что мне нужно, так это обеспечить сопоставление ресурсов DataSource в любом из EJB, используя EntityManager:

Это очень неэлегантное решение для меня, потому что:

@Resource(name = "java:comp/env/jdbc/MYAPP/DS001", lookup = "jdbc/MYAPP/DS001", shareable = true, authenticationType = Resource.AuthenticationType.CONTAINER)
private DataSource ds;

Это очень запутанно. Его нужно объявить только один раз в любом компоненте EJB, использующем @PersistenceContext. Тот DataSource может вообще не использоваться в коде Java, и в моем случае он не используется. Будет трудно понять, что делает это объявление в этом файле и почему оно только в одном файле.

  1. Это дублирование конфигурации, предоставленной в другом месте. Мне нужно еще раз указать имя ресурса (оно уже было указано в файле persistance.xml).

  2. Это сохранение конфигурации в исходном коде. Довольно грязный антипаттерн.

  3. Технически для этого требуется javax.annotation.Resource из Java 7, в то время как мой проект использует Java 6. Но среда выполнения WebSphere изменила версию этой аннотации, поэтому все работает, но требует компиляции с помощью javac из среды выполнения WebSphere вместо стандартного JDK.

  4. Можно ли избавиться от этой аннотации? Что мне нужно использовать в качестве альтернативы?

Область: ячейки:pxxxxNodexxCell


person Danubian Sailor    schedule 04.07.2014    source источник


Ответы (1)


1. Определите ресурс на уровне класса — это полностью поддерживается в Java 6 — и правильно определяет ссылку на ресурс:

Еще одно пояснение к этому и вашему коду - в имени вы на самом деле должны просто указать ссылочное имя (без java:comp/env), а затем в файле persistence.xml вы поместите java:comp/env/refName. Поиск определяет фактическое имя JNDI, зарегистрированное на сервере. Вы можете пропустить определение поиска и привязать ссылку к ресурсу во время установки или через файл привязки.

@Resource(name="jdbc/dsRef", type=javax.sql.DataSource.class, lookup="jdbc/DS")
public class MyBean implements MyBeanLocal {

2. Используйте дескриптор развертывания

Создайте дескриптор развертывания (web.xml или ejb-jar.xml) и определите в нем ссылку на ресурс для каждого EJB. Вам больше не нужно размещать DataSource с @Resource в своем классе.

3. Не использовать ссылку вообще

Хотя я бы этого не рекомендовал, вы можете использовать фактическое имя источника данных JNDI сервера в файле persistence.xml. Тогда вам не нужен источник данных в EJB, поскольку ссылка не используется.

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

<jta-data-source>jdbc/MYAPP/DS001</jta-data-source>

И в уточнении вашего комментария:

Технически для этого требуется javax.annotation.Resource из Java 7, в то время как мой проект использует Java 6. Но среда выполнения WebSphere изменила версию этой аннотации, поэтому все работает, но требует компиляции с javac из среды выполнения WebSphere вместо стандартного JDK.

javax.annotation.Resource является частью Java EE 6, который реализован WebSphere. Вам не нужна Java v7, а нужен полноценный сервер приложений Java EE 6. Вы создаете приложение Java EE, а не приложение Java SE. Вот почему вам нужны классы контейнеров для разрешения этой аннотации. Ничего не "изменено" WebSphere, просто следует спецификации.

Это все отличная информация. В качестве уточнения,

@Resource(name="jdbc/dsRef", type=javax.sql.DataSource.class, lookup="jdbc/DS")
public class MyBean implements MyBeanLocal {
не добавлялся до Java SE 7, но он требуется для EE 6, поэтому серверы приложений (включая WAS) переопределяют этот класс аннотаций. Это вызывает сложности при компиляции, но, как вы предложили, вы можете использовать альтернативы, такие как имя поиска в DD или привязку (файл bnd или развертывание).

person Gas    schedule 04.07.2014
comment
Причина: org.apache.openjpa.persistence.ArgumentException: поставщик сохраняемости пытается использовать свойства в файле persistence.xml для разрешения источника данных. Драйвер Java Database Connectivity (JDBC) или имя класса источника данных должны быть указаны в свойстве openjpa.ConnectionDriverName или javax.persistence.jdbc.driver. В конфигурации доступны следующие свойства: "WsJpaJDBCConfigurationImpl@83f2eb8d: PDQ отключено: AccessIntent Task=disable". в org.apache.openjpa.jdbc.schema.DataSourceFactory.newDataSource(DataSourceFactory.java:72) в org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.createConnectionFactory(JDBCurationImpl.java:849) в org.apache.openjpa.jdbc .conf.JDBCConfigurationImpl.getDBDictionaryInstance(JDBCConfigurationImpl.java:602) в org.apache.openjpa.jdbc.meta.MappingRepository.endConfiguration(MappingRepository.java:1518) в org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations) .java:531) в org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations.java:456) в org.apache.openjpa.lib.conf.PluginValue.instantiate(PluginValue.java:121) в org. apache.openjpa.conf.MetaDataRepositoryValue.instantiate(MetaDataRepositoryValue.java:68) в org.apache.openjpa.lib.conf.ObjectValue.instantiate(ObjectValue.java:83) в org.apache.openjpa.conf.OpenJPAConfigurationImpl.newMetaDataRepositoryInstance( OpenJPAConfigurationImpl.j ava:967) в org.apache.openjpa.conf.OpenJPAConfigurationImpl.getMetaDataRepositoryInstance(OpenJPAConfigurationImpl.java:958) в org.apache.openjpa.kernel.AbstractBrokerFactory.makeReadOnly(AbstractBrokerFactory.java:644) в org.apache.openjpa.kernel .AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:203) в org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156) в org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227) com.ibm.ws.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:72) в com.ibm.ws.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:35) в com.ibm.ws.jpa.management.JPAEMPool. getEntityManager(JPAEMPool.java:167) в com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:247) в com.ibm.ws.jpa.management. JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:179) в com.ibm.ws.jpa.management.JPAEntityManager.createQuery(JPAEntityManager.java:299) - person Brett Kail; 08.07.2014