Menú Curso Java EJB's : Código Fuente "CuentaBancariaBean" la implementación EJB de un "BMP Entity Bean"

(Anterior) BMP ("Bean Managed Persistence")

Debido a la longitud de esta clase, es fraccionada en cuatro partes describiendo el funcionamiento de cada sección.

Clase CuentaBancariaBean

package com.osmosislatina.ejb.cuenta;

import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;

public class CuentaBancariaBean implements EntityBean {

    private String id;
    private String nombre;
    private String apellido;
    private double saldo;

    private EntityContext context;
    private Connection con;
    private String dbName = "java:/DefaultDS";
 

    public void deducir(double cantidad) 
       throws SaldoInsuficiente  {

       if (saldo - cantidad < 0) {
           throw new SaldoInsuficiente();
       }
       saldo -= cantidad;
    }

    public void abonar(double cantidad) {

       saldo += cantidad;
    }
 
 

    public String getNombre() {
 
       return nombre;
    }
 
    public String getApellido() {
 
       return apellido;
    }
 
  
    public double getSaldo() {

       return saldo;
    }

  • En esta primer sección se importan las diversas clases que serán utilizadas a lo largo del EJB, vale notar que dentro de éstas se incluyen java.sql y javax.sql las cuales son empleadas para accesar Bases de Datos.

  • Posteriormente se inicia la declaración de la clase, misma que por ser un "Entity EJB" debe implementar la interfase EntityBean.

  • De inmediato se definen los 7 campos utilizados dentro del EJB.

  • Son definidos e implementados los métodos correspondientes al "Remote Interface": deducir, abonar, getNombre, getApellido, getSaldo.

A continuación se describen las implementaciones de los métodos del "Home Interface"

 

    public String ejbCreate(String id, String nombre, 
       String apellido, double saldo)
       throws CreateException {

       if (saldo < 0.00) {
          throw new CreateException
             ("No puede generarse una cuenta con Saldo Inicial menor que 0");
       }

       try {
          insertarFila(id, nombre, apellido, saldo);
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse crearse EJB (ejbCreate) : " + 
              ex.getMessage());
       }

       this.id = id;
       this.nombre = nombre;
       this.apellido = apellido;
       this.saldo = saldo;

       return id;
    }

   public String ejbFindByPrimaryKey(String primaryKey) 
      throws FinderException {

      boolean resultado;

      try {
         resultado = selectByPrimaryKey(primaryKey);
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse buscar el EJB por PrimaryKey :  " +  ex.getMessage());
       }
      if (resultado) {
         return primaryKey;
      }
      else {
         throw new ObjectNotFoundException
            ("Informacion sobre la cuenta numero " + primaryKey + " no fue encontrada.");
      }
   }

   public Collection ejbFindPorApellido(String apellido)
      throws FinderException {

      Collection resultado;

      try {
         resultado = seleccionarPorApellido(apellido);
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse buscar el EJB por Apellido :   " +  ex.getMessage());
       }
       return resultado;
   }


   public Collection ejbFindEnRango(double inferior, double superior)
      throws FinderException {

      Collection resultado;

      try {
         resultado = seleccionarEnRango(inferior, superior);
            
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse buscar el EJB por Rango : " +  ex.getMessage());
       }
      return resultado;
   }

  • La función ejbCreate a diferencia de aquella utilizada en un "SessionBean" contiene lógica de ejecución; esta lógica se encarga de dos procesos :

    • Se inserta una copia de la información proporcionada por el Cliente(JSP/Servlet) en la Base de Datos, la creación de esta fila/renglón es llevada acabo por el método insertarFila-- descrito posteriormente. Lo anterior permite que la información del "Application Server"/"EJB Container" refleje aquella de la Base de Datos.

    • Se inicializa la instancia del EJB a través de los campos definidos con anterioridad.

  • ejbFindByPrimaryKey realiza una búsqueda por la instancia del EJB en base a los parámetros pasados por el cliente; esta búsqueda es realizada a través del método selectByPrimaryKey -- también descrito posteriormente.

  • Los métodos ejbFindPorApellido y ejbFindEnRango realizan búsquedas por EJB's en base a Apellidos y rangos de Saldo respectivamente; dichas búsquedas son realizadas por los métodos seleccionarEnRango y seleccionarPorApellido descritos en otra sección de código.

