Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
-Tutoriales

Introducción a J2EE


Añadir un Bean de Entidad

Esta lección amplía el ejemplo de la lección anterior para usar un bean de entidad. BonusServlet llama al bean de entidad para grabar información sobre el número de la seguridad social y el bono y recuperarlo desde una tabla de la base de datos. Este funcionalidad de acceso a la base de datos añade la cuarta capa y la capa final al pequeño cliente empezado en la lección anterior.

El SDK J2EE viene con una base de datos Cloudscape, y no necesitamos configuración adicional en nuestro entorno para el bean de entidad. De echo en este jemplo, no escribimos ningún código SQL o JDBC™ para crear las operaciones de acceso a la base de datos. La tabla y el código SQL se generan con la herramienta de Despliegue durante en el ensamble y el despliegue. La lección sobre Tecnología JDBC y Persistencia Manejada por el Bean nos enseñará como escribir código SQL para un bean de entidad.

. Crear el Bean de Entidad

Un bean de entidad representa datos persistentes almacenados en una fila de una tabla de una base de datos. Cuando se crea un bean de entidad, los datos se escriben en la fila apropiada de la tabla, y si se actualizan los datos de un bean de entidad, los datos de la fila apropiada de la tabla también se actualizan. La creación de la tabla de la base de datos y la actualización de las filas ocurre sin escribir nada de código SQL o JDBC.

Los datos de un bean de entidad son persistentes porque sobreviven a los crashs.

  • Si ocurre un crash mientras se están actualizando los datos de un bean de entidad, estos datos son restaurados autmáticamente al estado de la última transación enviada a la base de datos.
  • si ocurre un crash en medio de una transación a la base de datos, la transación se "deshace" para evitar que un envío parcial corrompa los datos.

. BonusHome

La principal diferencia entre el bean de sesión CalcHome de la lección anterior y el bean de entidad BonusHome de esta lección es el método findByPrimaryKey. Este método de búsqueda toma la clave primaria como un parámetro. En este ejemplo, la clave primara es el número de la seguridad social, que se usa para recuperar la fila con el valor de la clave primaria que corresponde con el número de la seguridad social pasado a este método.

El método create toma el valor del bono y de la clave primaria como parámetros. Cuando BonusServlet ejemplariza el interface home y llama a su método create, el contenedor crea un ejemplar de BonusBean y llama a su método ejbCreate. Los métodos BonusHome.create y BonusBean.ejbCreate deben tener la misma firma , para que los valores del bono y la clave primaria puedan ser pasados desde el interface home al bean de entidad mediante el contenedor del bean de entidad. Si una fila para una clave primada dada (número de seguridad social) ya existe, se lanza una java.rmi.RemoteException que es manejada por el código cliente BonusServlet.

package Beans;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.ejb.EJBHome;

public interface BonusHome extends EJBHome {
  public Bonus create(double bonus, String socsec)
        throws CreateException, RemoteException;
  public Bonus findByPrimaryKey(String socsec)
        throws FinderException, RemoteException;
}

. Bonus

Después de crear el interface home, el contenedor crea el interface remoto y el bean de entidad. El interface Bonus declara los métodos getBonus y getSocSec para que el servlet pueda recuperar los datos desde el bean de entidad

package Beans;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface Bonus extends EJBObject {
  public double getBonus() throws RemoteException;
  public String getSocSec() throws RemoteException;
}

. BonusBean

BonusBean es un bean de entidad controlado por contenedor. Esto significa que el contenedor maneja la persistencia de los datos y el control de las transaciones sin tener que escribir código para transferir datos entre el bean de entidad y la base de datos o definir paquetes de transaciones.

Si por alguna razón queremos que el bean de entidad maneje su propia persistencia o las transaciones, podríamos proporcionar implementaciones para algunos de los métodos vacíos mostrados en el código de BonusBean de abajo.

Cuando BonusServlet llama a BonusHome.create, el contenedor llama al método BonusBean.setEntityContext. El ejemplar de EntityContext pasado al método setEntityContext tiene métodos que permiten al bean devolver una referencia a sí mismo o para obtener su clave primaria.

