Статьи

Поиск EJB в приложении Vaadin

Прошло много времени с тех пор, как я использовал последний сервисный локатор. Я думал, что больше не будет необходимости, учитывая зрелость CDI Java EE (контексты и внедрение зависимостей). Моей первой реализацией было использование EJB-компонентов в веб-приложении на основе Struts.

После этого я начал работать с 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
@EJB
private InformationSystemLocal informationSystemBsn;

CDI хорош и элегантен, но не широко применяется. То, как это реализовано сегодня, является основным недостатком спецификации Java EE. Возможно, есть веская причина, по которой аннотации EJB не работают в каждом классе Java. Я просто не вижу этой загадочной причины, потому что Spring уже давно решает эту проблему, просто используя аспектную ориентацию.

Ссылка: EJB Lookup в приложении Vaadin от нашего партнера JCG Хильдеберто Мендонки в блоге Хильдеберто

Статьи по Теме :