EJB - Краткое руководство

EJB означает Enterprise Java Beans. EJB - неотъемлемая часть платформы J2EE. Платформа J2EE имеет компонентную архитектуру, обеспечивающую многоуровневые, распределенные и высокотранзакционные функции для приложений корпоративного уровня.

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

Мы подробно обсудим EJB 3.0 в этом руководстве.

Типы

EJB в основном делится на три категории; В следующей таблице перечислены их имена с краткими описаниями -

S.No Тип и описание
1

Session Bean

Сессионный компонент хранит данные конкретного пользователя для одного сеанса. Это может бытьstateful или же stateless. Он менее ресурсоемкий по сравнению с entity-компонентом. Сессионный компонент уничтожается, как только пользовательский сеанс завершается.

2

Entity Bean

Entity beansпредставляют собой постоянное хранилище данных. Пользовательские данные могут быть сохранены в базе данных через объектные компоненты, а позже могут быть получены из базы данных в объектных компонентах.

3

Message Driven Bean

Message driven beansиспользуются в контексте JMS (Java Messaging Service). Компоненты, управляемые сообщениями, могут получать сообщения JMS от внешних объектов и действовать соответствующим образом.

Льготы

Ниже приведены важные преимущества EJB:

  • Упрощенная разработка крупномасштабных приложений корпоративного уровня.

  • Сервер приложений / контейнер EJB предоставляет большинство сервисов системного уровня, таких как обработка транзакций, ведение журнала, балансировка нагрузки, механизм сохранения, обработка исключений и т. Д. Разработчик должен сосредоточиться только на бизнес-логике приложения.

  • Контейнер EJB управляет жизненным циклом экземпляров EJB, поэтому разработчику не нужно беспокоиться о том, когда создавать / удалять объекты EJB.

EJB - это фреймворк для Java, поэтому самым первым требованием является наличие Jава Dразвитие Kон (JDK) установлен на вашем компьютере.

Системные требования

JDK 1.5 или выше.
объем памяти нет минимальных требований.
Дисковое пространство нет минимальных требований.
Операционная система нет минимальных требований.

Шаг 1. Проверьте установку Java в вашей системе

Теперь откройте консоль и выполните следующее java команда.

Операционные системы Задача Команда
Windows Открыть командную консоль c: \> java -версия
Linux Открыть командный терминал $ java -версия
Mac Открыть Терминал машина: ~ joseph $ java -version

Давайте проверим вывод для всех операционных систем -

Операционные системы Вывод
Windows

версия java "1.6.0_21"

Среда выполнения Java (TM) SE (сборка 1.6.0_21-b11)

64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 23.21-b01, смешанный режим)

Linux

версия java "1.6.0_21"

Среда выполнения Java (TM) SE (сборка 1.6.0_21-b11)

64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 23.21-b01, смешанный режим)

Mac

версия java "1.6.0_21"

Среда выполнения Java (TM) SE (сборка 1.6.0_21-b11)

64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 23.21-b01, смешанный режим)

Если у вас не установлена ​​Java, установите Java Software Development Kit (SDK) с сайта www.oracle.com . Мы предполагаем, что Java 1.6.0_21 является установленной версией этого руководства.

Шаг 2 - Установите среду JAVA

Установить JAVA_HOMEпеременная окружения, чтобы указать местоположение базового каталога, в котором установлена ​​Java в вашей системе. Например,

Операционные системы Вывод
Windows Установите для переменной среды JAVA_HOME значение C: \ Program Files \ Java \ jdk1.6.0_21
Linux экспорт JAVA_HOME = / usr / local / java-current
Mac экспорт JAVA_HOME = / Библиотека / Java / Home

Добавьте расположение компилятора Java в системный путь.

Операционные системы Вывод
Windows Добавьте строку C: \ Program Files \ Java \ jdk1.6.0_21 \ bin в конец системной переменной Path.
Linux экспорт PATH =$PATH:$JAVA_HOME / bin /
Mac не требуется

Проверьте установку Java с помощью java -version команда, описанная выше.

Шаг 3 - Загрузите и установите IDE NetBeans

Загрузите последнюю версию IDE NetBeans с сайта netbeans.org . На момент написания этого руководства я загрузил Netbeans 7.3, который поставляется вместе с JDK 1.7, по следующей ссылке www.oracle.com

Операционные системы Имя установщика
Windows Netbeans 7.3
Linux Netbeans 7.3
Mac Netbeans 7.3

Шаг 4 - Настройка сервера приложений JBoss

Вы можете загрузить последнюю версию JBoss Server с www.jboss.org . Скачайте архив согласно платформе. Распакуйте Jboss в любое место на вашем компьютере.

Операционные системы Имя файла
Windows jboss-5.1.0.GA-jdk6.zip
Linux jboss-5.1.0.GA-src.tar.gz
Mac jboss-5.1.0.GA-src.tar.gz

Шаг 5 - Настройте плагины JEE для Netbeans

Откройте окно плагина, выбрав Инструменты> Плагины. Откройте вкладку «Доступный плагин» и выберите «Java EE Base» и «EJB и EAR» в категории «Java Web and EE». Нажмите кнопку установки. Netbeans загрузит и установит соответствующие плагины. Проверьте установку плагинов, используя вкладку «Установленные» (как показано на изображении ниже).

Шаг 6 - Настройте сервер JBoss в Netbeans

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

Откроется мастер добавления экземпляра сервера. Выберите JBoss и на следующем шаге введите соответствующие данные для настройки сервера в netbeans.

Как только все будет настроено, вы увидите следующий экран.

Шаг 7 - Установите сервер базы данных (PostGreSql)

Загрузите последнюю версию сервера базы данных PostGreSql с www.postgresql.org . На момент написания этого руководства я загрузил PostGreSql 9.2.

Операционные системы Имя установщика
Windows PostGreSql 9.2
Linux PostGreSql 9.2
Mac PostGreSql 9.2

Чтобы создать простой модуль EJB, мы будем использовать NetBeans, мастер «Новый проект». В приведенном ниже примере мы создадим проект модуля EJB с именем Component.

Создать проект

В IDE NetBeans выберите File > New Project >. Вы увидите следующий экран

Выберите тип проекта в категории Java EE, Тип проекта как EJB Module. НажмитеNext >кнопка. Вы увидите следующий экран.

Введите название проекта и местоположение. НажмитеNext >кнопка. Вы увидите следующий экран.

Выберите сервер как JBoss Application Server. НажмитеFinishкнопка. Вы увидите следующий проект, созданный NetBeans.

Создать образец EJB

Чтобы создать простой EJB, мы будем использовать мастер «New» NetBeans. В приведенном ниже примере мы создадим класс EJB без сохранения состояния с именем librarySessionBean в проекте EjbComponent.

Выберите проект EjbComponent в окне проводника проекта и щелкните его правой кнопкой мыши. Выбрать,New > Session Bean. Вы увидитеNew Session Bean волшебник.

Введите имя сеансового компонента и имя пакета. НажмитеFinishкнопка. Вы увидите следующие классы EJB, созданные NetBeans.

  • LibrarySessionBean - сессионный компонент без сохранения состояния

  • LibrarySessionBeanLocal - локальный интерфейс для сессионного компонента

Я меняю локальный интерфейс на удаленный, так как мы собираемся получить доступ к нашему EJB в консольном приложении. Удаленный / локальный интерфейс используется для предоставления бизнес-методов, которые должен реализовать EJB.

LibrarySessionBeanLocal переименован в LibrarySessionBeanRemote, а LibrarySessionBean реализует интерфейс LibrarySessionBeanRemote.

LibrarySessionBeanRemote

package com.tutorialspoint.stateless;
 
import java.util.List;
import javax.ejb.Remote;
 
@Remote
public interface LibrarySessionBeanRemote {
   void addBook(String bookName);
   List getBooks();
}

LibrarySessionBean

package com.tutorialspoint.stateless;
 
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
 
@Stateless
public class LibrarySessionBean implements LibrarySessionBeanRemote {
   
   List<String> bookShelf;    
   
   public LibrarySessionBean() {
      bookShelf = new ArrayList<String>();
   }
    
   public void addBook(String bookName) {
      bookShelf.add(bookName);
   }    
 
   public List<String> getBooks() {
      return bookShelf;
   }
}

Постройте проект

  • Выберите проект EjbComponent в окне Project Explorer.
  • Щелкните его правой кнопкой мыши, чтобы открыть контекстное меню.
  • Выберите очистить и построить.

Вы увидите следующий вывод в выводе консоли NetBeans.

ant -f C:\\EJB\\EjbComponent clean dist
init:
undeploy-clean:
deps-clean:
Deleting directory C:\EJB\EjbComponent\build
Deleting directory C:\EJB\EjbComponent\dist
clean:
init:
deps-jar:
Created dir: C:\EJB\EjbComponent\build\classes
Copying 3 files to C:\EJB\EjbComponent\build\classes\META-INF
Created dir: C:\EJB\EjbComponent\build\empty
Created dir: C:\EJB\EjbComponent\build\generated-sources\ap-source-output
Compiling 2 source files to C:\EJB\EjbComponent\build\classes
warning: [options] bootstrap class path not set in conjunction with -source 1.6
Note: C:\EJB\EjbComponent\src\java\com\tutorialspoint\stateless
\LibraryPersistentBean.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 warning
compile:
library-inclusion-in-archive:
Created dir: C:\EJB\EjbComponent\dist
Building jar: C:\EJB\EjbComponent\dist\EjbComponent.jar
dist:
BUILD SUCCESSFUL (total time: 3 seconds)

Запустите сервер приложений

  • Выберите сервер приложений JBoss в окне «Серверы в службах».
  • Щелкните его правой кнопкой мыши, чтобы открыть контекстное меню.
  • Выберите начало.

Вы увидите следующий вывод в NetBeans, вывод на сервере приложений JBoss.

Calling C:\jboss-5.1.0.GA\bin\run.conf.bat
=========================================================================
 
   JBoss Bootstrap Environment
 
   JBOSS_HOME: C:\jboss-5.1.0.GA
 
   JAVA: C:\Program Files (x86)\Java\jdk1.6.0_21\bin\java
 
   JAVA_OPTS: -Dprogram.name=run.bat -Xms128m -Xmx512m -server
 
   CLASSPATH: C:\jboss-5.1.0.GA\bin\run.jar
 
=========================================================================
 
16:25:50,062 INFO  [ServerImpl] Starting JBoss (Microcontainer)...
16:25:50,062 INFO  [ServerImpl] Release ID: JBoss 
   [The Oracle] 5.1.0.GA (build: SVNTag=JBoss_5_1_0_GA date=200905221634)
...
 
16:26:40,420 INFO  [TomcatDeployment] deploy, ctxPath=/admin-console
16:26:40,485 INFO  [config] Initializing Mojarra (1.2_12-b01-FCS) for context '/admin-console'
16:26:42,362 INFO  [TomcatDeployment] deploy, ctxPath=/
16:26:42,406 INFO  [TomcatDeployment] deploy, ctxPath=/jmx-console
16:26:42,471 INFO  [Http11Protocol] Starting Coyote HTTP/1.1 on http-127.0.0.1-8080
16:26:42,487 INFO  [AjpProtocol] Starting Coyote AJP/1.3 on ajp-127.0.0.1-8009
16:26:42,493 INFO  [ServerImpl] JBoss (Microcontainer) 
   [5.1.0.GA (build: SVNTag=JBoss_5_1_0_GA date=200905221634)] Started in 52s:427ms

Развернуть проект

  • Выберите проект EjbComponent в окне Project Explorer.
  • Щелкните его правой кнопкой мыши, чтобы открыть контекстное меню.
  • Выберите Развернуть.

Вы увидите следующий вывод в выводе консоли NetBeans.

ant -f C:\\EJB\\EjbComponent -DforceRedeploy=true -Ddirectory.deployment.supported=false -Dnb.wait.for.caches=true run
init:
deps-jar:
compile:
library-inclusion-in-archive:
Building jar: C:\EJB\EjbComponent\dist\EjbComponent.jar
dist-directory-deploy:
pre-run-deploy:
Checking data source definitions for missing JDBC drivers...
Distributing C:\EJB\EjbComponent\dist\EjbComponent.jar to [org.jboss.deployment.spi.LocalhostTarget@1e4f84ee]
Deploying C:\EJB\EjbComponent\dist\EjbComponent.jar
Application Deployed
Operation start started
Operation start completed
post-run-deploy:
run-deploy:
run:
BUILD SUCCESSFUL (total time: 2 seconds)

Вывод журнала сервера приложений JBoss