A continuación se describen las implementaciones de los métodos necesarios para terminar de cumplir con los requerimientos de un "Entity EJB":


   public void ejbRemove() {

      id = (String)context.getPrimaryKey();

      try {
         eliminarFila(id);
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse eliminar EJB (ejbRemove):   " + 
              ex.getMessage());
       }
   } 
 

   public void setEntityContext(EntityContext context) {

      this.context = context;

   }

   public void unsetEntityContext() {
       context = null;
   }


   public void ejbActivate() {

      id = (String)context.getPrimaryKey();
   }

   public void ejbPassivate() {

      id = null;
   }

   public void ejbLoad() {

       id = (String)context.getPrimaryKey();

      try {
         cargarFila(id);
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse cargar informacion para el EJB (ejbLoad) : " + 
              ex.getMessage());
       }
   }


   public void ejbStore() {

      try {
         guardarFila();
       } catch (Exception ex) {
           throw new EJBException("Error al intentarse guardar informacion para el EJB (ejbStore) : " + 
              ex.getMessage());
       }
   }


   public void ejbPostCreate(String id, String nombre, 
      String apellido, double saldo) { }

  • La función ejbRemove también a diferencia de aquella utilizada en un "SessionBean" contiene cierta lógica de ejecución, esta lógica elimina tanto la instancia del EJB así como la respectiva fila en la Base de Datos; la eliminación de esta fila es llevada acabo por el método eliminarFila -- descrito en la siguiente sección.

  • Los métodos setEntityContext y unsetEntityContext como ya fue mencionado son utilizados para adquirir recursos que son empleados con distintas instancias de EJB's.

  • ejbActivate y ejbPassivate son métodos utilizados en caso de ser necesario pasar a memoria secundaria instancias de EJB's.

  • ejbLoad y ejbStore son dos métodos utilizados para cargar y guardar información hacia la Base de Datos, ambos emplean los métodos auxiliares cargarFila y guardarFila para realizar esta tarea; ambos métodos forman una parte critica de la sincronización entre la Base de Datos y EJB's, además su uso esta fuertemente vinculado a transacciones

Finalmente se describen las funciones utilizadas para interactuar con la Base de Datos; en la sección de CMP ("Container Managed Persistence") Entity Beans se observará como estas funciones son generadas por el "Application Server"/"EJB Container").


