Los EJB Session
Objetivo de los capítulos de los EJB (Enterprise Java Beans)
Desarrollar aplicaciones escritas en Java usando los EJB.
-
La aplicación cliente puede ser un cliente pesado, que accede a objetos remotos del contenedor de EJB del servidor JEE.
-
La aplicación cliente puede ser un cliente ligero, que accede a objetos remotos del contenedor de EJB del servidor JEE, a través del contenedor web del servidor JEE.
Tipos de EJB Session
1. EJB Session con estado (stateful)
Cada cliente que llama a un método de un EJB stateful dispone de una instancia dedicada. De esta manera, la clase EJB puede tener propiedades, que son distintas para cada instancia y, por lo tanto, para cada cliente. Estas propiedades se conservan entre dos llamadas de método.
Una instancia del EJB se instancia por el contenedor de EJB durante la primera llamada del método por el cliente.
El inconveniente de los EJB stateful es la congestión de memoria que puede resultar de la conexión de numerosos clientes. En general, es preferible utilizar los EJB stateless.
2. EJB Session sin estado (stateless)
El funcionamiento de los EJB Session stateless se parece al de los Servlets. Durante la primera llamada de un cliente, el contenedor de EJB instancia el objeto. Este objeto es único y común para todos los clientes. Permanece en memoria hasta que sea explícitamente destruido (parada del servidor o nuevo despliegue).
No está prohibido declarar propiedades en un objeto como este, pero preste atención a la mezcla de los datos porque son comunes a todos los clientes.
En general, un EJB Session stateless se presenta como una colección de servicios, por lo que cada uno se corresponde con un método.
3. Utilización Remota/Local
De una manera que al principio puede parecer curiosa, el objetivo de un EJB es ser llamado de forma remota...
Herramientas y convenciones utilizadas en este capítulo
1. Herramientas
El EDI utilizado es NetBeans.
El servidor JEE es GlassFish.
2. Convenciones de nomenclatura utilizadas
Los nombres de la interfaz y de la clase EJB que implementa la interfaz son convencionales. El nombre JNDI es una convención propia del libro.
La interfaz, la clase EJB y el programa cliente se ubican en los proyectos desarrollados en el EDI (aquí, NetBeans). Estos proyectos (disponibles en el sitio web de Ediciones ENI), también tienen nombres que obedecen a convenciones propias del libro:
-
La interfaz XxxRemote se sitúa en un proyecto llamado LibreriaXxx.
-
La clase del EJB Xxx se sitúa en un proyecto llamado EJBXxx.
La interfaz contenida en el proyecto LibreriaXxx se utiliza por el proyecto EJBXxx y por el proyecto cliente.
Ejemplo: un objeto remoto de ordenación
1. Creación del EJB Session
a. La interfaz ClasificadorRemoto
La escritura de la interfaz es más simple que en RMI:
-
La interfaz ya no hereda de la interfaz Remote.
-
El método ya no desencadena RemoteException.
La anotación @Remote de la interfaz indica al contenedor de EJB que el objeto remoto puede estar accesible a partir de otra máquina virtual Java.
package objetoRemoto;
import javax.ejb.Remote;
@Remote
public interfaz ClasificadorRemoto {
public Comparable[] ordenar(Comparable tabla[]);
}
b. Clase del objeto remoto: Clasificador
La anotación @Stateless de la clase indica al contenedor de EJB que el objeto remoto no tiene estado. Solo hay una ocurrencia para todos los clientes.
package objetoRemoto;
import javax.ejb.Stateless;
@Stateless
public class Clasificador implements ClasificadorRemoto
{
@Override
public Comparable[] ordenar(Comparable tabla[])
{
. . .
}
}
2. Despliegue
Para que el servidor pueda ejecutar los métodos de un objeto remoto, es necesario que lo conozca. Esta información se le da a lo largo de una fase automatizada...
Ciclo de vida del EJB Session: @PostConstruct, @PreDestroy
-
El ciclo de vida de un EJB Session se parece al de un Servlet. El contenedor de EJB instancia el EJB la primera vez que se llama uno de sus métodos por parte de un cliente.
-
Para realizar un tratamiento durante la instanciación, hay que utilizar la anotación @PostConstruct. Esta anotación precede a la declaración del método que se ejecuta justo después de la instanciación. El nombre de este método puede ser cualquiera.
-
Para realizar un tratamiento cuando se destruye el EJB (parada del servidor, por ejemplo), hay que utilizar la anotación @PreDestroy. Esta anotación precede a la declaración del método que se ejecuta justo antes de la destrucción. El nombre de este método es cualquier cosa.
Ejemplos
El método despuesInstanciacion() se ejecuta con la primera llamada del EJB:
@PostConstruct
public void despuesInstanciacion()
{
System.out.print("Apertura.............................");
}
La instrucción:
System.out.print("Apertura..............................");
solo sirve para visualizar esta primera llamada.
El método antesDestruccion() se ejecuta cuando el EJB se retira de la memoria:
@PreDestroy public void...
Trabajo práctico: Contacto remoto
1. Objetivos
-
Utilizar los EJB para acceder a una base de datos.
-
Arquitectura de la aplicación:
2. Tema
a. Para realizar
-
Crear un EJB Session que acceda a la tabla CONTACTO de la base de datos. Ofrecer un método de lectura de un contacto cuyo número sabemos.
-
Escribir el programa cliente que utiliza este EJB.
b. Piezas de software que se han de utilizar sin modificación
Las siguientes piezas de software ya están desarrolladas; podemos utilizarlas sin modificación alguna.
c. Copia de pantalla de la aplicación cliente
Cuando el usuario introduce un número de contacto y pulsa la tecla [Intro], se muestran las propiedades del contacto.
Diagrama de secuencia de la aplicación
3. Contacto remoto: propuesta de corrección
a. EJB Session ContactoRemoto
Interfaz ContactoRemotoRemoto
El método leerContacto devuelve el objeto Contacto correspondiente al número pasado como argumento o una SQLException:
package objetRemoto;
import java.sql.SQLException;
import javax.ejb.Remote;
import businessMapping.Contacto;
@Remote
public interfaz ContactoRemotoRemoto
{
public Contacto leerContacto(Integer numeroContacto) throws SQLException;
}
Clase ContactoRemoto
package objetRemoto;
. . .
@Stateless
public class ContactoRemoto implements ContactoRemotoRemoto
{
private BaseDeDatos base;
El método abreBase(), precedido por la anotación @PostConstruct, se ejecuta durante la primera llamada del EJB. Es una buena opción cambiar el driver JDBC e instanciar el objeto BaseDeDatos durante la primera llamada del EJB porque esta información...
Pools de conexiones
1. El problema de las conexiones a un servidor de base de datos
La gestión de las conexiones a una base de datos es de una gran importancia para optimizar el rendimiento de una aplicación.
Cuando un cliente se conecta a un servidor, se reserva un espacio en memoria de este solo para contener la información necesaria para responder.
Cada nueva conexión va ocupando más espacio en el servidor, lo que se puede convertir en un problema, sobre todo si se trata de un servidor de base de datos.
Para cada cliente, una solución puede consiste en abrir una conexión, realizar una consulta y cerrar la conexión, lo que libera el espacio reservado en el servidor. Esta solución (que hemos aplicado en el método leerContacto() del EJB ContactoRemoto del trabajo práctico anterior) presenta un inconveniente a pesar de todo: la asignación y desasignación del espacio reservado en el servidor lleva tiempo, lo que puede ralentizar el programa cliente y el servidor.
Los pools de conexiones ofrecen una solución eficaz a este problema.
2. Los pools de conexiones
a. Definición
Un pool de conexiones es un servidor de conexiones.
Cuando se arranca un servidor como este, abre un determinado número de conexiones con el servidor de base de datos. Los clientes se dirigen al pool, que les asigna una conexión.
Un servidor que cumple la norma JEE debe permitir la creación de pools de conexiones.
b. Creación de un pool de conexiones
Un pool de conexiones permite acceder...
Trabajo práctico: Proyecto GestionContactoEJB
1. Objetivos
-
Utilizar los EJB Session para desarrollar una aplicación 4 tiers web, que acceda a una base de datos.
-
Arquitectura de la aplicación:
2. Tema
a. Para realizar
-
Crear el EJB Mapping y su interfaz MappingRemote. Este objeto remoto tiene todos los métodos de acceso a los datos necesarios para la aplicación GestionContactoEJB.
-
Crear la aplicación GestionContactoEJB, que retoma la aplicación GestionContactoMVC2. Es la aplicación cliente del EJB.
-
Las pantallas de la aplicación no se modifican.
-
El encadenamiento de los programas y de las pantallas se modifican.
-
Hay que adaptar las clases ServletControlador, TratamientoInicio y TratamientoModif porque la aplicación accede a los datos por medio de un objeto remoto: el EJB Mapping.
b. Piezas de software que se van a utilizar sin modificación
Las JSP de la aplicación GestionContactoMVC2 se utilizan sin modificación.
c. Documentos proporcionados
-
La interfaz MappingRemote.java
-
Un diagrama de secuencia de la aplicación (lista de los contactos)
d. Interfaz MappingRemote
@Remote
public interfaz MappingRemote
{
Leer un contacto cuyo número conocemos. Se puede producir una SQLException:
public Contacto leerContacto(Integer numero) throws SQLException;
Lista de los contactos
El método leerListaContacto() devuelve un Vector<Vector> que contiene dos celdas:
-
La celda 0 contiene el Vector<Contacto>.
-
La celda 1 contiene el Vector<Columna>.
public Vector<Vector> leerListaContactos() throws SQLException;
Modificar un contacto
El método modificarContacto() devuelve:
-
1 si la modificación ha tenido éxito.
-
0 si se ha producido un incidente (el contacto no existe).
-
Una SQLException en otro caso.
public int modificarContacto(Contacto contacto) throws SQLException;
Lista de los sectores: mismo principio que leerListaContactos():
public Vector<Vector> leerListaSectores() throws SQLException;
}
e. Diagrama de secuencia
Este diagrama solo representa la secuencia de llamadas a los métodos correspondientes a las selecciones de la lista de contactos:
Se representan los 4 tiers que intervienen en la aplicación.