16:30:00,963 INFO  [DeployHandler] Begin start, [EjbComponent.jar]
...
16:30:01,233 INFO  [Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@12038795{vfszip:/C:/jboss-5.1.0.GA/server/default/deploy/EjbComponent.jar/}
...
16:30:01,281 INFO  [JBossASKernel]    jndi:LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote
16:30:01,281 INFO  [JBossASKernel]    Class:com.tutorialspoint.stateless.LibrarySessionBeanRemote
16:30:01,281 INFO  [JBossASKernel]    jndi:LibrarySessionBean/remote
16:30:01,281 INFO  [JBossASKernel]  Added bean(jboss.j2ee:jar=EjbComponent.jar,name=
LibrarySessionBean,service=EJB3) to KernelDeployment of: EjbComponent.jar
16:30:01,282 INFO  [JBossASKernel] installing bean: jboss.j2ee:jar=EjbComponent.jar,name=BookMessageHandler,service=EJB3
16:30:01,282 INFO  [JBossASKernel]   with dependencies:
16:30:01,282 INFO  [JBossASKernel]   and demands:
16:30:01,282 INFO  [JBossASKernel]    jboss.ejb:service=EJBTimerService
...
16:30:01,283 INFO  [EJB3EndpointDeployer] Deploy 
AbstractBeanMetaData@5497cb{name=jboss.j2ee:jar=EjbComponent.jar, 
name=LibrarySessionBean, service=EJB3_endpoint bean=org.jboss.ejb3.endpoint.deployers.impl.EndpointImpl properties=[container] constructor=null autowireCandidate=true}
...
16:30:01,394 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibrarySessionBean,service=EJB3
16:30:01,395 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBean ejbName: LibrarySessionBean
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibrarySessionBean/remote - EJB3.x Default Remote Business Interface
   LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibrarySessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBean ejbName: LibrarySessionBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
 
   LibrarySessionBean/remote - EJB3.x Default Remote Business Interface
   LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote - EJB3.x Remote Business Interface

Создать клиента для доступа к EJB

  • В IDE NetBeans выберите File > New Project >.

  • Выберите тип проекта в категории Java, Тип проекта как Java Application. Нажмите кнопку Далее>

  • Введите название проекта и местоположение. НажмитеFinish >кнопка. Мы выбрали имя EjbTester.

  • Щелкните правой кнопкой мыши имя проекта в окне проводника проекта. Выбратьproperties.

  • Добавьте проект компонента EJB, созданный ранее в библиотеках, используя Add Project кнопка в compile таб.

  • Добавить библиотеки jboss с помощью Add jar/folder кнопка в compileтаб. Библиотеки Jboss могут находиться в <папка установки jboss >> папка клиента.

Создайте jndi.properties в рамках проекта, скажем, EjbTester.

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost

Создайте пакет com.tutorialspoint.test и класс EJBTester.java под ним.

EJBTester.java

package com.tutorialspoint.test;
 
import com.tutorialspoint.stateless.LibrarySessionBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
 
public class EJBTester {
   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   public static void main(String[] args) {
 
      EJBTester ejbTester = new EJBTester();
 
      ejbTester.testStatelessEjb();
   }
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   private void testStatelessEjb() {
      try {
         int choice = 1; 
         LibrarySessionBeanRemote libraryBean = 
         (LibrarySessionBeanRemote)ctx.lookup("LibrarySessionBean/remote");
         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();                    
               libraryBean.addBook(bookName);          
            }else if (choice == 2) {
               break;
            }
         }
         List<String> booksList = libraryBean.getBooks();
         System.out.println("Book(s) entered so far: " + booksList.size());
         for (int i = 0; i < booksList.size(); ++i) {
            System.out.println((i+1)+". " + booksList.get(i));
         }
         LibrarySessionBeanRemote libraryBean1 = 
         (LibrarySessionBeanRemote)ctx.lookup("LibrarySessionBean/remote");
         List<String> booksList1 = libraryBean1.getBooks();
         System.out.println(
            "***Using second lookup to get library stateless object***");
         System.out.println(
            "Book(s) entered so far: " + booksList1.size());
         for (int i = 0; i < booksList1.size(); ++i) {
            System.out.println((i+1)+". " + booksList1.get(i));
         }
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      } finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }  
}

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
***Using second lookup to get library stateless object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 13 seconds)

В следующих главах мы рассмотрим несколько аспектов этого полного EJB-приложения.

Сессионный компонент без сохранения состояния - это тип корпоративного компонента, который обычно используется для выполнения независимых операций. Сессионный компонент без сохранения состояния в соответствии с его именем не имеет связанного состояния клиента, но он может сохранять состояние своего экземпляра. Контейнер EJB обычно создает пул из нескольких объектов bean без сохранения состояния и использует эти объекты для обработки запроса клиента. Из-за пула не гарантируется, что значения переменных экземпляра будут одинаковыми при поиске / вызовах методов.

Шаги по созданию EJB без сохранения состояния

Ниже приведены шаги, необходимые для создания EJB без сохранения состояния.

  • Создайте удаленный / локальный интерфейс, раскрывающий бизнес-методы.

  • Этот интерфейс будет использоваться клиентским приложением EJB.

  • Используйте аннотацию @Local, если клиент EJB находится в той же среде, где должен быть развернут сеансовый компонент EJB.

  • Используйте аннотацию @Remote, если клиент EJB находится в другой среде, в которой должен быть развернут сеансовый компонент EJB.

  • Создайте сессионный компонент без состояния, реализующий вышеуказанный интерфейс.

  • Используйте аннотацию @Stateless, чтобы обозначить его как bean-компонент без состояния. Контейнер EJB автоматически создает необходимые конфигурации или интерфейсы, читая эту аннотацию во время развертывания.

Удаленный интерфейс

import javax.ejb.Remote;
 
@Remote
public interface LibrarySessionBeanRemote {
   //add business method declarations
}

EJB без сохранения состояния

@Stateless
public class LibrarySessionBean implements LibrarySessionBeanRemote {
   //implement business method 
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования EJB без сохранения состояния.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.stateless, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Create Application, как таковой для этой главы, чтобы понять концепции EJB без сохранения состояния.

2

Создайте LibrarySessionBean.java и LibrarySessionBeanRemote, как описано в главе EJB - Создание приложения . Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

LibrarySessionBeanRemote.java

package com.tutorialspoint.stateless;
 
import java.util.List;
import javax.ejb.Remote;
 
@Remote
public interface LibrarySessionBeanRemote {
   void addBook(String bookName);
   List getBooks();
}

LibrarySessionBean.java

package com.tutorialspoint.stateless;
 
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
 
@Stateless
public class LibrarySessionBean implements LibrarySessionBeanRemote {
    
   List<String> bookShelf;    
 
   public LibrarySessionBean() {
      bookShelf = new ArrayList<String>();
   }
 
   public void addBook(String bookName) {
      bookShelf.add(bookName);
   }    
 
   public List<String> getBooks() {
      return bookShelf;
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibrarySessionBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.stateless.LibrarySessionBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibrarySessionBean/remote - EJB3.x Default Remote Business Interface
   LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibrarySessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBeanRemote ejbName: LibrarySessionBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
 
   LibrarySessionBean/remote - EJB3.x Default Remote Business Interface
   LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibrarySessionBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class EJBTester {
 
   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {
 
      EJBTester ejbTester = new EJBTester();
 
      ejbTester.testStatelessEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testStatelessEjb() {
 
      try {
         int choice = 1; 
 
         LibrarySessionBeanRemote libraryBean =
         LibrarySessionBeanRemote)ctx.lookup("LibrarySessionBean/remote");
 
         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }
 
         List<Book> booksList = libraryBean.getBooks();
 
         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }       
         LibrarySessionBeanRemote libraryBean1 = 
            (LibrarySessionBeanRemote)ctx.lookup("LibrarySessionBean/remote");
         List<String> booksList1 = libraryBean1.getBooks();
         System.out.println(
            "***Using second lookup to get library stateless object***");
         System.out.println(
            "Book(s) entered so far: " + booksList1.size());
         for (int i = 0; i < booksList1.size(); ++i) {
            System.out.println((i+1)+". " + booksList1.get(i));
         }		 
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatelessEjb () поиск в jndi выполняется с именем «LibrarySessionBean / remote» для получения удаленного бизнес-объекта (ejb без сохранения состояния).

  • Затем пользователю отображается пользовательский интерфейс хранилища библиотеки, и его просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент хранит книгу в своей переменной экземпляра.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

  • Затем выполняется еще один поиск по jndi с именем «LibrarySessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB без сохранения состояния) и выполняется вывод книг.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
***Using second lookup to get library stateless object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 13 seconds)

Снова запустите клиент, чтобы получить доступ к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 0
***Using second lookup to get library stateless object***
Book(s) entered so far: 1
1. Learn Java
BUILD SUCCESSFUL (total time: 12 seconds)
  • Показанный выше результат может отличаться в зависимости от того, сколько объектов EJB без сохранения состояния поддерживает JBoss.

  • В случае, если поддерживается один объект EJB без сохранения состояния, вы можете увидеть один и тот же список книг после каждого поиска.

  • Контейнер EJB может возвращать один и тот же объект EJB без сохранения состояния при каждом поиске.

  • Компонент EJB без сохранения состояния сохраняет значение переменной экземпляра до тех пор, пока сервер не будет перезапущен.

Сессионный компонент с отслеживанием состояния - это тип корпоративного компонента, который сохраняет состояние диалога с клиентом. Сессионный компонент с отслеживанием состояния согласно своему имени сохраняет связанное состояние клиента в своих переменных экземпляра. Контейнер EJB создает отдельный сессионный компонент с отслеживанием состояния для обработки каждого запроса клиента. Как только область запроса заканчивается, сессионный компонент с отслеживанием состояния уничтожается.

Шаги по созданию EJB с отслеживанием состояния

Ниже приведены шаги, необходимые для создания EJB с отслеживанием состояния.

  • Создайте удаленный / локальный интерфейс, раскрывающий бизнес-методы.

  • Этот интерфейс будет использоваться клиентским приложением EJB.

  • Используйте аннотацию @Local, если клиент EJB находится в той же среде, где необходимо развернуть сеансовый компонент EJB.

  • Используйте аннотацию @Remote, если клиент EJB находится в другой среде, в которой должен быть развернут сеансовый компонент EJB.

  • Создайте сессионный компонент с отслеживанием состояния, реализующий вышеуказанный интерфейс.

  • Используйте аннотацию @Stateful, чтобы обозначить его как bean-компонент с отслеживанием состояния. Контейнер EJB автоматически создает необходимые конфигурации или интерфейсы, читая эту аннотацию во время развертывания.

Удаленный интерфейс

import javax.ejb.Remote;
 
@Remote
public interface LibraryStatefulSessionBeanRemote {
   //add business method declarations
}

EJB с сохранением состояния

@Stateful
public class LibraryStatefulSessionBean implements LibraryStatefulSessionBeanRemote {
   //implement business method 
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования EJB с отслеживанием состояния.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.stateful, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Создание приложения, как таковой для этой главы, чтобы понять концепции EJB с отслеживанием состояния.

2

Создайте LibraryStatefulSessionBean.java и LibraryStatefulSessionBeanRemote, как описано в главе EJB - Создание приложения . Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

LibraryStatefulSessionBeanRemote.java

package com.tutorialspoint.stateful;
 
import java.util.List;
import javax.ejb.Remote;
 
@Remote
public interface LibraryStatefulSessionBeanRemote {
   void addBook(String bookName);
   List getBooks();
}

LibraryStatefulSessionBean.java

package com.tutorialspoint.stateful;
 
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateful;
 
@Stateful
public class LibraryStatefulSessionBean implements LibraryStatefulSessionBeanRemote {
    
   List<String> bookShelf;    
 
   public LibraryStatefulSessionBean() {
      bookShelf = new ArrayList<String>();
   }
 
   public void addBook(String bookName) {
      bookShelf.add(bookName);
   }    
 
   public List<String> getBooks() {
      return bookShelf;
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryStatefulSessionBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryStatefulSessionBean/remote - EJB3.x Default Remote Business Interface
   LibraryStatefulSessionBean/remote-com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryStatefulSessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote ejbName: LibraryStatefulSessionBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
 
   LibraryStatefulSessionBean/remote - EJB3.x Default Remote Business Interface
   LibraryStatefulSessionBean/remote-com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial = org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs = org.jboss.naming:org.jnp.interfaces
java.naming.provider.url = localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента с отслеживанием состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class EJBTester {
 
   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {
 
      EJBTester ejbTester = new EJBTester();
 
      ejbTester.testStatelessEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testStatelessEjb() {
 
      try {
         int choice = 1; 
 
         LibraryStatefulSessionBeanRemote libraryBean =
         LibraryStatefulSessionBeanRemote)ctx.lookup("LibraryStatefulSessionBean/remote");
 
         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }
 
         List<Book> booksList = libraryBean.getBooks();
 
         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }       
         LibraryStatefulSessionBeanRemote libraryBean1 = 
            (LibraryStatefulSessionBeanRemote)ctx.lookup("LibraryStatefulSessionBean/remote");
         List<String> booksList1 = libraryBean1.getBooks();
         System.out.println(
            "***Using second lookup to get library stateful object***");
         System.out.println(
            "Book(s) entered so far: " + booksList1.size());
         for (int i = 0; i < booksList1.size(); ++i) {
            System.out.println((i+1)+". " + booksList1.get(i));
         }		 
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск в jndi выполняется с именем «LibraryStatefulSessionBean / remote» для получения удаленного бизнес-объекта (ejb с отслеживанием состояния).

  • Затем пользователю показывают пользовательский интерфейс магазина библиотеки, и его просят сделать выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента с сохранением состояния. Сессионный компонент хранит книгу в своей переменной экземпляра.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента с отслеживанием состояния и завершает работу.

  • Затем выполняется еще один поиск в jndi с именем «LibraryStatefulSessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB с отслеживанием состояния) и выполняется вывод списка книг.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans -

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
***Using second lookup to get library stateful object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 13 seconds)

Снова запустите клиент, чтобы получить доступ к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 0
***Using second lookup to get library stateful object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 12 seconds)
  • Показанный выше результат указывает, что для каждого поиска возвращается другой экземпляр EJB с отслеживанием состояния.

