La capa de lógica
En la arquitectura de capas que estamos utilizando en nuestros proyectos, la capa de lógica de la aplicación o negocio se encarga de coordinar los llamados del api rest y el acceso a la capa de persistencia. Es una capa intermedia entre la implementación de los recursos y la base de datos.
Una de sus responsabilidades es ocuparse de validar reglas de negocio o de invocar servicios de otras aplicaciones. Por ejemplo:
- Que el isbn del libro exista en el servicio internacional de isbns.
- Que la fecha de publicación del libro sea mayor que la fecha de nacimiento del autor.
La lógica de la aplicación está implementada en Java Enterprise Edition (JEE) utilizando Enterprise Java Beans de Sesión sin estado (Stateless EJBs).
A continuación algunos conceptos básicos de los EJBs.
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. Los EJBs que conforman una aplicación deben ser desplegados dentro de un servidor de aplicaciones que implemente la especificación JEE (Glassfish, JBoss, BEA,..).
Existen tres tipos de EJBs:
- Session beans (pueden ser sin estado Stateless o con estado Stateful),
- Entity beans para manejar los datos persistentes (ver Persistencia)
- Message-driven beans para manejar mensajes de manera asincrónica.
Los beans de sesión representan elementos fachada 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 hay 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 llamados 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.
Para propósitos de escalabilidad de una aplicación se utilizan los beans de sesión sin estado para que cualquier bean pueda atender una petición sin necesidad de guardar una relación entre un usuario y un bean particular. En nuestros ejemplos siempre utilizaremos beans de sesión sin estado. Que denotaremos con la anotación @Stateless
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.
El ciclo de vida de los beans de sesión, es decir, la creación/destrucción de las instancias, lo maneja el contenedor. Desde el punto de vista de quien esté utilizando los servicios del bean de sesión, la instancia que lo atiende es indistinguible para él. Por eso, como lo ilustra la figura, para el llamado de un servicio (1) lo atiende un bean A1
pero, para el mismo cliente, cuando invoca otro servicio (2) lo atiende otro bean A2
.
Imagen tomada de: http://theopentutorials.com/examples/java-ee/ejb3/stateless-session-bean-pooling-example
La capa de lógica en nuestros proyectos
El siguiente diagrama de clases presenta un fragmento del proyecto company-back
. La clase CompanyResource
es la responsable de responder a los llamados de los servicios rest. Está implementada utilizando JAX-RS
quien recibe objetos en formato json
y los convierte a pojos (Plain Java Objects), en este ejemplo CompanyDTO
.
La clase CompanyResource
declara una interface ICompanyLogic
y accede a los servicios de la lógica a través de ella. Esta interface recibe/devuelve entidades de persistencia, en el ejemplo CompanyEntity
. La clase CompanyResource
se ocupa de transformar objetos pojos en entidades y viceversa.
La clase que implementa la lógica CompanyLogic
no conoce los objetos pojos (DTOs). Se ocupa de validar reglas de negocio y de comunicarse con la capa de persistencia para realizar sus acciones.
Inyección de Dependencias en EJBs
La mayoría de las aplicaciones empresariales Java utilizan recursos y servicios, como fuentes de datos, EJBs o servicios web externos. El uso de estos recursos se convierte en algo simple en EJB 3 mediante la inyección de dependencias.
La inyección de dependencias permite que un recurso A
declare una dependencia a un recurso B
y delega la resolución de la misma al contenedor. El contenedor se ocupa de resolver y entregar una instancia del recurso B
y se lo "inyecta" al recurso A
.
Ejemplos
Inyección de la lógica en el recurso
En el contexto de nuestro ejemplo company-back
tenemos que el recurso CompanyResource
define una variable cuyo tipo es una interface de la lógica. Utilizamos la anotación @Inject
para indicarle al contenedor que en ejecución "inyecte", es decir, haga que la variable apunte a un objeto de una clase que implementa esa interface.
Inyección de la persistencia en la lógica
La clase de la lógica de company
define una variable para acceder a la persistencia de tipo CompanyPersistence
. Utilizamos la anotación @Inject
para indicarle al contenedor que en ejecución "inyecte", es decir, haga que la variable apunte a un objeto de una clase que CompanyPersistence
.
Más información sobre la implementación de la lógica en nuestro proyecto del curso puede se encontrada en el siguiente taller: