Учебники

EJB — обратные вызовы

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

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

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

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

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

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

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

Ниже приведен список аннотаций обратного вызова для объекта управления данными:

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

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

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

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

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

2

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

3

Используйте Бины, созданные в главе EJB — Постоянство . Добавьте методы обратного вызова, как показано ниже. Сохраните остальные файлы без изменений.

4

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

5

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

6

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

7

Теперь создайте EJB-клиент, консольное приложение, аналогично тому, как описано в главе EJB — Создание приложения в разделе « Создание клиента для доступа к EJB» .

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

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

Используйте Бины, созданные в главе EJB — Постоянство . Добавьте методы обратного вызова, как показано ниже. Сохраните остальные файлы без изменений.

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

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

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

Теперь создайте EJB-клиент, консольное приложение, аналогично тому, как описано в главе EJB — Создание приложения в разделе « Создание клиента для доступа к 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

Как только вы развернете проект 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 будет использоваться для поиска сессионного компонента без сохранения состояния.

Эти свойства используются для инициализации объекта 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 () сессионного компонента без сохранения состояния, и завершает работу.

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

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

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

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

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

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

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

Проверьте следующий вывод в консоли 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