  • Объект EJB с отслеживанием состояния сохраняет значение только для одного сеанса. Как и во втором прогоне, мы не получаем никакой стоимости книг.

EJB 3.0, объектный компонент, используемый в EJB 2.0, в значительной степени заменен механизмом сохранения. Теперь объектный компонент - это простой POJO, имеющий отображение с таблицей.

Ниже приведены ключевые действующие лица API персистентности.

  • Entity- Постоянный объект, представляющий запись хранилища данных. Хорошо быть сериализуемым.

  • EntityManager- Интерфейс сохранения для выполнения операций с данными, таких как добавление / удаление / обновление / поиск постоянного объекта (объекта). Это также помогает выполнять запросы, используяQuery интерфейс.

  • Persistence unit (persistence.xml) - Единица сохранения состояния описывает свойства механизма сохранения состояния.

  • Data Source (*ds.xml)- Источник данных описывает свойства, связанные с хранилищем данных, например URL-адрес подключения. имя пользователя, пароль и т. д.

Чтобы продемонстрировать механизм устойчивости EJB, нам нужно выполнить следующие задачи:

  • Step 1 - Создать таблицу в базе данных.

  • Step 2 - Создайте класс Entity, соответствующий таблице.

  • Step 3 - Создать источник данных и блок сохранения состояния.

  • Step 4 - Создайте EJB без сохранения состояния, имеющий экземпляр EntityManager.

  • Step 5- Обновить EJB без сохранения состояния. Добавьте методы для добавления записей и получения записей из базы данных через диспетчер сущностей.

  • Step 6 - Клиент консольного приложения будет обращаться к EJB без сохранения состояния для сохранения данных в базе данных.

Создать таблицу

Создать таблицу books в базе данных по умолчанию postgres.

CREATE TABLE books (
   id     integer PRIMARY KEY,
   name   varchar(50)
);

Создать класс сущности

//mark it entity using Entity annotation 
//map table name using Table annotation
@Entity
@Table(name="books")
public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }

   //mark id as primary key with autogenerated value
   //map database column id with id field
   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }
   ...
}

Создать источник данных и блок сохранения состояния

Источник данных (jboss-ds.xml)

<?xml version = "1.0" encoding = "UTF-8"?>
<datasources>
   <local-tx-datasource>
      <jndi-name>PostgresDS</jndi-name>
      <connection-url>jdbc:postgresql://localhost:5432/postgres</connection-url>
      <driver-class>org.postgresql.driver</driver-class>
      <user-name>sa</user-name>
      <password>sa</password>
      <min-pool-size>5</min-pool-size>
      <max-pool-size>20</max-pool-size>
      <idle-timeout-minutes>5</idle-timeout-minutes>
   </local-tx-datasource>
</datasources>

Единица сохранения состояния (persistence.xml)

<persistence version = "1.0" 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_1_0.xsd">

   <persistence-unit name = "EjbComponentPU" transaction-type = "JTA">
      <jta-data-source>java:/PostgresDS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
      <properties/>
   </persistence-unit>
   
   <persistence-unit name = "EjbComponentPU2" transaction-type = "JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/PostgresDS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
	  
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
      </properties>
   </persistence-unit>
   
</persistence>

Создание EJB без сохранения состояния с экземпляром EntityManager

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   //pass persistence unit to entityManager.
   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {        
      return entityManager.createQuery("From Books").getResultList();
   }
   ...
}

После сборки модуля EJB нам понадобится клиент для доступа к bean-компоненту без сохранения состояния, который мы собираемся создать в следующем разделе.

Пример приложения

Давайте создадим тестовое приложение EJB для проверки механизма устойчивости EJB.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Создание приложения, как таковой для этой главы, чтобы понять концепции сохраняемости EJB.

2

Создайте Book.java в пакете com.tutorialspoint.entity и измените его, как показано ниже.

3

Создайте LibraryPersistentBean.java и LibraryPersistentBeanRemote, как описано в главах EJB - Создание приложения, и измените их, как показано ниже.

4

Создайте jboss-ds.xml вEjbComponent > setup папка и persistence.xml вEjbComponent > src > conf папка. Эти папки можно увидеть на вкладке файлов в Netbeans. Измените эти файлы, как показано выше.

5

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

6

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

7

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB. Измените его, как показано ниже.

EJBComponent (модуль EJB)

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="books")
public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }

   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }    
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryPersistentBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBeanRemote,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEntityEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEntityEjb() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean =
         LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи.

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск в jndi выполняется с именем «LibraryStatefulSessionBean / remote» для получения удаленного бизнес-объекта (ejb с отслеживанием состояния).

  • Затем пользователю отображается пользовательский интерфейс хранилища библиотеки, и его просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент сохраняет книгу в базе данных через вызов EntityManager.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента с отслеживанием состояния и завершает работу.

  • Затем выполняется еще один поиск по jndi с именем «LibraryStatelessSessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB без сохранения состояния) и выполняется вывод списка книг.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans -

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn java
BUILD SUCCESSFUL (total time: 15 seconds)

Снова запустите клиент, чтобы получить доступ к EJB

Перед доступом к EJB перезапустите JBoss.

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Spring
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 2
1. learn java
2. Learn Spring
BUILD SUCCESSFUL (total time: 15 seconds)

В приведенных выше выходных данных говорится, что книги хранятся в постоянном хранилище и извлекаются из базы данных.

Компонент, управляемый сообщениями, - это тип корпоративного компонента, который вызывается контейнером EJB, когда он получает сообщение из очереди или раздела. Компонент, управляемый сообщениями, - это компонент без сохранения состояния, который используется для асинхронного выполнения задачи.

Чтобы продемонстрировать использование bean-компонента, управляемого сообщениями, мы воспользуемся главой EJB-persistence, и нам нужно будет выполнить следующие задачи:

  • Step 1- Создать таблицу в базе данных (см. Главу EJB-Persistence ).

  • Step 2- Создайте класс Entity, соответствующий таблице (см. Главу EJB-Persistence ).

  • Step 3- Создание DataSource и Persistence Unit (см. Главу EJB-Persistence ).

  • Step 4- Создайте EJB без сохранения состояния, имеющий экземпляр EntityManager (см. Главу EJB-Persistence ).

  • Step 5- Обновите методы ejb.Add без сохранения состояния для добавления записей и получения записей из базы данных через диспетчер сущностей (см. Главу EJB-Persistence ).

  • Step 6 - Создайте очередь с именем BookQueue в JBoss default каталог приложений.

  • Step 7 - Клиентское приложение на основе консоли отправит сообщение в эту очередь.

  • Step 8 - Создать bean-компонент, управляемый сообщениями, который будет использовать bean-компонент без сохранения состояния для сохранения данных клиента.

  • Step 9 - EJB-контейнер jboss вызовет указанный выше bean-компонент, управляемый сообщениями, и передаст ему сообщение, которому клиент будет отправлять.

Создать очередь

Создайте файл с именем jbossmq-destinations-service.xml, если он не существует в <JBoss Installation Folder> > server > default > deploy папка.

Здесь мы создаем очередь с именем BookQueue -

jbossmq-destination-service.xml

<mbean code="org.jboss.mq.server.jmx.Queue"  
   name="jboss.mq.destination:service=Queue,name=BookQueue">  
   <depends optional-attribute-name="DestinationManager">
      jboss.mq:service=DestinationManager
   </depends>  
</mbean>

Когда вы запустите JBoss, вы увидите аналогичную запись в журнале jboss.

...
10:37:06,167 INFO  [QueueService] Queue[/queue/BookQueue] started, fullSize=200000, pageSize=2000, downCacheSize=2000
...

Создать объект, управляемый сообщениями

@MessageDriven(
   name = "BookMessageHandler",
   activationConfig = {
      @ActivationConfigProperty( propertyName = "destinationType", 
                                 propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty( propertyName = "destination", 
                                 propertyValue ="/queue/BookQueue")
   }
)
public class LibraryMessageBean implements MessageListener {
 
   @Resource
   private MessageDrivenContext mdctx;  
 
   @EJB
   LibraryPersistentBeanRemote libraryBean;
 
   public LibraryMessageBean() {        
   }
 
   public void onMessage(Message message) {
   }
}
  • LibraryMessageBean снабжен аннотацией @MessageDriven, чтобы пометить его как компонент, управляемый сообщениями.

  • Его свойства определены как destinationType - Queue и destination - / queue / BookQueue.

  • Он реализует интерфейс MessageListener, который предоставляет метод onMessage.

  • В качестве ресурса у него есть MessgeDrivenContext.

  • Бин LibraryPersistentBeanRemote без сохранения состояния внедряется в этот компонент для обеспечения устойчивости.

Создайте проект EjbComponent и разверните его на JBoss. После сборки и развертывания модуля EJB нам нужен клиент для отправки сообщения в очередь jboss.

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования компонента, управляемого сообщениями.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Создание приложения, как таковой для этой главы, чтобы понять концепции сохраняемости EJB.

2

Создайте Book.java в пакете com.tutorialspoint.entity, как описано в главе EJB-Persistence .

3

Создайте LibraryPersistentBean.java и LibraryPersistentBeanRemote, как описано в главе EJB-Persistence .

4

Создайте jboss-ds.xml вEjbComponent > setup папка и persistence.xml вEjbComponent > src > conf папка. Эти папки можно увидеть на вкладке файлов в Netbeans, созданной в главе EJB-Persistence .

5

Создание LibraryMessageBean.java под пакет com.tutorialspoint.messagebean и изменить его , как показано ниже.

6

Создайте очередь BookQueue в Jboss, как описано выше.

7

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

8

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

9

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB. Измените его, как показано ниже.

EJBComponent (модуль EJB)

LibraryMessageBean.java

package com.tutorialspoint.messagebean;
 
import com.tutorialspoint.entity.Book;
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
 
@MessageDriven(
   name = "BookMessageHandler",
   activationConfig = {
      @ActivationConfigProperty( propertyName = "destinationType", 
                                 propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty( propertyName = "destination", 
                                 propertyValue ="/queue/BookQueue")
   }
)
public class LibraryMessageBean implements MessageListener {
 
   @Resource
   private MessageDrivenContext mdctx;  
 
   @EJB
   LibraryPersistentBeanRemote libraryBean;
 
   public LibraryMessageBean() {        
   }
 
   public void onMessage(Message message) {
      ObjectMessage objectMessage = null;
      try {
         objectMessage = (ObjectMessage) message;
         Book book = (Book) objectMessage.getObject(); 
         libraryBean.addBook(book);
 
      } catch (JMSException ex) {
         mdctx.setRollbackOnly();
      }       
   }   
}

EJBTester (клиент EJB)

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.entity.Book;
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class EJBTester {
 
   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {
 
      EJBTester ejbTester = new EJBTester();
 
      ejbTester.testMessageBeanEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testMessageBeanEjb() {
 
      try {
         int choice = 1; 
         Queue queue = (Queue) ctx.lookup("/queue/BookQueue");
         QueueConnectionFactory factory =
         (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
         QueueConnection connection =  factory.createQueueConnection();
         QueueSession session = 
         connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
         QueueSender sender = session.createSender(queue);
 
         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               ObjectMessage objectMessage = 
                  session.createObjectMessage(book);
               sender.send(objectMessage); 
            } else if (choice == 2) {
               break;
            }
         }
 
         LibraryPersistentBeanRemote libraryBean = 
         (LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");
 
         List<Book> booksList = libraryBean.getBooks();
 
         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }   
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск jndi выполняется с именем - "/ queue / BookQueue", чтобы получить доступ к очереди в Jboss. Затем отправитель создается с использованием сеанса очереди.

  • Затем пользователю отображается пользовательский интерфейс хранилища библиотеки, и его просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает название книги, и отправитель отправляет название книги в очередь. Когда контейнер JBoss получает это сообщение в очереди, он вызывает метод onMessage нашего управляемого сообщениями bean-компонента. Затем наш управляемый сообщениями компонент сохраняет книгу, используя метод addBook () сессионного компонента с сохранением состояния. Сессионный компонент сохраняет книгу в базе данных через вызов EntityManager.

  • Если пользователь вводит 2, то выполняется другой поиск jndi с именем «LibraryStatefulSessionBean / remote», чтобы снова получить удаленный бизнес-объект (EJB с отслеживанием состояния), и список книг будет выполнен.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans -

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn EJB
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 2
1. learn java
1. learn EJB
BUILD SUCCESSFUL (total time: 15 seconds)

В выходных данных, показанных выше, говорится, что наш объект, управляемый сообщениями, получает сообщение и сохраняет книгу в постоянном хранилище, а книги извлекаются из базы данных.

Аннотации были введены в Java 5.0. Аннотации предназначены для присоединения дополнительной информации к классу или метаданных класса в его исходном коде. В EJB 3.0 аннотации используются для описания метаданных конфигурации в классах EJB. Таким образом, EJB 3.0 устраняет необходимость описывать данные конфигурации в файлах XML конфигурации.

Контейнер EJB использует инструмент компилятора для создания необходимых артефактов, таких как интерфейсы, дескрипторы развертывания, путем чтения этих аннотаций. Ниже приводится список часто используемых аннотаций.

Старший нет имя Описание
1

javax.ejb.Stateless

Указывает, что данный класс EJB является сеансовым компонентом без сохранения состояния.

Attributes

  • name - Используется для указания имени сеансового компонента.

  • mappedName - Используется для указания JNDI-имени сессионного компонента.

  • description - Используется для описания сессионного компонента.

2

javax.ejb.Stateful

Указывает, что данный класс EJB является сессионным компонентом с отслеживанием состояния.

Attributes

  • name - Используется для указания имени сеансового компонента.

  • mappedName - Используется для указания JNDI-имени сессионного компонента.

  • description - Используется для описания сессионного компонента.

3

javax.ejb.MessageDrivenBean

Указывает, что данный класс EJB является компонентом, управляемым сообщениями.

Attributes

  • name - Используется для указания имени управляемого сообщениями bean-компонента.

  • messageListenerInterface - Используется для указания интерфейса прослушивателя сообщений для управляемого сообщениями bean-компонента.

  • activationConfig - Используется для указания деталей конфигурации управляемого сообщениями bean-компонента в операционной среде управляемого сообщениями bean-компонента.

  • mappedName - Используется для указания JNDI-имени сессионного компонента.

  • description - Используется для описания сессионного компонента.

4

javax.ejb.EJB

Используется для указания или внедрения зависимости как экземпляра EJB в другой EJB.

Attributes

  • name - Используется для указания имени, которое будет использоваться для поиска указанного bean-компонента в среде.

  • beanInterface - Используется для указания типа интерфейса ссылочного bean-компонента.

  • beanName - Используется для указания имени компонента, на который имеется ссылка.

  • mappedName - Используется для указания имени JNDI ссылочного компонента.

  • description - Используется для предоставления описания компонента, на который имеется ссылка.

5

javax.ejb.Local

Используется для указания локального интерфейса (ов) сеансового компонента. Этот локальный интерфейс определяет бизнес-методы сессионного компонента (которые могут быть без состояния или с отслеживанием состояния).

Этот интерфейс используется для предоставления бизнес-методов локальным клиентам, которые работают в том же развертывании / приложении, что и EJB.

Attributes

  • value - Используется для указания списка локальных интерфейсов в виде массива интерфейсов.

6

javax.ejb.Remote

Используется для указания удаленного интерфейса (ов) сеансового компонента. В этом удаленном интерфейсе указаны бизнес-методы сессионного компонента (которые могут быть без состояния или с отслеживанием состояния).

Этот интерфейс используется для предоставления бизнес-методов удаленным клиентам, которые работают в другом развертывании / приложении как EJB.

Attributes

  • value - Используется для указания списка удаленных интерфейсов в виде массива интерфейсов.

7

javax.ejb.Activation ConfigProperty

Используется для указания свойств, необходимых для управляемого сообщениями bean-компонента. Например, конечная точка, пункт назначения, селектор сообщений и т. Д.

Эта аннотация передается как параметр в атрибут ActivationConfig аннотации javax.ejb.MessageDrivenBean.

Attributes

  • propertyName - название собственности.

  • propertyValue - стоимость имущества.

8

javax.ejb.PostActivate

Используется для указания метода обратного вызова жизненного цикла EJB. Этот метод будет вызываться, когда контейнер EJB только что активировал / повторно активировал экземпляр компонента.

Этот интерфейс используется для предоставления бизнес-методов локальным клиентам, которые работают в том же развертывании / приложении, что и EJB.

Обратный вызов - это механизм, с помощью которого можно перехватить жизненный цикл корпоративного компонента. В спецификации EJB 3.0 указаны обратные вызовы, для которых создаются методы обработчика обратных вызовов. Контейнер EJB вызывает эти обратные вызовы. Мы можем определить методы обратного вызова в самом классе EJB или в отдельном классе. EJB 3.0 предоставляет множество аннотаций для обратных вызовов.

Ниже приведен список аннотаций обратного вызова для bean-компонента без состояния.

Аннотации Описание
@PostConstruct Вызывается при первом создании компонента.
@PreDestroy Вызывается, когда компонент удаляется из пула компонентов или уничтожается.

Ниже приведен список аннотаций обратного вызова для bean-компонента с отслеживанием состояния.

Аннотации Описание
@PostConstruct Вызывается при первом создании компонента.
@PreDestroy Вызывается, когда компонент удаляется из пула компонентов или уничтожается.
@PostActivate Вызывается, когда bean-компонент загружается для использования.
@PrePassivate Вызывается, когда компонент возвращается в пул компонентов.

Ниже приведен список аннотаций обратного вызова для bean-компонента, управляемого сообщениями.

Аннотации Описание
@PostConstruct Вызывается при первом создании компонента.
@PreDestroy Вызывается, когда компонент удаляется из пула компонентов или уничтожается.

Ниже приведен список аннотаций обратного вызова для entity-компонента.

Аннотации Описание
@PrePersist Вызывается при создании объекта в базе данных.
@PostPersist Вызывается после создания объекта в базе данных.
@PreRemove Вызывается, когда объект удаляется из базы данных.
@PostRemove Вызывается после удаления объекта из базы данных.
@PreUpdate Вызывается перед обновлением объекта в базе данных.
@PostLoad Вызывается, когда запись извлекается из базы данных и загружается в сущность.

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования различных обратных вызовов в EJB.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.stateless, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Persistence, как таковой для этой главы, чтобы добавить различные обратные вызовы в EJB.

2

Создайте LibrarySessionBean.java и LibrarySessionBeanRemote, как описано в главе EJB - Создание приложения . Остальные файлы оставьте без изменений.

3

Используйте Beans, созданные в главе EJB - Persistence . Добавьте методы обратного вызова, как показано ниже. Остальные файлы оставьте без изменений.

4

Создайте Java-класс BookCallbackListener в пакете com.tutorialspoint.callback . Этот класс продемонстрирует разделение методов обратного вызова.

5

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

6

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

7

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

BookCallbackListener.java

package com.tutorialspoint.callback;

import javax.persistence.PrePersist;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;

import com.tutorialspoint.entity.Book;

public class BookCallbackListener {
    
   @PrePersist
   public void prePersist(Book book) {
      System.out.println("BookCallbackListener.prePersist:" 
         + "Book to be created with book id: "+book.getId());
   }

   @PostPersist
   public void postPersist(Object book) {
      System.out.println("BookCallbackListener.postPersist::"
         + "Book created with book id: "+((Book)book).getId());
   }

   @PreRemove
   public void preRemove(Book book) {
      System.out.println("BookCallbackListener.preRemove:"
         + " About to delete Book: " + book.getId());
   }

   @PostRemove
   public void postRemove(Book book) {
      System.out.println("BookCallbackListener.postRemove::"
         + " Deleted Book: " + book.getId());
   }

   @PreUpdate
   public void preUpdate(Book book) {
      System.out.println("BookCallbackListener.preUpdate::"
         + " About to update Book: " + book.getId());
   }

   @PostUpdate
   public void postUpdate(Book book) {
      System.out.println("BookCallbackListener.postUpdate::"
         + " Updated Book: " + book.getId());
   }

   @PostLoad
   public void postLoad(Book book) {
      System.out.println("BookCallbackListener.postLoad::"
         + " Loaded Book: " + book.getId());
   }
}

Book.java

package com.tutorialspoint.entity;
 
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name="books")
public class Book implements Serializable{
    
   private int id;
   private String name;
 
   public Book() {        
   }
 
   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }
 
   public void setId(int id) {
      this.id = id;
   }
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      this.name = name;
   }    
}

LibraryStatefulSessionBean.java

package com.tutorialspoint.stateful;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Stateful;

@Stateful
public class LibraryStatefulSessionBean 
   implements LibraryStatefulSessionBeanRemote {
   List<String> bookShelf;    

   public LibraryStatefulSessionBean() {
      bookShelf = new ArrayList<String>();
   }

   public void addBook(String bookName) {
      bookShelf.add(bookName);
   }    

   public List<String> getBooks() {
      return bookShelf;
   }

   @PostConstruct
   public void postConstruct() {
      System.out.println("LibraryStatefulSessionBean.postConstruct::"
         + " bean created.");
   }

   @PreDestroy
   public void preDestroy() {
      System.out.println("LibraryStatefulSessionBean.preDestroy:"
         + " bean removed.");
   }

   @PostActivate
   public void postActivate() {
      System.out.println("LibraryStatefulSessionBean.postActivate:"
         + " bean activated.");
   }

   @PrePassivate
   public void prePassivate() {
      System.out.println("LibraryStatefulSessionBean.prePassivate:"
         + " bean passivated.");
   }    
}

LibraryStatefulSessionBeanRemote.java

package com.tutorialspoint.stateful;

import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryStatefulSessionBeanRemote {
   void addBook(String bookName);
   List getBooks();
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean 
   implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {}

   @PersistenceContext(unitName="EntityEjbPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {     
      return entityManager.createQuery("From Book")
         .getResultList();
   }

   @PostConstruct
   public void postConstruct() {
      System.out.println("postConstruct:: LibraryPersistentBean session bean"
         + " created with entity Manager object: ");
   }

   @PreDestroy
   public void preDestroy() {
      System.out.println("preDestroy: LibraryPersistentBean session"
      + " bean is removed ");
   }
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryPersistentBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBeanRemote ejbName: LibraryPersistentBean
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibrarySessionBeanRemote;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.List;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEntityEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEntityEjb() {    
      try {
      int choice = 1; 

      LibraryPersistentBeanRemote libraryBean = 
      (LibraryPersistentBeanRemote)
      ctx.lookup("LibraryPersistentBean/remote");

      while (choice != 2) {
         String bookName;
         showGUI();
         String strChoice = brConsoleReader.readLine();
         choice = Integer.parseInt(strChoice);
         if (choice == 1) {
            System.out.print("Enter book name: ");
            bookName = brConsoleReader.readLine();
            Book book = new Book();
            book.setName(bookName);
            libraryBean.addBook(book);          
         } else if (choice == 2) {
            break;
         }
      }

      List<Book> booksList = libraryBean.getBooks();

      System.out.println("Book(s) entered so far: " + booksList.size());
      int i = 0;
      for (Book book:booksList) {
         System.out.println((i+1)+". " + book.getName());
         i++;
      }           

      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }    
   }    
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatelessEjb () поиск в jndi выполняется с именем «LibrarySessionBean / remote» для получения удаленного бизнес-объекта (EJB без сохранения состояния).

  • Затем пользователю показывается пользовательский интерфейс магазина библиотеки, и его / ее просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент хранит книгу в базе данных.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
BUILD SUCCESSFUL (total time: 13 seconds)

Вывод журнала сервера приложений JBoss

Вы можете найти следующие записи обратного вызова в журнале JBoss

14:08:34,293 INFO  [STDOUT] postConstruct:: LibraryPersistentBean session bean created with entity Manager object
...
16:39:09,484 INFO  [STDOUT] BookCallbackListener.prePersist:: Book to be created with book id: 0
16:39:09,531 INFO  [STDOUT] BookCallbackListener.postPersist:: Book created with book id: 1
16:39:09,900 INFO  [STDOUT] BookCallbackListener.postLoad:: Loaded Book: 1
...

Служба таймера - это механизм, с помощью которого можно построить запланированное приложение. Например, формирование зарплаты 1-го числа каждого месяца. В спецификации EJB 3.0 указана аннотация @Timeout, которая помогает программировать службу EJB в компоненте без состояния или управляемом сообщениями. Контейнер EJB вызывает метод, который аннотируется @Timeout.

Служба таймера EJB - это служба, предоставляемая контейнером EJB, которая помогает создать таймер и запланировать обратный вызов по истечении времени таймера.

Шаги по созданию таймера

Внедрить SessionContext в bean-компонент с помощью аннотации @Resource -

@Stateless
public class TimerSessionBean {

   @Resource
   private SessionContext context;
   ...
}

Используйте объект SessionContext, чтобы получить TimerService и создать таймер. Передайте время в миллисекундах и сообщение.

public void createTimer(long duration) {
   context.getTimerService().createTimer(duration, "Hello World!");
}

Шаги по использованию таймера

Используйте аннотацию @Timeout к методу. Тип возврата должен быть недействительным и передавать параметр типа Timer. Мы отменяем таймер после первого выполнения, иначе он будет продолжать работать после интервалов исправления.

@Timeout
public void timeOutHandler(Timer timer) {
   System.out.println("timeoutHandler : " + timer.getInfo());        
   timer.cancel();
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования службы таймера в EJB.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.timer, как описано в главе EJB - Создание приложения .

2

Создайте TimerSessionBean.java и TimerSessionBeanRemote, как описано в главе EJB - Создание приложения . Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

TimerSessionBean.java

package com.tutorialspoint.timer;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Timer;
import javax.ejb.Stateless;
import javax.ejb.Timeout;

@Stateless
public class TimerSessionBean implements TimerSessionBeanRemote {

   @Resource
   private SessionContext context;

   public void createTimer(long duration) {
      context.getTimerService().createTimer(duration, "Hello World!");
   }

   @Timeout
   public void timeOutHandler(Timer timer) {
      System.out.println("timeoutHandler : " + timer.getInfo());        
      timer.cancel();
   }
}

TimerSessionBeanRemote.java

package com.tutorialspoint.timer;

import javax.ejb.Remote;

@Remote
public interface TimerSessionBeanRemote {
   public void createTimer(long milliseconds);
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - TimerSessionBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.timer.TimerSessionBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   TimerSessionBean/remote - EJB3.x Default Remote Business Interface
   TimerSessionBean/remote-com.tutorialspoint.timer.TimerSessionBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=TimerSessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.timer.TimerSessionBeanRemote ejbName: TimerSessionBean
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.TimerSessionBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testTimerService();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testTimerService() {
      try {
         TimerSessionBeanRemote timerServiceBean = (TimerSessionBeanRemote)ctx.lookup("TimerSessionBean/remote");

         System.out.println("["+(new Date()).toString()+ "]" + "timer created.");
         timerServiceBean.createTimer(2000);            

      } catch (NamingException ex) {
         ex.printStackTrace();
      }
   }
}

EJBTester выполняет следующие задачи.

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testTimerService () поиск jndi выполняется с именем «TimerSessionBean / remote» для получения удаленного бизнес-объекта (EJB без сохранения состояния таймера).

  • Затем вызывается createTimer, передавая 2000 миллисекунд в качестве времени расписания.

  • Контейнер EJB вызывает метод timeoutHandler через 2 секунды.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
[Wed Jun 19 11:35:47 IST 2013]timer created.
BUILD SUCCESSFUL (total time: 0 seconds)

Вывод журнала сервера приложений JBoss

Вы можете найти следующие записи обратного вызова в журнале JBoss

...
11:35:49,555 INFO  [STDOUT] timeoutHandler : Hello World!
...

Спецификация EJB 3.0 предоставляет аннотации, которые можно применять к полям или методам установки для внедрения зависимостей. Контейнер EJB использует глобальный реестр JNDI для поиска зависимости. Следующие аннотации используются в EJB 3.0 для внедрения зависимостей.

  • @EJB - используется для вставки другой ссылки EJB.

  • @Resource - используется для внедрения источников данных или одноэлементных сервисов, таких как sessionContext, timerService и т. Д.

Шаги по использованию @EJB

@EJB можно использовать в полях или методах следующим образом:

public class LibraryMessageBean implements MessageListener {
   //dependency injection on field. 
   @EJB
   LibraryPersistentBeanRemote libraryBean;
   ...
}
public class LibraryMessageBean implements MessageListener {
  
   LibraryPersistentBeanRemote libraryBean;
   
   //dependency injection on method. 
   @EJB(beanName="com.tutorialspoint.stateless.LibraryPersistentBean")
   public void setLibraryPersistentBean(
   LibraryPersistentBeanRemote libraryBean)
   {
      this.libraryBean = libraryBean;
   }
   ...
}

Шаги по использованию @Resource

@Resource обычно используется для внедрения синглтонов, предоставляемых контейнером EJB.

public class LibraryMessageBean implements MessageListener {
   @Resource
   private MessageDrivenContext mdctx;  
   ...
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования службы внедрения зависимостей в EJB.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.timer, как описано в главе EJB - Создание приложения .

2

Используйте Beans, созданные в главе EJB - Message Driven Bean . Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

LibraryMessageBean.java

package com.tuturialspoint.messagebean;
 
import com.tutorialspoint.entity.Book;
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
 
@MessageDriven(
   name = "BookMessageHandler",
   activationConfig = {
      @ActivationConfigProperty( propertyName = "destinationType", 
                                 propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty( propertyName = "destination", 
                                 propertyValue ="/queue/BookQueue")
   }
)
public class LibraryMessageBean implements MessageListener {
 
   @Resource
   private MessageDrivenContext mdctx;  
 
   @EJB
   LibraryPersistentBeanRemote libraryBean;
 
   public LibraryMessageBean() {        
   }
 
   public void onMessage(Message message) {
      ObjectMessage objectMessage = null;
      try {
         objectMessage = (ObjectMessage) message;
         Book book = (Book) objectMessage.getObject(); 
         libraryBean.addBook(book);
 
      }catch (JMSException ex) {
         mdctx.setRollbackOnly();
      }       
   }   
}

EJBTester (клиент EJB)

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.entity.Book;
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class EJBTester {
 
   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {
 
      EJBTester ejbTester = new EJBTester();
 
      ejbTester.testMessageBeanEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testMessageBeanEjb() {
 
      try {
         int choice = 1; 
         Queue queue = (Queue) ctx.lookup("/queue/BookQueue");
         QueueConnectionFactory factory =
         (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
         QueueConnection connection =  factory.createQueueConnection();
         QueueSession session = connection.createQueueSession( 
         false, QueueSession.AUTO_ACKNOWLEDGE);
         QueueSender sender = session.createSender(queue);
 
         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               ObjectMessage objectMessage = 
               session.createObjectMessage(book);
               sender.send(objectMessage); 
            } else if (choice == 2) {
               break;
            }
         }
 
         LibraryPersistentBeanRemote libraryBean = 
         (LibraryPersistentBeanRemote)
		 ctx.lookup("LibraryPersistentBean/remote");
 
         List<Book> booksList = libraryBean.getBooks();
 
         System.out.println("Book(s) entered so far: " 
         + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }   
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск jndi выполняется с именем - «/ queue / BookQueue» для получения ссылки на очередь, доступную в Jboss. Затем отправитель создается с использованием сеанса очереди.

  • Затем пользователю показывают пользовательский интерфейс магазина библиотеки, и его просят сделать выбор.

  • Если пользователь вводит 1, система запрашивает название книги, и отправитель отправляет название книги в очередь. Когда контейнер JBoss получает это сообщение в очереди, он вызывает метод onMessage нашего управляемого сообщениями bean-компонента. Затем наш управляемый сообщениями компонент сохраняет книгу, используя метод addBook () сессионного компонента с сохранением состояния. Сессионный компонент сохраняет книгу в базе данных через вызов EntityManager.

  • Если пользователь вводит 2, то выполняется еще один поиск jndi с именем «LibraryStatefulSessionBean / remote», чтобы снова получить удаленный бизнес-объект (EJB с отслеживанием состояния), и список книг будет выполнен.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn EJB
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 2
1. learn java
1. learn EJB
BUILD SUCCESSFUL (total time: 15 seconds)

Вывод, показанный выше, показывает, что наш управляемый сообщениями компонент получает сообщение и сохраняет книгу в постоянном хранилище, а книги извлекаются из базы данных.

Наш управляемый сообщениями bean-компонент использует LibraryPersistentBean, внедренный в него с использованием аннотации @EJB, а в случае исключения объект MessageDrivenContext используется для отката транзакции.

EJB 3.0 предоставляет спецификацию для перехвата вызовов бизнес-методов с использованием методов, аннотированных аннотацией @AroundInvoke. Метод-перехватчик вызывается ejbContainer перед вызовом бизнес-метода, который он перехватывает. Ниже приведен пример сигнатуры метода перехватчика.

@AroundInvoke
public Object methodInterceptor(InvocationContext ctx) throws Exception {
   System.out.println("*** Intercepting call to LibraryBean method: " 
   + ctx.getMethod().getName());
   return ctx.proceed();
}

Методы перехватчика можно применять или связывать на трех уровнях.

  • Default - Перехватчик по умолчанию вызывается для каждого компонента в развертывании. Перехватчик по умолчанию может применяться только через xml (ejb-jar.xml).

  • Class- Перехватчик уровня класса вызывается для каждого метода компонента. Перехватчик уровня класса может применяться как аннотацией через xml (ejb-jar.xml).

  • Method- Перехватчик уровня метода вызывается для определенного метода компонента. Перехватчик на уровне метода может применяться как аннотацией через xml (ejb-jar.xml).

Здесь мы обсуждаем перехватчик на уровне класса.

Класс перехватчика

package com.tutorialspoint.interceptor;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class BusinessInterceptor {
   @AroundInvoke
   public Object methodInterceptor(InvocationContext ctx) throws Exception {
      System.out.println("*** Intercepting call to LibraryBean method: " 
      + ctx.getMethod().getName());
      return ctx.proceed();
   }
}

Удаленный интерфейс

import javax.ejb.Remote;

@Remote
public interface LibraryBeanRemote {
   //add business method declarations
}

Перехваченный EJB без сохранения состояния

@Interceptors ({BusinessInterceptor.class})
@Stateless
public class LibraryBean implements LibraryBeanRemote {
   //implement business method 
}

Пример приложения

Давайте создадим тестовое приложение EJB для проверки перехваченного EJB без сохранения состояния.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.interceptor, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Create Application, как таковой для этой главы, чтобы понять перехваченные концепции EJB.

2

Создание LibraryBean.java и LibraryBeanRemote под пакет com.tutorialspoint.interceptor , как описано в EJB - Создание приложений главу. Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент ejb, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

EJBComponent (модуль EJB)

LibraryBeanRemote.java

package com.tutorialspoint.interceptor;

import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryBeanRemote {
   void addBook(String bookName);
   List getBooks();
}

LibraryBean.java

package com.tutorialspoint.interceptor;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Interceptors ({BusinessInterceptor.class})
@Stateless
public class LibraryBean implements LibraryBeanRemote {
    
   List<String> bookShelf;    

   public LibraryBean() {
      bookShelf = new ArrayList<String>();
   }

   public void addBook(String bookName) {
      bookShelf.add(bookName);
   }    

   public List<String> getBooks() {
      return bookShelf;
   }   
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.interceptor.LibraryBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryBean/remote - EJB3.x Default Remote Business Interface
   LibraryBean/remote-com.tutorialspoint.interceptor.LibraryBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.interceptor.LibraryBeanRemote ejbName: LibraryBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryBean/remote - EJB3.x Default Remote Business Interface
   LibraryBean/remote-com.tutorialspoint.interceptor.LibraryBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibraryBeanRemote;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.List;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testInterceptedEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testInterceptedEjb() {

      try {
         int choice = 1; 

         LibraryBeanRemote libraryBean =
         LibraryBeanRemote)ctx.lookup("LibraryBean/remote");

         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }                
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testInterceptedEjb () поиск jndi выполняется с именем - «LibraryBean / remote» для получения удаленного бизнес-объекта (EJB без сохранения состояния).

  • Затем пользователю показывается пользовательский интерфейс магазина библиотеки, и его / ее просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент хранит книгу в своей переменной экземпляра.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
BUILD SUCCESSFUL (total time: 13 seconds)

Вывод журнала сервера приложений JBoss

Проверьте следующий вывод в выводе журнала сервера приложений JBoss.

....
09:55:40,741 INFO  [STDOUT] *** Intercepting call to LibraryBean method: addBook
09:55:43,661 INFO  [STDOUT] *** Intercepting call to LibraryBean method: getBooks

EJB 3.0 предоставляет возможность встраивать JAVA POJO (простой старый объект Java) в объектный компонент и позволяет отображать имена столбцов с методами встроенного класса POJO. Встраиваемый объект Java POJO должен быть аннотирован как @Embeddable.

@Embeddable
public class Publisher implements Serializable{
   private String name;
   private String address;
   ...
}

Вышеупомянутый класс может быть встроен с помощью аннотации @Embedded.

@Entity
public class Book implements Serializable{
   private int id;
   private String name;
   private Publisher publisher;
   ...
   @Embedded
   @AttributeOverrides({
      @AttributeOverride(name = "name", 
                      column = @Column(name = "PUBLISHER")),
      @AttributeOverride(name = "address", 
                      column = @Column(name = "PUBLISHER_ADDRESS"))
   })
   public Publisher getPublisher() {
      return publisher;
   }
   ...
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования встроенных объектов в EJB 3.0.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Пожалуйста, используйте проект, созданный в главе EJB - Persistence, как таковой для этой главы, чтобы понять встроенные объекты в концепциях EJB.

2

Создайте Publisher.java в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Остальные файлы оставьте без изменений.

3

Создайте Book.java в пакете com.tutorialspoint.entity . Используйте в качестве справочника главу EJB - Persistence . Остальные файлы оставьте без изменений.

4

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

5

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

6

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

Создать / изменить книжный стол

CREATE TABLE book (
   id     integer PRIMARY KEY,
   name   varchar(50)
);
Alter table book add publisher varchar(100);
Alter table book add publisher_address varchar(200);

EJBComponent (модуль EJB)

Publisher.java

package com.tutorialspoint.entity;

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class Publisher implements Serializable{
    
   private String name;
   private String address;

   public Publisher() {}

   public Publisher(String name, String address) {
      this.name = name;
      this.address = address;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public String toString() {
      return name + "," + address;
   }    
}

Book.java

package com.tutorialspoint.entity;

import com.tutorialspoint.callback.BookCallbackListener;
import java.io.Serializable;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="book")
public class Book implements Serializable{

   private int id;
   private String name;
   private Publisher publisher;

   public Book() {        
   }

   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }


   @Embedded
   @AttributeOverrides({
      @AttributeOverride(name = "name", 
         column = @Column(name = "PUBLISHER")),
      @AttributeOverride(name = "address", 
         column = @Column(name = "PUBLISHER_ADDRESS"))
   })
   public Publisher getPublisher() {
      return publisher;
   }

   public void setPublisher(Publisher publisher) {
      this.publisher = publisher;
   }    
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryPersistentBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.interceptor.LibraryPersistentBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.interceptor.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibraryBeanRemote;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.List;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEmbeddedObjects();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEmbeddedObjects() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean = 
        (LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            String publisherName;
            String publisherAddress;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               System.out.print("Enter publisher name: ");
               publisherName = brConsoleReader.readLine();
               System.out.print("Enter publisher address: ");
               publisherAddress = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               book.setPublisher
              (new Publisher(publisherName,publisherAddress));

               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            System.out.println("Publication: "+book.getPublisher());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testInterceptedEjb () поиск в jndi выполняется с именем «LibraryPersistenceBean / remote» для получения удаленного бизнес-объекта (EJB без сохранения состояния).

  • Затем пользователю показывают пользовательский интерфейс магазина библиотеки, и его просят сделать выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент хранит книгу в базе данных.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: learn html5
Enter publisher name: SAMS
Enter publisher address: DELHI
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn html5
Publication: SAMS,DELHI
BUILD SUCCESSFUL (total time: 21 seconds)

EJB 3.0 обеспечивает поддержку типов Blob и Clob с помощью аннотации @Lob. Следующие типы Java можно сопоставить с помощью аннотации @Lob.

  • java.sql.Blob
  • java.sql.Clob
  • byte[]
  • String
  • Сериализуемый объект
@Entity
@Table(name="books")
@EntityListeners(BookCallbackListener.class)
public class Book implements Serializable{
   ...
   private byte[] image;    

   @Lob @Basic(fetch= FetchType.EAGER)
   public byte[] getImage() {
      return image;
   }
   ...
}

Пример приложения

Давайте создадим тестовое приложение EJB для проверки поддержки blob / clob в EJB 3.0.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Используйте проект, созданный в главе EJB - Persistence, как таковой для этой главы, чтобы понять объекты clob / blob в концепциях ejb.

2

Создайте Book.java в пакете com.tutorialspoint.entity . Используйте в качестве справочника главу EJB - Persistence . Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

5

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB.

Создать / изменить книжный стол

CREATE TABLE book (
   id     integer PRIMARY KEY,
   name   varchar(50)
);
Alter table book add image bytea;
Alter table book add xml text;

EJBComponent (модуль EJB)

Book.java

package com.tutorialspoint.entity;

import com.tutorialspoint.callback.BookCallbackListener;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;

@Entity
@Table(name="book")
public class Book implements Serializable{
    
   private int id;
   private String name;    
   private byte[] image;   
   private String xml;

   public Book() {        
   }

   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Lob @Basic(fetch= FetchType.EAGER)
   public byte[] getImage() {
      return image;
   }

   public void setImage(byte[] image) {
      this.image = image;
   }

   @Lob @Basic(fetch= FetchType.EAGER)
   public String getXml() {
      return xml;
   }

   public void setXml(String xml) {
      this.xml = xml;
   }
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryPersistentBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.interceptor.LibraryPersistentBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.interceptor.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibraryBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testBlobClob();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testBlobClob() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean = 
        (LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            String publisherName;
            String publisherAddress;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               String xml = "<book><name>"+bookName+"</name></book>";
               Book book = new Book();
               book.setName(bookName);                                        
               byte[] imageBytes = {0x32, 0x32,0x32, 0x32,0x32,
               0x32,0x32, 0x32,
               0x32, 0x32,0x32, 0x32,0x32, 0x32,0x32, 0x32,
               0x32, 0x32,0x32, 0x32,0x32, 0x32,0x32, 0x32
               };
               book.setImage(imageBytes);
               book.setXml(xml);

               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            byte[] imageByts = book.getImage();
            if(imageByts != null) {
               System.out.print("image bytes: [");
               for(int j = 0; j < imageByts.length ; j++) {
                  System.out.print("0x" 
                  + String.format("%x", imageByts[j]) +" ");
               }            
               System.out.println("]");
            }        
            System.out.println(book.getXml());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи.

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testInterceptedEjb () поиск в jndi выполняется с именем «LibraryPersistenceBean / remote» для получения удаленного бизнес-объекта (EJB без сохранения состояния).

  • Затем пользователю показывают пользовательский интерфейс магазина библиотеки, и его просят сделать выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент хранит книгу в базе данных.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: learn testing
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn testing
image bytes: [
   0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 ]
<book><name>learn testing</name></book>
BUILD SUCCESSFUL (total time: 20 seconds)

Транзакция - это отдельная единица рабочих элементов, которая соответствует свойствам ACID. ACID означает атомарный, согласованный, изолированный и надежный.

  • Atomic- Если какой-либо из рабочих элементов выйдет из строя, весь блок будет считаться неисправным. Успех означает, что все элементы выполняются успешно.

  • Consistent - Транзакция должна поддерживать систему в согласованном состоянии.

  • Isolated - Каждая транзакция выполняется независимо от любой другой транзакции.

  • Durable - Транзакция должна пережить сбой системы, если она была выполнена или зафиксирована.

Контейнер / серверы EJB являются серверами транзакций и обрабатывают распространение контекста транзакций и распределенные транзакции. Транзакциями можно управлять с помощью контейнера или с помощью пользовательской обработки кода в коде компонента.

  • Container Managed Transactions - В этом типе контейнер управляет состояниями транзакции.

  • Bean Managed Transactions - В этом типе разработчик управляет жизненным циклом состояний транзакции.

Транзакции, управляемые контейнером

EJB 3.0 определяет следующие атрибуты транзакций, которые реализуют контейнеры EJB:

  • REQUIRED - Указывает, что бизнес-метод должен выполняться внутри транзакции, в противном случае для этого метода будет запущена новая транзакция.

  • REQUIRES_NEW - Указывает, что для бизнес-метода должна быть начата новая транзакция.

  • SUPPORTS - Указывает, что бизнес-метод будет выполняться как часть транзакции.

  • NOT_SUPPORTED - Указывает, что бизнес-метод не должен выполняться как часть транзакции.

  • MANDATORY - Указывает, что бизнес-метод будет выполняться как часть транзакции, в противном случае будет создано исключение.

  • NEVER - Указывает, выполняется ли бизнес-метод как часть транзакции, тогда будет создано исключение.

пример

package com.tutorialspoint.txn.required;
 
import javax.ejb.*
 
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UserDetailBean implements UserDetailRemote {
	
   private UserDetail;

   @TransactionAttribute(TransactionAttributeType.REQUIRED)
   public void createUserDetail() {
      //create user details object
   }
}

Бизнес-метод createUserDetail () сделан Обязательным с использованием Обязательной аннотации.

package com.tutorialspoint.txn.required;
 
import javax.ejb.*
 
@Stateless
public class UserSessionBean implements UserRemote {
	
   private User;

   @EJB
   private UserDetailRemote userDetail;

   public void createUser() {
      //create user 
      //...
      //create user details
      userDetail.createUserDetail();
   }
}

Бизнес-метод createUser () использует createUserDetail (). Если во время вызова createUser () возникло исключение и объект User не был создан, объект UserDetail также не будет создан.

Транзакции, управляемые компонентом

В транзакциях, управляемых компонентами, транзакциями можно управлять путем обработки исключений на уровне приложения.

Ниже приведены ключевые моменты, которые следует учитывать:

  • Start - Когда начинать транзакцию в бизнес-методе.

  • Sucess - Определите сценарий успеха, когда транзакция должна быть зафиксирована.

  • Failed - Выявление сценария сбоя при откате транзакции.

пример

package com.tutorialspoint.txn.bmt;
 
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;
 
@Stateless
@TransactionManagement(value=TransactionManagementType.BEAN)
public class AccountBean implements AccountBeanLocal {
 
   @Resource
   private UserTransaction userTransaction;

   public void transferFund(Account fromAccount, double fund , 
      Account toAccount) throws Exception{

      try{
         userTransaction.begin();

         confirmAccountDetail(fromAccount);
         withdrawAmount(fromAccount,fund);

         confirmAccountDetail(toAccount);
         depositAmount(toAccount,fund);

         userTransaction.commit();
      }catch (InvalidAccountException exception) {
         userTransaction.rollback();
      }catch (InsufficientFundException exception) {
         userTransaction.rollback();
      }catch (PaymentException exception) {
         userTransaction.rollback();
      }
   }

   private void confirmAccountDetail(Account account) 
      throws InvalidAccountException {
   }

   private void withdrawAmount() throws InsufficientFundException {
   }

   private void depositAmount() throws PaymentException{
   }
}

В этом примере мы использовали UserTransaction интерфейс для отметки начала транзакции с помощью userTransaction.begin()вызов метода. Мы отмечаем завершение транзакции, используяuserTransaction.commit() метод, и если во время транзакции возникло какое-либо исключение, мы откатываем всю транзакцию, используя userTransaction.rollback() вызов метода.

Безопасность - главная забота любого приложения корпоративного уровня. Он включает идентификацию пользователя (ей) или системы, осуществляющей доступ к приложению. На основе идентификации он разрешает или запрещает доступ к ресурсам в приложении. Контейнер EJB управляет стандартными проблемами безопасности или может быть настроен для решения любых конкретных проблем безопасности.

Важные условия безопасности

  • Authentication - Это процесс, обеспечивающий проверку подлинности пользователя, получающего доступ к системе или приложению.

  • Authorization - Это процесс, гарантирующий, что подлинный пользователь имеет необходимый уровень полномочий для доступа к системным ресурсам.

  • User - Пользователь представляет клиента или систему, которая обращается к приложению.

  • User Groups - Пользователи могут быть частью группы с определенными полномочиями, например группой администраторов.

  • User Roles - Роли определяют уровень полномочий пользователя или разрешений на доступ к системному ресурсу.

Безопасность, управляемая контейнером

EJB 3.0 определяет следующие атрибуты / аннотации безопасности, которые реализуют контейнеры EJB.

  • DeclareRoles- Указывает, что класс примет заявленные роли. Аннотации применяются на уровне класса.

  • RolesAllowed- Указывает, что к методу может получить доступ пользователь с указанной ролью. Может применяться на уровне класса, в результате чего все методы класса могут быть доступны для пользователя указанной роли.

  • PermitAll- Указывает, что бизнес-метод доступен всем. Его можно применять как на уровне класса, так и на уровне метода.

  • DenyAll - Указывает, что бизнес-метод недоступен для любого пользователя, указанного на уровне класса или метода.

пример

package com.tutorialspoint.security.required;
 
import javax.ejb.*
 
@Stateless
@DeclareRoles({"student" "librarian"})
public class LibraryBean implements LibraryRemote {

   @RolesAllowed({"librarian"})
   public void delete(Book book) {
	  //delete book
   }
   
   @PermitAll
   public void viewBook(Book book) {
      //view book
   }
   
   @DenyAll
   public void deleteAll() {
      //delete all books
   } 
}

Конфигурация безопасности

Сопоставьте роли и группы пользователей в файле конфигурации.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<ejb-jar>
   <security-role-mapping>
      <role-name>student</role-name>
      <group-name>student-group</group-name>
   </security-role-mapping>
   <security-role-mapping>
      <role-name>librarian</role-name>
      <group-name>librarian-group</group-name>
   </security-role-mapping>  
   <enterprise-beans/>
</ejb-jar>

JNDI расшифровывается как Java Naming and Directory Interface. Это набор API и сервисных интерфейсов. Приложения на основе Java используют JNDI для именования и служб каталогов. В контексте EJB есть два термина.

  • Binding - Это относится к присвоению имени объекту EJB, которое можно использовать позже.

  • Lookup - Это относится к поиску и получению объекта EJB.

В Jboss сессионные компоненты по умолчанию связаны в JNDI в следующем формате.

  • local - EJB-имя / локальный

  • remote - EJB-имя / удаленный

В случае, если EJB связан с файлом <application-name> .ear, то формат по умолчанию следующий:

  • local - имя-приложения / имя-ejb / местное

  • remote - имя-приложения / имя-ejb / удаленный

Пример привязки по умолчанию

См. Раздел «EJB - Создание приложения », вывод консоли JBoss.

Вывод журнала сервера приложений JBoss

...
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibrarySessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBean ejbName: LibrarySessionBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibrarySessionBean/remote - EJB3.x Default Remote Business Interface
   LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote - EJB3.x Remote Business Interface
...

Индивидуальная привязка

Следующие аннотации могут использоваться для настройки привязок JNDI по умолчанию:

  • local - org.jboss.ejb3.LocalBinding

  • remote - org.jboss.ejb3.RemoteBindings

Обновите LibrarySessionBean.java. См. Главу EJB - Создание приложения .

LibrarySessionBean

package com.tutorialspoint.stateless;
 
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
 
@Stateless
@LocalBinding(jndiBinding="tutorialsPoint/librarySession")
public class LibrarySessionBean implements LibrarySessionBeanLocal {
    
    List<String> bookShelf;    
    
    public LibrarySessionBean() {
       bookShelf = new ArrayList<String>();
    }
    
    public void addBook(String bookName) {
       bookShelf.add(bookName);
    }    
 
    public List<String> getBooks() {
        return bookShelf;
    }
}

LibrarySessionBeanLocal

package com.tutorialspoint.stateless;
 
import java.util.List;
import javax.ejb.Local;
 
@Local
public interface LibrarySessionBeanLocal {
 
    void addBook(String bookName);
 
    List getBooks();
    
}

Соберите проект, разверните приложение на Jboss и проверьте следующий вывод в консоли Jboss:

...
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibrarySessionBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibrarySessionBean ejbName: LibrarySessionBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   tutorialsPoint/librarySession - EJB3.x Default Local Business Interface
   tutorialsPoint/librarySession-com.tutorialspoint.stateless.LibrarySessionBeanLocal - EJB3.x Local Business Interface
...

EJB 3.0 предоставляет возможность определять отношения / сопоставления сущностей базы данных, такие как отношения «один к одному», «один ко многим», «многие к одному» и «многие ко многим».

Ниже приведены соответствующие аннотации -

  • One-to-One- Объекты взаимно однозначно связаны. Например, пассажир может путешествовать по одному билету за раз.

  • One-to-Many- Объекты имеют отношение "один ко многим". Например, у отца может быть несколько детей.

  • Many-to-One- Объекты имеют отношение "многие к одному". Например, у нескольких детей одна мать.

  • Many-to-Many- У объектов есть отношения "многие ко многим". Например, у книги может быть несколько авторов, и автор может написать несколько книг.

Здесь мы продемонстрируем использование отображения ManyToMany. Для представления отношения ManyToMany требуются три следующие таблицы:

  • Book - Книжный стол, имеющий записи книг.

  • Author - Таблица авторов, содержащая записи об авторах.

  • Book_Author - Таблица "Автор книги", имеющая связь между таблицами "Автор" и "Книга".

Создать таблицы

Создать таблицу book author, book_author в базе данных по умолчанию postgres.

CREATE TABLE book (
   book_id     integer,   
   name   varchar(50)      
);

CREATE TABLE author (
   author_id   integer,
   name   varchar(50)      
);

CREATE TABLE book_author (
   book_id     integer,
   author_id   integer 
);

Создать классы сущностей

@Entity
@Table(name="author")
public class Author implements Serializable{
   private int id;
   private String name;
   ...   
}

@Entity
@Table(name="book")
public class Book implements Serializable{
   private int id;
   private String title;
   private Set<Author> authors;
   ...   
}

Используйте аннотацию ManyToMany в Book Entity.

@Entity
public class Book implements Serializable{
   ...
   @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}
      , fetch = FetchType.EAGER)
   @JoinTable(table = @Table(name = "book_author"),
      joinColumns = {@JoinColumn(name = "book_id")},
      inverseJoinColumns = {@JoinColumn(name = "author_id")})
   public Set<Author> getAuthors() {
      return authors;
   }
   ...
}

Пример приложения

Давайте создадим тестовое приложение EJB для тестирования объектов отношений сущностей в EJB 3.0.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Пожалуйста, используйте проект, созданный в главе EJB - Persistence, как таковой для этой главы, чтобы понять встроенные объекты в концепциях EJB.

2

Create Author.java under package com.tutorialspoint.entity as explained in the EJB - Create Application chapter. Keep rest of the files unchanged.

3

Create Book.java under package com.tutorialspoint.entity. Use EJB - Persistence chapter as reference. Keep rest of the files unchanged.

4

Clean and Build the application to make sure business logic is working as per the requirements.

5

Finally, deploy the application in the form of jar file on JBoss Application Server. JBoss Application server will get started automatically if it is not started yet.

6

Now create the EJB client, a console based application in the same way as explained in the EJB - Create Application chapter under topic Create Client to access EJB.

EJBComponent (EJB Module)

Author.java

package com.tutorialspoint.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="author")
public class Author implements Serializable{
    
   private int id;
   private String name;

   public Author() {}

   public Author(int id, String name) {
      this.id = id;
      this.name = name;
   }
   
   @Id  
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="author_id")
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String toString() {
      return id + "," + name;
   }    
}

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;

@Entity
@Table(name="book")
public class Book implements Serializable{

   private int id;
   private String name;
   private Set<Author> authors;

   public Book() {        
   }

   @Id  
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="book_id")
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public void setAuthors(Set<Author> authors) {
      this.authors = authors;
   }    
   
   @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}
      , fetch = FetchType.EAGER)
   @JoinTable(table = @Table(name = "book_author"),
      joinColumns = {@JoinColumn(name = "book_id")},
      inverseJoinColumns = {@JoinColumn(name = "author_id")})
   public Set<Author> getAuthors() {
      return authors;
   }
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}
  • As soon as you deploy the EjbComponent project on JBOSS, notice the jboss log.

  • JBoss has automatically created a JNDI entry for our session bean − LibraryPersistentBean/remote.

  • We will using this lookup string to get remote business object of type − com.tutorialspoint.interceptor.LibraryPersistentBeanRemote

JBoss Application Server Log Output

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.interceptor.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (EJB Client)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • These properties are used to initialize the InitialContext object of java naming service.

  • InitialContext object will be used to lookup stateless session bean.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateful.LibraryBeanRemote;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.*;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEmbeddedObjects();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEmbeddedObjects() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean = 
         (LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            String authorName;
            
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               System.out.print("Enter author name: ");
               authorName = brConsoleReader.readLine();               
               Book book = new Book();
               book.setName(bookName);
               Author author = new Author();
               author.setName(authorName);
               Set<Author> authors = new HashSet<Author>();
               authors.add(author);
               book.setAuthors(authors);

               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            System.out.print("Author: ");
            Author[] authors = (Author[])books.getAuthors().toArray();
            for(int j=0;j<authors.length;j++) {
               System.out.println(authors[j]);
            }
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester performs the following tasks −

  • Load properties from jndi.properties and initialize the InitialContext object.

  • In testInterceptedEjb() method, jndi lookup is done with name - "LibraryPersistenceBean/remote" to obtain the remote business object (stateless EJB).

  • Then the user is shown a library store User Interface and he/she is asked to enter a choice.

  • If the user enters 1, the system asks for book name and saves the book using stateless session bean addBook() method. Session Bean is storing the book in database.

  • If the user enters 2, the system retrieves books using stateless session bean getBooks() method and exits.

Run Client to Access EJB

Locate EJBTester.java in project explorer. Right click on EJBTester class and select run file.

Verify the following output in Netbeans console.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: learn html5
Enter Author name: Robert
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn html5
Author: Robert
BUILD SUCCESSFUL (total time: 21 seconds)

In EJB 3.0, persistence mechanism is used to access the database in which the container manages the database related operations. Developers can access database using JDBC API call directly in EJB business methods.

To demonstrate database access in EJB, we need to perform the following tasks −

  • Step 1 − Create a table in the database.

  • Step 2 − Create a stateless EJB having business me.

  • Step 3 − Update stateless EJB. Add methods to add records and get records from database via entity manager.

  • Step 4 − A console based application client will access the stateless EJB to persist data in database.

Create Table

Create a table books in default database postgres.

CREATE TABLE books (
   id     integer PRIMARY KEY,
   name   varchar(50)
);

Create a Model Class

public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }
   
   public int getId() {
      return id;
   }
   ...
}

Create Stateless EJB

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   public void addBook(Book book) {
     //persist book using jdbc calls
   }    

   public List<Book> getBooks() {        
     //get books using jdbc calls
   }
   ...
}

After building the EJB module, we need a client to access the stateless bean, which we will be going to create in the next section.

Example Application

Let us create a test EJB application to test EJB database access mechanism.

Step Description
1

Create a project with a name EjbComponent under a package com.tutorialspoint.entity as explained in the EJB - Create Application chapter. You can also use the project created in EJB - Create Application chapter as such for this chapter to understand EJB data access concepts.

2

Create Book.java under package com.tutorialspoint.entity and modify it as shown below.

3

Create LibraryPersistentBean.java and LibraryPersistentBeanRemote as explained in the EJB - Create Application chapter and modify them as shown below.

4

Clean and Build the application to make sure business logic is working as per the requirements.

5

Finally, deploy the application in the form of jar file on JBoss Application Server. JBoss Application server will get started automatically if it is not started yet.

6

Now create the EJB client, a console based application in the same way as explained in the EJB - Create Application chapter under topic Create Client to access EJB. Modify it as shown below.

EJBComponent (EJB Module)

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;

public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }
   
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }    
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   public void addBook(Book book) {
      Connection con = null;
      String url = "jdbc:postgresql://localhost:5432/postgres";
      String driver = "org.postgresql.driver";

      String userName = "sa";
      String password = "sa";
      List<Book> books = new ArrayList<Book>();
      try {

         Class.forName(driver).newInstance();
         con = DriverManager.getConnection(url , userName, password);

         PreparedStatement st = 
         con.prepareStatement("insert into book(name) values(?)");
         st.setString(1,book.getName());

         int result = st.executeUpdate();                

      } catch (SQLException ex) {
         ex.printStackTrace();
      } catch (InstantiationException ex) {
         ex.printStackTrace();
      } catch (IllegalAccessException ex) {
         ex.printStackTrace();
      } catch (ClassNotFoundException ex) {
         ex.printStackTrace();
      }    
   }    

   public List<Book> getBooks() {
      Connection con = null;
      String url = "jdbc:postgresql://localhost:5432/postgres";
      String driver = "org.postgresql.driver";
   
      String userName = "sa";
      String password = "sa";
      List<Book> books = new ArrayList<Book>();
      try {

         Class.forName(driver).newInstance();
         con = DriverManager.getConnection(url , userName, password);

         Statement st = con.createStatement();
         ResultSet rs = st.executeQuery("select * from book");

         Book book;
         while (rs.next()) {
            book = new Book();
            book.setId(rs.getInt(1));                 
            book.setName(rs.getString(2));
            books.add(book);
         }
      } catch (SQLException ex) {
         ex.printStackTrace();
      } catch (InstantiationException ex) {
         ex.printStackTrace();
      } catch (IllegalAccessException ex) {
         ex.printStackTrace();
      } catch (ClassNotFoundException ex) {
         ex.printStackTrace();
      }
      return books;
   }
}
  • As soon as you deploy the EjbComponent project on JBOSS, notice the jboss log.

  • JBoss has automatically created a JNDI entry for our session bean - LibraryPersistentBean/remote.

  • We will be using this lookup string to get remote business object of type − com.tutorialspoint.stateless.LibraryPersistentBeanRemote

JBoss Application Server Log Output

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBeanRemote,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (EJB Client)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • These properties are used to initialize the InitialContext object of java naming service.

  • InitialContext object will be used to lookup stateless session bean.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEntityEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEntityEjb() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean =
         LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester performs the following tasks −

  • Load properties from jndi.properties and initialize the InitialContext object.

  • In testStatefulEjb() method, jndi lookup is done with the name - "LibraryStatelessSessionBean/remote" to obtain the remote business object (stateful EJB).

  • Then user is shown a library store User Interface and he/she is asked to enter a choice.

  • If the user enters 1, the system asks for book name and saves the book using stateless session bean addBook() method. Session Bean is persisting the book in database via EntityManager call.

  • If the user enters 2, the system retrieves books using stateless session bean getBooks() method and exits.

  • Then another jndi lookup is done with the name - "LibraryStatelessSessionBean/remote" to obtain the remote business object (stateful EJB) again and listing of books is done.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn java
BUILD SUCCESSFUL (total time: 15 seconds)

EJB Query Languageочень удобно писать собственные запросы, не беспокоясь о деталях базовой базы данных. Он очень похож на HQL, язык запросов спящего режима и часто упоминается под названием EJBQL.

Чтобы продемонстрировать EJBQL в EJB, мы собираемся выполнить следующие задачи:

  • Step 1 - Создать таблицу в базе данных.

  • Step 2 - Создайте EJB без состояния, имеющий дело со мной.

  • Step 3−Обновить EJB без сохранения состояния. Добавьте методы для добавления записей и получения записей из базы данных через диспетчер сущностей.

  • Step 4 - Клиент консольного приложения будет обращаться к EJB без сохранения состояния для сохранения данных в базе данных.

Создать таблицу

Создать таблицу books в базе данных по умолчанию postgres.

CREATE TABLE books (
   id     integer PRIMARY KEY,
   name   varchar(50)
);

Создать класс модели

public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }
   
   public int getId() {
      return id;
   }
   ...
}

