По сути, для этого необходимо написать так называемое портативное расширение CDI .
Но, поскольку оно довольно длинное и требует нескольких настроек, позвольте мне объяснить это подробнее.
Переносимое расширение
Как объясняет документ сварки, первым шагом является создание класса, реализующего интерфейс тегирования Extension
, в котором будет написан код, соответствующий интересным событиям CDI.,В этом конкретном случае наиболее интересное событие, на мой взгляд, AfterBeanDiscovery .Действительно, это событие происходит после того, как все «локальные» bean-компоненты были найдены с помощью CDI.
Таким образом, расширение записи, более того, пишет обработчик для этого события:
public void loadJndiBeansFromServer(
@Observes AfterBeanDiscovery beanDiscovery, BeanManager beanManager)
throws NamingException, ClassNotFoundException, IOException {
// Due to my inability to navigate in server JNDI naming (a weird issue in Glassfish naming)
// This props maps interface class to JNDI name for its server-side
Properties interfacesToNames = extractInterfacesToNames();
// JNDI properties
Properties jndiProperties = new Properties();
Context context = new InitialContext();
for (Entry<?, ?> entry : interfacesToNames.entrySet()) {
String interfaceName = entry.getKey().toString();
Class<?> interfaceClass = Class.forName(interfaceName);
String jndiName = entry.getValue().toString();
Bean<?> jndiBean = createJndIBeanFor(beanManager, interfaceClass, jndiName, jndiProperties);
beanDiscovery.addBean(jndiBean);
}
}
Создание bean-компонента не является тривиальной операцией: оно требует преобразования «базовых» объектов Java-отражения в более сложные объекты сварки (ну, в моем случае)
private <Type> Bean<Type> createJndIBeanFor(BeanManager beanManager, Class<Type> interfaceClass,
String jndiName, Properties p) {
AnnotatedType<Type> annotatedType = beanManager
.createAnnotatedType(interfaceClass);
// Creating injection target in a classical way will fail, as interfaceClass is the interface of an EJB
JndiBean<Type> beanToAdd = new JndiBean<Type>(interfaceClass, jndiName, p);
return beanToAdd;
}
Наконец, нужно написать класс JndiBean.Но раньше требуется небольшое перемещение в области аннотаций.
Определение используемой аннотации
Сначала я использовал @EJB
.Идея bad : Weld использует вызов метода-аннотации для вызова метода result для создания хеш-кода bean-компонента!Итак, я создал свою собственную аннотацию @JndiClient
, которая не содержит ни методов, ни констант, чтобы она была максимально простой.
Создание клиентского компонента JNDI
Два понятияслиться здесь.
- С одной стороны, интерфейс
Bean
кажется (мне) определять, что такое бин. - С другой стороны,
InjectionTarget
определяет, в определенной степени, жизненный цикл этого самого компонента.
Из литературы, которую я смог найти, эти две реализации интерфейсов часто разделяют, по крайней мере, некоторые из ихгосударство.Поэтому я решил использовать их с помощью уникального класса: JndiBean
!
В этом бине большинство методов оставлены пустыми (или имеют значение по умолчанию), за исключением
Bean#getTypes
, который должен возвращать удаленный интерфейс EJB и все расширенные интерфейсы @Remote
(так как через этот интерфейс могут вызываться методы из этих интерфейсов) Bean#getQualifiers
, который возвращает набор, содержащий только один элемент: AnnotationLiteral
, соответствующий @JndiClient
интерфейсу. Contextual#create
(вызабыл расширенный Бин Contextual, не так ли?) который выполняет поиск:
@Override
public T create(CreationalContext<T> arg0) {
// Some classloading confusion occurs here in my case, but I guess they're of no interest to you
try {
Hashtable contextProps = new Hashtable();
contextProps.putAll(jndiProperties);
Context context = new InitialContext(contextProps);
Object serverSide = context.lookup(jndiName);
return interfaceClass.cast(serverSide);
} catch (NamingException e) {
// An unchecked exception to go through weld and break the world appart
throw new LookupFailed(e);
}
}
И это все
Использование?
Ну,теперь, в своем коде Java-клиента Glassfish, я могу написать такие вещи, как
private @Inject @JndiClient MyRemoteEJB instance;
И это работает без проблем
Будущее?
Ну, пока,учетные данные пользователя не управляются, но я полагаю, что это вполне возможно при использовании C CDI: Контексты ... о нет!Не контексты: Области применения !