EJB: devoluciones de llamada

La devolución de llamada es un mecanismo mediante el cual se puede interceptar el ciclo de vida de un bean empresarial. La especificación EJB 3.0 ha especificado devoluciones de llamada para las que se crean métodos de manejador de devolución de llamada. EJB Container llama a estas devoluciones de llamada. Podemos definir métodos de devolución de llamada en la propia clase EJB o en una clase separada. EJB 3.0 ha proporcionado muchas anotaciones para devoluciones de llamada.

A continuación se muestra la lista de anotaciones de devolución de llamada para el bean sin estado:

Anotación Descripción
@PostConstruct Se invoca cuando se crea un bean por primera vez.
@Predestroy Se invoca cuando un frijol se elimina del grupo de frijoles o se destruye.

A continuación se muestra la lista de anotaciones de devolución de llamada para el bean con estado:

Anotación Descripción
@PostConstruct Se invoca cuando se crea un bean por primera vez.
@Predestroy Se invoca cuando un frijol se elimina del grupo de frijoles o se destruye.
@PostActivate Se invoca cuando se carga un bean para su uso.
@PrePassivate Se invoca cuando un bean se devuelve al grupo de beans.

A continuación se muestra la lista de anotaciones de devolución de llamada para el bean controlado por mensajes:

Anotación Descripción
@PostConstruct Se invoca cuando se crea un bean por primera vez.
@Predestroy Se invoca cuando un frijol se elimina del grupo de frijoles o se destruye.

A continuación se muestra la lista de anotaciones de devolución de llamada para el bean de entidad:

Anotación Descripción
@PrePersist Se invoca cuando se crea una entidad en la base de datos.
@PostPersist Se invoca después de que se crea una entidad en la base de datos.
@PreQuitar Se invoca cuando se elimina una entidad de la base de datos.
@PostRemove Se invoca después de que se elimina una entidad de la base de datos.
@PreUpdate Se invoca antes de que una entidad se actualice en la base de datos.
@PostLoad Se invoca cuando se obtiene un registro de la base de datos y se carga en la entidad.

Aplicación de ejemplo

Creemos una aplicación EJB de prueba para probar varias devoluciones de llamada en EJB.

Paso Descripción
1

Cree un proyecto con un nombre EjbComponent en un paquete com.tutorialspoint.stateless como se explica en el capítulo EJB - Crear aplicación . También puede usar el proyecto creado en EJB - Capítulo de persistencia como tal para este capítulo para agregar varias devoluciones de llamada a EJB.

2

Cree LibrarySessionBean.java y LibrarySessionBeanRemote como se explica en el capítulo EJB - Crear aplicación . Mantenga el resto de los archivos sin cambios.

3

Utilice Beans creados en el capítulo EJB - Persistencia . Agregue métodos de devolución de llamada como se muestra a continuación. Mantenga el resto de los archivos sin cambios.

4

Cree una clase de Java BookCallbackListener en el paquete com.tutorialspoint.callback . Esta clase demostrará la separación de los métodos de devolución de llamada.

5

Limpie y compile la aplicación para asegurarse de que la lógica empresarial funcione según los requisitos.

6

Finalmente, implemente la aplicación en forma de archivo jar en JBoss Application Server. El servidor de aplicaciones JBoss se iniciará automáticamente si aún no se ha iniciado.

7

Ahora cree el cliente EJB, una aplicación basada en consola de la misma manera que se explica en el capítulo EJB - Crear aplicación en el temaCreate Client to access EJB.

EJBComponent (módulo 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();
    
}
  • Tan pronto como implemente el proyecto EjbComponent en JBOSS, observe el registro de jboss.

  • JBoss ha creado automáticamente una entrada JNDI para nuestro bean de sesión - LibraryPersistentBean/remote.

  • Usaremos esta cadena de búsqueda para obtener un objeto comercial remoto de tipo: com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Salida de registro del servidor de aplicaciones 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 (cliente 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
  • Estas propiedades se utilizan para inicializar el objeto InitialContext del servicio de nombres de Java.

  • El objeto InitialContext se utilizará para buscar un bean de sesión sin estado.

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 realiza las siguientes tareas:

  • Cargue las propiedades de jndi.properties e inicialice el objeto InitialContext.

  • En el método testStatelessEjb (), la búsqueda de jndi se realiza con el nombre "LibrarySessionBean / remote" para obtener el objeto de negocio remoto (EJB sin estado).

  • Luego, se muestra al usuario una interfaz de usuario de la tienda de la biblioteca y se le pide que ingrese una opción.

  • Si el usuario ingresa 1, el sistema solicita el nombre del libro y guarda el libro usando el método addBook () del bean de sesión sin estado. Session Bean está almacenando el libro en la base de datos.

  • Si el usuario ingresa 2, el sistema recupera los libros usando el método getBooks () del bean de sesión sin estado y sale.

Ejecute el cliente para acceder a EJB

Busque EJBTester.java en el explorador de proyectos. Haga clic derecho en la clase EJBTester y seleccionerun file.

Verifique la siguiente salida en la consola de 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)

Salida de registro del servidor de aplicaciones JBoss

Puede encontrar las siguientes entradas de devolución de llamada en el registro de 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
...