Создать EJB без сохранения состояния

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   public void addBook(Book book) {
     //persist book using entity manager
   }    

   public List<Book> getBooks() {        
     //get books using entity manager
   }
   ...
}

После сборки модуля EJB нам понадобится клиент для доступа к bean-компоненту без сохранения состояния, который мы собираемся создать в следующем разделе.

Пример приложения

Давайте создадим тестовое приложение EJB для проверки механизма доступа к базе данных EJB.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения . Вы также можете использовать проект, созданный в главе EJB - Create Application, как таковой для этой главы, чтобы понять концепции доступа к данным EJB.

2

Создайте Book.java в пакете com.tutorialspoint.entity и измените его, как показано ниже.

3

Создайте LibraryPersistentBean.java и LibraryPersistentBeanRemote, как описано в главе EJB - Создание приложения, и измените их, как показано ниже.

4

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

5

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

6

Теперь создайте клиент EJB, консольное приложение таким же образом, как описано в главе EJB - Создание приложения в разделеCreate Client to access EJB. Измените его, как показано ниже.

EJBComponent (модуль EJB)

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;

public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }
   
   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }    
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {
   void addBook(Book bookName);
   List<Book> getBooks();
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EntityEjbPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      //create an ejbql expression
      String ejbQL = "From Book b where b.name like ?1";
      //create query
      Query query = entityManager.createQuery(ejbQL);
      //substitute parameter.
      query.setParameter(1, "%test%");   
      //execute the query
      return query.getResultList();
   }   
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сеансового компонента - LibraryPersistentBean/remote.

  • Мы будем использовать эту строку поиска, чтобы получить удаленный бизнес-объект типа - com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Вывод журнала сервера приложений JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBeanRemote,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (клиент EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Эти свойства используются для инициализации объекта InitialContext службы имен Java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEntityEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEntityEjb() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean =
         LibraryPersistentBeanRemote)
         ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester выполняет следующие задачи -

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск jndi выполняется с именем «LibraryStatelessSessionBean / remote» для получения удаленного бизнес-объекта (ejb с отслеживанием состояния).

  • Затем пользователю показывается пользовательский интерфейс магазина библиотеки, и его / ее просят ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент сохраняет книгу в базе данных через вызов EntityManager.

  • Если пользователь вводит 2, система извлекает книги с помощью метода getBooks () сессионного компонента без сохранения состояния и завершает работу.

  • Затем выполняется еще один поиск jndi с именем «LibraryStatelessSessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB с отслеживанием состояния) и выполняется вывод списка книг.

