Conceptos Básicos

A continuación algunos conceptos básicos de los EJBs necesarios para el entendimiento del taller.

Enterprise Java Beans

Los Enterprise Java Beans proporcionan un modelo de componentes distribuido del lado del servidor. Son unidades modulares reutilizables entre aplicaciones que se ejecutan dentro de un servidor de aplicaciones (por ejemplo, jboss, glassfish, etc.). Permiten que el desarrollador separe el desarrollo de la lógica de negocio de temas como el manejo del ciclo de vida de los beans, la concurrencia, las transacciones, la persistencia, la seguridad, etc.

Existen tres tipos de EJBs: Session (pueden ser Stateless o Stateful), Entity, Message-driven. Los beans de sesión representan un elemento que atiende los llamados a los servicios de negocio. Dependiendo del diseño de la aplicación puede haber muchos EJBs de sesión, normalmente uno por cada módulo funcional que se ocupa de la lógica de negocio del módulo. Los beans de sesión sin estado reciben llados y devuelven respuestas pero no guardan información del cliente específico que están atendiendo. Los beans de sesión con estado guardan en sus variables de instancia información con el cliente que inició la sesión. Estos valores desaparecen cuando la sesión se termina.

En nuestros ejemplos siempre utilizaremos beans de sesión sin estado. Que denotaremos con la anotación @Sateteless

Un EJB de sesión es una clase Java anotada adecuadamente para indicar que tipo de EJB de sesión es. Normalmente este clase implementa una interface de negocio. Esta interface de negocio puede ser utilizada en otro bean para definir una dependencia entre dos beans.

Interface del ejemplo: IBookLogic

package co.edu.uniandes.basicrestlogic.ejb;
import co.edu.uniandes.basicrestlogic.dtos.BookDTO;
import java.util.List;

public interface IBookLogic {
    public List<BookDTO> getBooks();
    public BookDTO createBook(BookDTO dto);
    public BookDTO updateBook(Long id, BookDTO dto);
    public void deleteBook(Long id);
}

Como puede observar, los métodos (los servicios de negocio del módulo Book) reciben como parámetro y retorna como resultado objetos de la clase BookDTO (DTO significa Data Transfer Object). Esta estructura de datos corresponde a los atributos privados de la clase Book y sus correspondientes setters y getters.

DTO del ejemplo: BookDTO

public class BookDTO {

    /** Atributos de la clase */
    private Long id;
    private String name;
    private String description;
    private String image;
    private String isbn;
    private int price;
   ...
}

La clase que implementa la interface IBookLogic es el bean de sesión. En nuestro ejemplo es un bean de sesión sin estado:

Bean de sesión del ejemplo: BookLogic

/**
* Clase EJB para el desarrollo de la lógica del negocio y conexión de los
* servicios con la capa de datos
*/
@Stateless
public class BookLogic implements IBookLogic {

   /**
   * Metodo para obtener todos los libros
   * @return lista de libros
   */
   public List<BookDTO> getBooks() {
      return book;
   }

  /**
  * Metodo para crear un libro
  * @param dto
  * @return el libro creado con su nuevo id. 
  */
  public BookDTO createBook(BookDTO dto) {
      book.add(dto);
      return dto;
  } 
  ...
}

Inyección de Dependencias

En el ejemplo del Taller 1 Rest la implementación de los servicios Restful la hacíamos directamente sobre la clase definida utilizando Jax-rs. Ahora vamos a delegar desde esta clase, la implementación de los servicios a los EJBs de Sesión, i.e., el servicio restful le delega a la capa de EJBs la implementación del servicio de negocio.

Para lograr esto, la clase que implementa el servicio debe tener una referencia al Ejb de sesión o a un proxy de él. En este taller es el servidor de aplicaciones quien se encarga de resolver la dependencia o inyectarla.

El propósito de la inyección de dependencias es reducir el acoplamiento en las aplicaciones para hacer los componentes más flexibles y fáciles de probar. Las dependencias entre los componentes no quedan "cableadas" en el código.

Hay muchos frameworks de inyección de dependencias. Contexts and Dependency Injection (CDI) para Java EE es el framework que estamos utilizando. Dependency injection: es la habilidad para inyectar componentes en una aplicación en una forma "typesafe". Se puede escoger, en tiempo de despliegue, cuál implementación de una interface particular será inyectada. Por defecto se utiliza un objeto de la clase que implemente la interface.

Inyección de dependencia en el Servicio

El ejemplo siguiente es un fragmento de la clase que implementa el servicio. Esta clase va a delegar en la lógica (El EJB de sesión). Para esto hace una inyección dependencia utilizando sobre una variable del tipo de la interface IBookLogic la anotación @Inject. EN ejecución esta variable será instanciada por el servidor de aplicaciones, con un objeto de la clase BookLogic quien implementa la interface.

   /**
   * Clase que contiene lo relacionado con el servicio REST
   */
   @Path("/books")
   @Consumes(MediaType.APPLICATION_JSON)
   @Produces(MediaType.APPLICATION_JSON)
   public class BookService {

       @Context 
       private HttpServletResponse response;

       @Inject
       private IBookLogic bookLogic;

       /**
       * Metodo POST para la creación de un libro
       * @param dto
       * @return 
       */
       @POST
       public BookDTO createBook(BookDTO dto) {
       return bookLogic.createBook(dto);
       }
       ...
}