Luego, el contenedor, llama al método ejbCreate. Este método asigna datos a las variables de ejemplar del bean, y luego el contenedor escribe los datos en la base de datos. Se llama al método ejbPostCreate después de ejbCreate y realiza cualquier proceso necesario después de que se cree el bean. Este sencillo ejemplo no hace procesamiento post-creacción.

Los otros métodos vacíos son métodos de retrollamada usados por el contenedor para notificar al bean algún evento que va a ocurrir. Podríamos proporcionar comportamiento para algunos de estos métodos si estámos usando persistencia controlada por el bean, y otros si necesitamos proporcionar limpieza específica del bean u operaciones de limpieza. Estas operaciones de limpieza e inicialización tienen lugar en momentos específicos durante el ciclo de vida del bean, y el contenedor se lo notifica al bean y llama al método aplicable en el momento apropiado. Aquí tenemos una breve descripción de los métodos vacíos:

  • Los métodos ejbPassivate y ejbActivate los llama el contenedor antes de que el contenedor mueva el bean de su almacenamiento. Este proceso es similar al concepto de intercambio de una página de memoria virtual entre la memoria y el disco.
  • El contenedor llama al método ejbRemove si el interface home tiene el correspondiente método remove que es llamado por el cliente.
  • Los métodos ejbLoad y ejbStore los llama el contenedor antes de que se sincronize el estado del bean con la base de datos subyacente.

Los métodos getBonus y getSocSec son llamados por los clientes para recuperar datos almacenados en variables de ejemplar. Este ejemplo no tiene métodos del tipo set< type >, pero si los tuviera, el cliente podría llamarlos para modificar los datos de las variables de ejemplar del bean. Cualquier cambio hecho en una variable de ejemplar resulta en una actualización de la fila de la tabla de la base de datos subyacente.

package Beans;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;

public class BonusBean implements EntityBean {

  public double bonus;
  public String socsec;
  private EntityContext ctx;

  public double getBonus() {
    return this.bonus;
  }
  public String getSocSec() {
    return this.socsec;
  }

  public String ejbCreate(double bonus, 
		String socsec) 
		throws CreateException{
  //Called by container after setEntityContext 
    this.socsec=socsec;
    this.bonus=bonus;
     return null;
  }

  public void ejbPostCreate(double bonus,
                            String socsec) {
  //Called by container after ejbCreate
  }

//These next methods are callback methods that
//are called by the container to notify the
//Bean some event is about to occur

  public void ejbActivate() {
  //Called by container before Bean 
  //swapped into memory 
  }

  public void ejbPassivate() {
  //Called by container before 
  //Bean swapped into storage 
  }

  public void ejbRemove() throws RemoteException {
  //Called by container before 
  //data removed from database
  }

  public void ejbLoad() {
  //Called by container to 
  //refresh entity Bean's state
  }

  public void ejbStore() {
  //Called by container to save 
  //Bean's state to database
  }

  public void setEntityContext(EntityContext ctx){
  //Called by container to set Bean context
  }

  public void unsetEntityContext(){
  //Called by container to unset Bean context
  }
}

. Cambiar el Servlet

El código de esta lección es muy similar al de la página anterior con cambios en los métodos init y doGet. El método init de esta lección busca el bean de sesión CalcBean, y el bean de entidad BonusBean.