Запустить клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберитеrun file.

Проверьте следующий вывод в консоли Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Testing
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn Testing
BUILD SUCCESSFUL (total time: 15 seconds)

EJB-компоненты являются частью корпоративных приложений, которые обычно основаны на распределенных средах. Таким образом, помимо обычных исключений, которые могут возникнуть, могут быть исключения, такие как сбой связи, разрешения безопасности, сбой сервера и т. Д.

Контейнер EJB рассматривает исключения двумя способами:

  • Application Exception - Если бизнес-правило нарушается или возникает исключение при выполнении бизнес-логики.

  • System Exception- Любое исключение, не вызванное бизнес-логикой или бизнес-кодом. RuntimeException, RemoteException - это SystemException. Например, ошибка при поиске EJB. RuntimeException, RemoteException - это SystemException.

Как контейнер EJB обрабатывает исключения?

когда Application Exceptionпроисходит, контейнер EJB перехватывает исключение, но возвращает то же самое клиенту, что и есть. Он не откатывает транзакцию, если это не указано в коде методом EJBContext.setRollBackOnly (). Контейнер EJB не оборачивает исключение в случае исключения приложения.

когда System Exceptionпроисходит, контейнер EJB перехватывает исключение, откатывает транзакцию и запускает задачи очистки. Он переносит исключение в RemoteException и передает его клиенту.

