После этого я начал работать с JSF, который требует только аннотированных атрибутов с @EJB или @Resource для связи с бизнес-уровнем. До сих пор это был большой опыт, пока меня не попросили оценить Vaadin как интерфейсную технологию для бизнес-приложений.
Прежде чем заходить слишком далеко, я прочитал статью « Добавление JPA в демонстрационную версию адресной книги », опубликованную в вики Vaadin, в которой объясняется, как вызывать EJB из классов Vaadin для извлечения и сохранения данных из бизнес-уровня. EJB-компоненты используют JPA для получения и помещения данных в базу данных. Они предложили вызывать EJB из собственного сервлета, который, согласно спецификации Java EE, может выполнять вызовы EJB с использованием CDI.
Если у нас есть 1 или 3 EJB для вызова, кажется, это подходящее решение, но что делать в Сервлете, когда у нас есть ~ 40 EJB для работы? Как передать все эти ссылки в класс приложений Ваадина? Интерфейс этого класса может сойти с ума! Вот почему я считаю, что поиск с использованием JNDI является желательным.
Следующий код — это сервисный локатор, который я использую в Proof of Concept (PoC).
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
import java.util.Collections;import java.util.HashMap;import java.util.Map;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;public class MyServiceLocator { private Context initialContext; private Map cache; private static ClientServiceLocator ourInstance = new ClientServiceLocator(); public static ClientServiceLocator getInstance() { return ourInstance; } private ClientServiceLocator() { try { this.initialContext = new InitialContext(); this.cache = Collections.synchronizedMap(new HashMap()); } catch(NamingException ne) { System.err.printf( "Error in CTX looking up %s because of %s while %s", ne.getRemainingName(), ne.getCause(), ne.getExplanation()); } } public Object lookupEjb(String ejbName) { if(this.cache.containsKey(ejbName)) { return this.cache.get(ejbName); } else { try { Object ejbRef = initialContext.lookup("java:comp/env/"+ ejbName); this.cache.put(ejbName, ejbRef); return ejbRef; } catch (NamingException ne) { throw new RuntimeException(ne); } catch (Exception e) { throw new RuntimeException(e); } } }} |
Класс MyServiceLocator следует шаблону проектирования Singleton , следя за тем, чтобы существовал только один экземпляр объекта для обслуживания всех запросов из веб-приложения. Уникальный экземпляр создается в процессе инициализации класса, и поскольку конструктор является закрытым, экземпляр класса не может быть создан другим классом, будучи доступным только через метод getInstance (). Конструктор инициализирует контекст и создает синхронизированную карту, где мы храним все ссылки, уже созданные. Метод lookupEjb ( String ejbName ) находит EJB- компоненты , имена которых доступны в локальном контексте JNDI. Этот метод работает только для тех EJB-компонентов, ссылки на которые объявлены в файле web.xml, как указано ниже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
<web-app version="2.5" xsi:schemalocation="http://java.sun.com/xml/ns/javaee <display-name>Information Systems</display-name> ... <ejb-local-ref> <ejb-ref-name>InformationSystemBean</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local> example.business.InformationSystemBeanLocal </local> <ejb-link> eac-architecture-ejb.jar#InformationSystemBean </ejb-link> </ejb-local-ref></web-app> |
Тег <ejb-local-ref> используется для объявления ссылки на локальный EJB. В приведенном выше примере отображается только один EJB. Таким образом, вы должны повторить это для каждого EJB, который вы хотите отобразить. Подробности об этом теге можно найти здесь . После объявления мы можем получить экземпляр EJB в любой части приложения, используя следующий код:
|
1
2
3
|
private InformationSystemLocal informationSystemBsn = (InformationSystemLocal)MyServiceLocator.getInstance() .lookupEjb("InformationSystemBean"); |
Переменная вводится с помощью локального интерфейса EJB, который называется InformationSystemLocal . Локатор службы возвращает экземпляр EJB с именем InformationSystemBean , который по умолчанию является классом реализации EJB. Обратите внимание, что ни один из приведенных выше кодов не требуется при использовании CDI. Вызов AjudaBsn будет просто так:
|
1
2
|
@EJBprivate InformationSystemLocal informationSystemBsn; |
CDI хорош и элегантен, но не широко применяется. То, как это реализовано сегодня, является основным недостатком спецификации Java EE. Возможно, есть веская причина, по которой аннотации EJB не работают в каждом классе Java. Я просто не вижу этой загадочной причины, потому что Spring уже давно решает эту проблему, просто используя аспектную ориентацию.
Ссылка: EJB Lookup в приложении Vaadin от нашего партнера JCG Хильдеберто Мендонки в блоге Хильдеберто
Статьи по Теме :