public class BonusServlet extends HttpServlet {
  CalcHome homecalc;
  BonusHome homebonus;
  Bonus theBonus, record;

public void init(ServletConfig config) 
		throws ServletException{
  try {
    InitialContext ctx = new InitialContext();
    Object objref = ctx.lookup("bonus");
    Object objref2 = ctx.lookup("calcs");
    homebonus=(
          BonusHome)PortableRemoteObject.narrow(
          objref, BonusHome.class);
    homecalc=(CalcHome)
          PortableRemoteObject.narrow(
          objref2, CalcHome.class);
  } catch (Exception NamingException) {
    NamingException.printStackTrace();
  }
}

La sentencia try en el método doGet crea los interfaces home de CalcBean y BonusBean. Después de llamar a calcBonus para calcular el bono, se llama al método BonusHome.create para crear un ejemplar del bean de entidad y la correspondiente fila en la tabla de la base de datos subyacente. Después de crear la tabla, se llama al método BonusHome.findByPrimaryKey para recuperar el mismo registro por su clave primaria (número de la seguridad social). Luego, se devuelve una página HTML al navegador mostrado los datos pasados originalmente, el bono calculado, y los datos recuperados desde la fila de tabla de la base de datos.

La sentencia catch captura y maneja los valores de claves primaria duplicados (números de seguridad social. La tabla de la base de datos subyacente no puede tener dos filas con la misma clave primaria, por eso si pasamos el mismo número de la seguridad social, el servlet captura el error antes de intentar crear el bean de entidad. En el evento de una clave duplicada, el servlet devuelve una página HTML con los datos pasados originalmente, el bono calculado, y un mensaje de error de clave duplicada:

try {
    Calc theCalculation; 
//Retrieve Bonus and Social Security Information
    String strMult = request.getParameter(
                 "MULTIPLIER");//Calculate bonus
    Integer integerMult = new Integer(strMult);
    multiplier = integerMult.intValue();
    socsec = request.getParameter("SOCSEC");
//Calculate bonus
    double bonus = 100.00;
    theCalculation = homecalc.create();
    calc = theCalculation.calcBonus(
         multiplier, bonus);
//Create row in table
    theBonus = homebonus.create(calc, socsec);
    record = homebonus.findByPrimaryKey(socsec);
//Display data
    out.println("<H1>Bonus Calculation</H1>");
    out.println("<P>Soc Sec passed in: " + 
        theBonus.getSocSec() + "<P>");
    out.println("<P>Multiplier passed in: " + 
        multiplier + "<P>");
    out.println("<P>Bonus Amount calculated: " + 
		 theBonus.getBonus() + "<P>");
    out.println("<P>Soc Sec retrieved: " + 
		  record.getSocSec() + "<P>");
    out.println("<P>Bonus Amount retrieved: " + 
		 record.getBonus() + "<P>");
    out.println("</BODY></HTML>");
//Catch duplicate key error
  } catch (javax.ejb.DuplicateKeyException e) {
    String message = e.getMessage();
//Display data
    out.println("<H1>Bonus Calculation</H1>");
    out.println("<P>Soc Sec passed in: " + 
    socsec + "<P>");
    out.println("<P>Multiplier passed in: " + 
        multiplier + "<P>");
    out.println("<P>Bonus Amount calculated: " + 
		  calc + "<P>");
    out.println("<P>" + message + "<P>");
    out.println("</BODY></HTML>");
  } catch (Exception CreateException) {
    CreateException.printStackTrace();
  }
}

. Compilar

Primero, compilamos el Bean de entidad y el servlet. Puedes volver a la lección anterior para ver la configuración del path, classpath y dónde situar los ficheros fuentes.

. Compilar el Bean de Entidad

Unix

#!/bin/sh
cd /home/monicap/J2EE
J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1
CPATH=.:$J2EE_HOME/lib/j2ee.jar
javac -d . -classpath "$CPATH" Beans/BonusBean.java
           Beans/BonusHome.java Beans/Bonus.java

Windows

cd \home\monicap\J2EE
set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2.1
set CPATH=.;%J2EE_HOME%\lib\j2ee.jar
javac -d . -classpath %CPATH% Beans/BonusBean.java 
           Bean s/BonusHome.java Beans/Bonus.java

. Compilar el Servlet

Unix:

cd /home/monicap/J2EE/ClientCode 
J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1
CPATH=.:$J2EE_HOME/lib/j2ee.jar:/home/monicap/J2EE
javac -d . -classpath "$CPATH" BonusServlet.java 

Windows:

cd \home\monicap\J2EE\ClientCode
set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2.1
set CPATH=.;%J2EE_HOME%\lib\j2ee.jar;
          \home\monicap\J2EE
javac -d . -classpath %CPATH% BonusServlet.java

. Arrancar la Plataforma y las Herramientas

Para ejecutar este ejemplo, necesitamos arrancar el servidor J2EE, la herramienta Deploy y la base de datos Cloudscape. En diferentes ventanas, tecleamos los siguientes comandos.

j2ee -verbose
deploytool
cloudscape -start

Si esto no funciona, tecleamos esto desde el directorio J2EE:

Unix

j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1/bin/cloudscape -start

Windows

j2sdkee1.2.1\bin\j2ee -verbose
j2sdkee1.2.1\bin\deploytool
j2sdkee1.2.1\bin\cloudscape -start

. Ensamblar y Desplegar

Los pasos de esta sección son:

  • Actualizar el Fichero de Aplicación
  • Crear el Bean de Entidad

. Actualizar el Fichero de Aplicación

El archivo web (WAR) contiene BonusServlet y bonus.html. Como hemos modificado BonusServlet, tenemos que actualizar la aplicación J2EE con el nuevo código del servlet.

  • Ventana Local Applicatons: Iluminamos la aplicación BonusApp.
  • Menú Tools Menu: Seleccionamos Update Application Files .
Nota:
Se desinstalará automáticamente la aplicación BonusApp de la lección anterior.

. Crear el Bean de Entidad

Los pasos para crear el EJB JAR para el bean de entidad son muy similares a los pasos del bean de sesión cubiertos en la lección anterior. Sin embargo, hay algunas diferencias, y se explican aquí:

Nota:
En esta lección, el bean de entidad va en un ficjero JAR separado del bean de sesión para continuar el ejemplo de la lección anterior con el menor número de cambios. Sin embargo, como estos beans tienen funcionalidades relacionadas podríamos empaquetarlos y desplegarlos en el mismo fichero JAR. Vermos como hacer esto en la siguiente lección.

Menu File:

  • Seleccionamos New Enterprise Bean.

Introducción :

  • Leer y Pulsar Next

EJB JAR :

  • Nos aseguramos de que BonusApp se ve en Enterprise Bean will go in field.
  • Especificamos BonusJar como nombre.
  • Pulsamos Add (el más cercano a la ventana Contents).

Añadir Componentes al JAR:

  • Cambiamos el directorio para que el directorio de beans muestre su contenido.
  • Seleccionamos Bonus.class
  • Pulsamos Add.
  • Selecionamos BonusBean.class
  • Pulsamos Add.
  • Seleccionamos BonusHome.class
  • Pulsamos Add.
  • Pulsamos OK.

EJB JAR:

  • Pulsamos Next .

General:

  • Beans.BonusBean es el nombre de la clase.
  • Beans.BonusHome es el interface Home.
  • Beans.Bonus es el interface Remoto.
  • Introducimos BonusBean como nombre a mostrar.
  • Pulsamos Entity .
  • Pulsamos Next .

Configuración Entity:

  • Seleccionamos Container-Managed persistence.
  • En la ventana inferior, marcamos bonus y socsec .
  • Especificamos java.lang.String para la clase de la clave primaria. Observa que la clave primaria tiene que ser un tipo de clase. Los tipos primitivos no pueden ser claves primaria.
  • Especificamos socsec para el nombre de campo de la clave primaria.
  • Pulsamos Next .

Entradas de Entorno:

  • Pulsamos Next. Este sencillo bean de entidad no usa propiedades (entradas de entorno).

Referencias a Beans Enterprise:

  • Pulsamos Next. Este sencillo bean de entidad no referencia otros beans enterprise.

Referencias a Recursos:

  • Pulsamos Next. Este sencillo bean de entidad no busca un objeto database o JavaMail™ session.

Seguridad:

  • Pulsamos Next. Este sencillo bean de entidad no usa roles de seguridad.

Control de Transación :

  • Seleccionamos Container-managed transactions (si no está ya seleccionado).
  • En la lista hacemos que sean requeridos create, findByPrimaryKey, getBonus y getSocSec. Esto significa que el contenedor empieza una nueva transación antes de ejecutar estos métodos. Las transaciones se envían justo antes de que los métodos terminen.
  • Pulsamos Next .
  • Pulsamos Finish .

Aplicaciones Locales:

  • Seleccionamos BonusApp .
  • En la ventana Inspecting, seleccionamos JNDI names
  • La damos a BonusBean el nombre JNDI de bonus
  • Pulsamos la tecla Return

Antes de poder desplegar la aplicación J2EE, necesitamos especificar las condiciones de despliegue para el bean de entidad y generar el SQL. Aquí está cómo hacerlo:

Ventana Local Applications:

  • Seleccionamos BonusBean .

Ventana Inspecting:

  • Seleccionamos Entity
  • Pulsamos el botón Deployment Settings de la parte inferior izquierda.

Configuración de Despliegue:

  • Especificamos jdbc/Cloudscape (con una C maýuscula en Cloudscape) para el nombre JNDI de la base de datos.
  • Pulsamos Return.
  • Nos aseguramos de que las cajas Create table on deploy y Delete table on Deploy están marcadas.
  • Ahora pulsamos Generate SQL.
Nota:
Si obtenemos un error de que la conexión fue rechazada, arrancamos la base de datos como se describe en Arrancar la Plataforma y las Herramientas.
  • Cuando se complete la generación de SQL, seleccionamos el método findByPrimaryKey en la caja EJB method. Aparecerá una secuencia SQL a la derecha. Debería leerse SELECT "socsec" FROM "BonusBeanTable" WHERE "socsec"=?. El interrogante representa el parámetro pasado por el método findByPrimaryKey.
  • Pulsamos OK.

. Verificar y Desplegar la aplicación J2EE

Verificar:

  • Con BonusApp seleccionado, elegimos Verifier desde el menú Tools.
  • En el diálogo que aparece, pulsamos OK. La ventana debería decirnos que no ha fallado ningún test.
  • Cerramos la ventana del verificador porque ya estamos listos para desplegar la apliación.
Nota:
En la versión 1.2 del software podría obtener un error tests app.WebURI. La Aplicación J2EE se desplegará de todas formas.

Despliegue:

  • En el Menú Tools: Seleccionamos Tools.Deploy Application.
Nota:
No marcamos la caja "Return Client Jar". El único momento en que debemos chequear esta caja es cuando usamos persistencia controlada por el bean o desplegamos una aplicación solitaria para el programa cliente. Este ejemplo usa un servlet y una página HTML por lo que no debe estár marcada. Esta caja crea un fichero JAR con toda la información de despliegue necesaria para una aplicación solitaria.
  • Pulsamos Next. Nos aseguramos de que JNDI names muestra calcs para CalcBean y bonus para BonusBean . Tecleamos cualquier nombre JNDI que no esté y pulsamos la tecla Return.
  • Pulsamos Next. Nos aseguramos que el nombre Context Root muestra BonusRoot. Si no lo hace, lo tecleamos nosotros mismos y pulsamos la tecla Return.
  • Pulsamos Next.
  • Pulsamos Finish para empezar el despliegue.
  • Cuando se haya completado el despliegue, pulsamos OK.

. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página bonus.html apuntamos nuestros navegador a http://localhost:8000/BonusRoot/bonus.html, que es donde DeployTool puso el fichero HMTL.

Rellenamos un número de la seguridad social y un múltiplicador, y pulsamos el botón Submit. BonusServlet procesa nuestros datos y devuelve una página HTML con el bono calculado.

Bonus Calculation

Soc Sec passed in: 777777777
Multiplier passed in: 25
Bonus Amount calculated: 2500.0
Soc Sec retrieved: 7777777777
Bonus Amount retrieved: 2500.0

Si volvemos al código de bonus.html y cambiamos el multiplicador por 2, pero usamos el mismo número de la seguridad social, veremos esto:

Bonus Calculation
Soc Sec passed in: 777777777
Multiplier passed in: 2
Bonus Amount calculated: 200.0
Duplicate primary key.

. Código Fuente de los Ejemplos

Aquí tienes un fichero Zip con los ficheros fuente de los ejemplos de esta página:

fuentes_L2.zip

 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network