Обработка исключения приложения

Исключения приложений обычно создаются в методах Session EJB, поскольку именно эти методы отвечают за выполнение бизнес-логики. Исключение приложения должно быть объявлено в предложении throws бизнес-метода и должно выдаваться в случае сбоя бизнес-логики.

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   ...

   public List<Book> getBooks() throws NoBookAvailableException {        
      List<Book> books = 
         entityManager.createQuery("From Books").getResultList();
      if(books.size == 0)
		throw NoBookAvailableException
           ("No Book available in library.");
      return books;
   }
   ...
}

Обработка системного исключения

Системное исключение может произойти в любой момент, например, сбой поиска имен, ошибка sql при выборке данных. В таком случае такое исключение должно быть заключено в EJBException и возвращено клиенту.

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   ...

   public List<Book> getBooks() {   
      try {
         List<Book> books = 
            entityManager.createQuery("From Books").getResultList();
      } catch (CreateException ce) {
         throw (EJBException) new EJBException(ce).initCause(ce);
      } catch (SqlException se) {
         throw (EJBException) new EJBException(se).initCause(se);    
      }	  
      return books;
   }
   ...
}

На стороне клиента обработайте исключение EJBException.

public class EJBTester {
   private void testEntityEjb() {
   ...
   try{
      LibraryPersistentBeanRemote libraryBean =
      LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote");
   
      List<Book> booksList = libraryBean.getBooks();
   } catch(EJBException e) {
      Exception ne = (Exception) e.getCause();
      if(ne.getClass().getName().equals("SqlException")) {
         System.out.println("Database error: "+ e.getMessage());
      }
   }
   ...
   }
}