/*********************** Rutina para Base de Datos *************************/

   private void realizarConexion() throws NamingException, SQLException {

      InitialContext ic = new InitialContext();
      DataSource ds = (DataSource) ic.lookup(dbName);
      con =  ds.getConnection();
   }

    private void liberarConexion() throws NamingException, SQLException {
	con.close();
    }

 


   private void insertarFila (String id, String nombre, String apellido, 
                           double saldo) throws SQLException,NamingException {
          realizarConexion();
          String insertStatement =
                "insert into cuentas_bancarias values ( ? , ? , ? , ? )";
          PreparedStatement prepStmt = 
                con.prepareStatement(insertStatement); 

          prepStmt.setString(1, id);
          prepStmt.setString(2, nombre);
          prepStmt.setString(3, apellido);
          prepStmt.setDouble(4, saldo);

          prepStmt.executeUpdate();
          prepStmt.close();
	  liberarConexion();
   }


   private void eliminarFila(String id) throws SQLException,NamingException {

       realizarConexion();

      String deleteStatement =
            "delete from cuentas_bancarias where id = ? ";
      PreparedStatement prepStmt =
            con.prepareStatement(deleteStatement);

      prepStmt.setString(1, id);
      prepStmt.executeUpdate();
      prepStmt.close();

      liberarConexion();
   }

 

   private boolean selectByPrimaryKey(String primaryKey) 
      throws SQLException,NamingException {

      realizarConexion();

      String selectStatement =
            "select id " +
            "from cuentas_bancarias where id = ? ";
      PreparedStatement prepStmt =
            con.prepareStatement(selectStatement);
      prepStmt.setString(1, primaryKey);

      ResultSet rs = prepStmt.executeQuery();
      boolean resultado = rs.next();
      prepStmt.close();
      liberarConexion();
      return resultado;
   }
   private Collection seleccionarPorApellido(String apellido) 
      throws SQLException,NamingException {

      realizarConexion();

      String selectStatement =
            "select id " +
            "from cuentas_bancarias where apellido = ? ";
      PreparedStatement prepStmt = 
            con.prepareStatement(selectStatement);

      prepStmt.setString(1, apellido);
      ResultSet rs = prepStmt.executeQuery();
      ArrayList a = new ArrayList();

      while (rs.next()) {
         String id = rs.getString(1);
         a.add(id);
      }

      prepStmt.close();
      liberarConexion();
      return a;
   }

 

   private Collection seleccionarEnRango(double inferior, double superior) 
      throws SQLException,NamingException {

      realizarConexion();

      String selectStatement =
            "select id from cuentas_bancarias " +
            "where saldo between  ? and ?";
      PreparedStatement prepStmt = 
            con.prepareStatement(selectStatement);

      prepStmt.setDouble(1, inferior);
      prepStmt.setDouble(2, superior);
      ResultSet rs = prepStmt.executeQuery();
      ArrayList a = new ArrayList();

      while (rs.next()) {
         String id = rs.getString(1);
         a.add(id);
      }

      prepStmt.close();
      liberarConexion();
      return a;
   }

   private void cargarFila(String id) throws SQLException,NamingException {

      realizarConexion();
      String selectStatement =
            "select nombre, apellido, saldo " +
            "from cuentas_bancarias where id = ? ";
      PreparedStatement prepStmt = 
            con.prepareStatement(selectStatement);

      prepStmt.setString(1, this.id);

      ResultSet rs = prepStmt.executeQuery();

      if (rs.next()) {
         this.nombre = rs.getString(1);
         this.apellido = rs.getString(2);
         this.saldo = rs.getDouble(3);
         prepStmt.close();
      }
      else {
         prepStmt.close();
         throw new NoSuchEntityException("Fila para la cuenta numero " + id +
            " no fue encontrada en la Base de Datos.");
      }
      liberarConexion();
   }
 

   private void guardarFila() throws SQLException,NamingException {
       realizarConexion();
      String updateStatement =
            "update cuentas_bancarias set nombre =  ? ," +
            "apellido = ? , saldo = ? " +
            "where id = ?";
      PreparedStatement prepStmt = 
            con.prepareStatement(updateStatement);

      prepStmt.setString(1, nombre);
      prepStmt.setString(2, apellido);
      prepStmt.setDouble(3, saldo);
      prepStmt.setString(4, id);
      int rowCount = prepStmt.executeUpdate();
      prepStmt.close();
      liberarConexion();
      if (rowCount == 0) {
         throw new EJBException("No fue posible guardar informacion de la cuenta numero  " + id);

      }
   }

} //

  • El método realizarConexion es utilizado para adquirir una conexión hacia la Base de Datos; es importante notar que esta búsqueda se esta realizando a través de JNDI, esto es, para el EJB la Base de Datos es un Objeto que esta disponible en la Red , la ubicación exacta de la Base de Datos es definida al nivel de "Application Server"; observe que el parámetro de entrada es llamado dbName, dicho parámetro es definido al inicio de la Clase con un valor java:/DefaultDS el cual representa una ubicación JNDI, dicho nombre JNDI es asociado en el "Application Server"/"EJB Container" con una ubicación física de la Base de Datos.

  • Los métodos que siguen definen la lógica que será utilizada para interactuar con la Base de Datos, y contienen en su mayoría declaraciones comunes del API JDBC.

Terminos Legales de Contenido ©2000-2011 Osmosis Latina

Diseñado bajo estándares : XHTML   CSS  

webmaster@osmosislatina.com