EJB 3.0 предоставляет возможность предоставлять сеансовый EJB как веб-службу. Аннотация @WebService используется для обозначения класса как конечной точки веб-службы, а @WebMethod используется для предоставления клиенту метода как веб-метода.

@Stateless
@WebService(serviceName="LibraryService")
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   ...
   @WebMethod(operationName="getBooks")
   public List<Book> getBooks()  {    
      return entityManager.createQuery("From Books").getResultList();
   }
   ...
}

Пример приложения

Давайте создадим тестовое приложение EJB для проверки поддержки blob / clob в EJB 3.0.

Шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB - Создание приложения. Пожалуйста, используйте проект, созданный в главе EJB - Persistence, как таковой для этой главы, чтобы понять объекты clob / blob в концепциях EJB.

2

Создайте LibraryPersistentBean.java в пакете com.tutorialspoint.stateless. Используйте в качестве справочника главу EJB - Persistence. Остальные файлы оставьте без изменений.

3

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

4

Наконец, разверните приложение в виде файла jar на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
@WebService(serviceName="LibraryService")
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    
   
   @WebMethod(operationName="getBooks")
   public List <Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}

Вывод журнала сервера приложений JBoss

10:51:37,271 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibraryPersistentBean ejbName: LibraryPersistentBean
10:51:37,287 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

	LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
	LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface

10:51:37,349 INFO  [EJBContainer] STARTED EJB: com.tuturialspoint.messagebean.LibraryMessageBean ejbName: BookMessageHandler
10:51:37,443 INFO  [DefaultEndpointRegistry] register: jboss.ws:context=EjbComponent,endpoint=LibraryPersistentBean
10:51:38,191 INFO  [WSDLFilePublisher] WSDL published to: file:/D:/Jboss-5.0.1/server/default/data/wsdl/EjbComponent.jar/
LibraryService3853081455302946642.wsdl

Создать клиента для доступа к EJB как к веб-службе

В IDE NetBeans выберите ,File > New Project >.Выберите тип проекта в категории,Java, Тип проекта как Java Application. НажмитеNext >Кнопка Введите название проекта и расположение. НажмитеFinish >кнопка. Мы выбрали имя EJBWebServiceClient.

Щелкните правой кнопкой мыши имя проекта в окне проводника проекта. ВыбратьNew > WebService Client.

Добавьте LibraryPersistentBean проекта компонента EJB, созданный ранее в WSDL и Client Location, используя Add Project кнопка в compile таб.

Нажмите кнопку «Готово». Проверьте следующую структуру в проводнике проекта.

Создать EJBWebServiceClient.java

package ejbwebserviceclient;

public class EJBWebServiceClient {
   public static void main(String[] args) {   
   }
}

Выберите веб-метод getBooks веб-службы, как показано на рисунке ниже, и перетащите его в окно кода EJBWebServiceClient.

Вы увидите результат, аналогичный показанному ниже.

Обновите код EJBWebServiceClient, чтобы использовать этот метод.

package ejbwebserviceclient;

public class EJBWebServiceClient {

   public static void main(String[] args) {
      for(com.tutorialspoint.stateless.Book book:getBooks()) {
         System.out.println(book.getName());
      }       
   }

   private static java.util.List
   <com.tutorialspoint.stateless.Book> getBooks() {
      com.tutorialspoint.stateless.LibraryService service = 
         new com.tutorialspoint.stateless.LibraryService();
      com.tutorialspoint.stateless.LibraryPersistentBean port = 
         service.getLibraryPersistentBeanPort();
      return port.getBooks();
   }      
}

Запустите клиент

Щелкните правой кнопкой мыши имя проекта в окне проводника проекта. ВыбратьRun. Netbeans соберет клиента и запустит его. Проверьте следующий вывод.

ant -f D:\\SVN\\EJBWebServiceClient run
init:
Deleting: D:\SVN\EJBWebServiceClient\build\built-jar.properties
deps-jar:
Updating property file: D:\SVN\EJBWebServiceClient\build\built-jar.properties
wsimport-init:
wsimport-client-LibraryPersistentBean:
files are up to date
classLoader = java.net.URLClassLoader@4ce46c
SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@182cdac
wsimport-client-generate:
Compiling 1 source file to D:\SVN\EJBWebServiceClient\build\classes
compile:
run:
learn java
Learn Spring
learn JSF
Learn HTML
Learn JBoss
Learn EJB
Learn Hibernate
Learn IBatis
Times Now
learn html5
Learn images
Learn Testing
Forbes
test1
BUILD SUCCESSFUL (total time: 1 second)

Требования к пакетным приложениям, использующим EJB 3.0, аналогичны требованиям платформы J2EE. Компоненты EJB упакованы в модули в виде файлов jar и упакованы в корпоративный архив приложения в виде файла ear.

Любое корпоративное приложение состоит из трех основных компонентов:

  • jar - Архив приложений Java, содержащий модули EJB, клиентские модули EJB и служебные модули.

  • war - Архив веб-приложений, содержащий веб-модули.

  • ear - Архив корпоративных приложений, содержащий jar-файлы и военный модуль.

В NetBeans очень легко создавать, разрабатывать, упаковывать и развертывать приложения J2EE.

В IDE NetBeans выберите,File > New Project >.Выберите тип проекта в категории,Java EE, Тип проекта как Enterprise Application. НажмитеNext >кнопка. Введите название проекта и местоположение. НажмитеFinish >кнопка. Мы выбрали имя EnterpriseApplicaton.

Выберите Сервер и настройки. ХранитьCreate EJB Module и Create Web Application Moduleпроверено с предоставленными именами по умолчанию. Нажмите кнопку «Готово». NetBeans создаст следующую структуру в окне проекта.

Щелкните правой кнопкой мыши проект Enterprise Application в проводнике проекта и выберите «Сборка».

ant -f D:\\SVN\\EnterpriseApplication dist
pre-init:
init-private:
init-userdir:
init-user:
init-project:
do-init:
post-init:
init-check:
init:
deps-jar:
deps-j2ee-archive:
EnterpriseApplication-ejb.init:
EnterpriseApplication-ejb.deps-jar:
EnterpriseApplication-ejb.compile:
EnterpriseApplication-ejb.library-inclusion-in-manifest:

Building jar: D:\SVN\EnterpriseApplication\EnterpriseApplication-ejb\dist\EnterpriseApplication-ejb.jar

EnterpriseApplication-ejb.dist-ear:
EnterpriseApplication-war.init:
EnterpriseApplication-war.deps-module-jar:
EnterpriseApplication-war.deps-ear-jar:
EnterpriseApplication-ejb.init:
EnterpriseApplication-ejb.deps-jar:
EnterpriseApplication-ejb.compile:
EnterpriseApplication-ejb.library-inclusion-in-manifest:
EnterpriseApplication-ejb.dist-ear:
EnterpriseApplication-war.deps-jar:
EnterpriseApplication-war.library-inclusion-in-archive:
EnterpriseApplication-war.library-inclusion-in-manifest:
EnterpriseApplication-war.compile:
EnterpriseApplication-war.compile-jsps:
EnterpriseApplication-war.do-ear-dist:

Building jar: D:\SVN\EnterpriseApplication\EnterpriseApplication-war\dist\EnterpriseApplication-war.war

EnterpriseApplication-war.dist-ear:
pre-pre-compile:
pre-compile:
Copying 1 file to D:\SVN\EnterpriseApplication\build
Copying 1 file to D:\SVN\EnterpriseApplication\build
do-compile:
post-compile:
compile:
pre-dist:
do-dist-without-manifest:
do-dist-with-manifest:

Building jar: D:\SVN\EnterpriseApplication\dist\EnterpriseApplication.ear

post-dist:
dist:
BUILD SUCCESSFUL (total time: 1 second)

Здесь вы можете видеть, что Netbeans сначала готовит Jar, затем War и, в конце концов, файл уха, содержащий jar и war, файл. Каждая банка, война и ушная папка содержатmeta-inf папка, чтобы иметь метаданные в соответствии со спецификацией J2EE.