Estás en:

informaciónDESARROLLADO POR:
icono_twiter icono_linkedin icono_linkedin icono_xing

Creador y propietario de AdictosAlTrabajo.com, Director General de Autentia S.L., Ingeniero Técnico de Telecomunicaciones y Executive MBA por el Instituto de Empresa 2007. Twitter: @rcanalesmora

Autor del Libro: Informática profesional, las reglas no escritas para triunfar en la empresa

Puedes consultar mi CV y alguna de mis primeras aplicaciones (de los 90) aquí

Fecha de publicación del tutorial: 2003-10-03
Tutorial visitado 24.623 veces24.623
Descargar el tutorial en PDF


Regístrate para votar
Share |
New Page 1

CMP Entity Bean con MySql

Como comentamos en el anterior tutorial, la persistencia de un Entity Bean puede ser gestionada por el contenedor.

En este tutorial vamos a ver los pequeños cambios que debemos realizar sobre nuestro EJB, del mismo modo que os vamos a enseñar el truquillo para poder usar la implementación de referencia de J2EE de Sun (J2EE RI) para usar MySql como base de datos.

Como podemos suponer, pocas cosas deben cambiar... aunque hay algunas sutilizas.

Lo que es realmente importante, es la definición del despliegue

 

Definición de interfaz Remoto

El único cambio, que además tiene mucho sentido, es la eliminación de la definición del metodo setId.

Digo que tiene sentido porque cambiar la clave primaria normalmente requiere de otras precauciones.

package ejbfacturas;

/**
 *
 * Interfaz remoto a nuestro EJB de Facturas
 *
 * @author  Roberto Canales
 */
import java.rmi.*;
import javax.ejb.*;
import facturascomun.*;
import java.util.*;

public interface iFacturaItemCMP extends EJBObject
{
    public String getConcepto() throws java.rmi.RemoteException;
    public void setConcepto(String sConcepto) throws java.rmi.RemoteException;
    public String getFecha() throws java.rmi.RemoteException;
    public void setFecha(String sFecha) throws java.rmi.RemoteException;
    public String getDireccion() throws java.rmi.RemoteException;
    public void setDireccion(String sDireccion) throws java.rmi.RemoteException ;
    public String getTitular() throws java.rmi.RemoteException;
    public void setTitular(String sTitular) throws java.rmi.RemoteException;
    public String getCif() throws java.rmi.RemoteException;
    public void setCif(String sCif) throws java.rmi.RemoteException;
    public String getId() throws java.rmi.RemoteException;
    //public void setId(String iId) throws RemoteException, EJBException;
    public double getCantidad() throws java.rmi.RemoteException;
    public void setCantidad(double dCantidad) throws java.rmi.RemoteException;
}    

 

Definición del Interfaz Home

La definicón del interfaz Home, en este caso cambia en el tipo de retorno del metodo findByPrimaryKey

package ejbfacturas;
/**
 *
 * @author  Roberto Canales
 */

import java.rmi.*;
import javax.ejb.*;
import java.io.*;
import java.util.*;

import facturascomun.*;

/**
 * Interfaz Home para definir los méodos de creación de nuestro EJB
 *
 */
public interface iFacturaItemHomeCMP extends EJBHome
{
    // ver las diferencias entre las declaraciones del Home y del Bean
    public iFacturaItemCMP create(Factura pFactura) throws CreateException, RemoteException;
    public iFacturaItemCMP findByPrimaryKey(String pParam) throws FinderException, RemoteException;
}

 

Implementación del Bean

Hay que realizar una definición de métodos abstractos

    public abstract String getConcepto();
    public abstract void setConcepto(String sConcepto);
    public abstract String getFecha();
    public abstract void setFecha(String sFecha);
    public abstract String getDireccion();
    public abstract void setDireccion(String sDireccion);
    public abstract String getTitular();
    public abstract void setTitular(String sTitular);
    public abstract String getCif() ;
    public abstract void setCif(String sCif);
    public abstract String getId();
    public abstract void setId(String iId);
    public abstract double getCantidad();
    public abstract void setCantidad(double dCantidad);

Para asignar los valores del Bean, debemos invocar a los metodos, en el ejbCreate

Por último, lo único que queda por hacer en el código, es borrar el código que gestiona la persistencia.

package ejbfacturas;

/**
 * @author Roberto Canales
 */

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

import facturascomun.*;


public abstract class iFacturaItemBeanCMP implements EntityBean
{
    private void depura(String cadena)
    {
        System.out.println("EJB iFacturaItemBeanCMP: " + cadena);
    }


    private EntityContext context = null;

    /**
     * Metodo destinado a construir nuestro objeto
     *
     * Debe retornar la clave primaria del objeto creado
     */
    public String ejbCreate(Factura pFactura) throws CreateException
    {
        if (pFactura == null)
        {
            throw new CreateException("El Objeto retornado es nulo");
        }

        // asignamos las propiedades a los miembros de nuestra clase
        this.setId(pFactura.getId());  // clave primaria de nuestra factura
        this.setTitular(pFactura.getTitular());
        this.setConcepto(pFactura.getConcepto());
        this.setCif(pFactura.getCif());
        this.setDireccion(pFactura.getDireccion());
        this.setFecha(pFactura.getFecha());
        this.setCantidad(pFactura.getCandidad());

        return null;  // en un CMP se retorna NULL
    }

    /**
     * PosCreate del create construido
     */
    public void ejbPostCreate(Factura pFactura) throws CreateException
    {
        depura("Enviado post-create");
        // no es necesario código aunque si el metodo por haber escrito un create
    }


    /**
     * Metodo invocado por el contenedor para reactivar la instancia
     */
    public void ejbActivate() {
         depura("Se activa el EJB");
    }


    /**
     * Metodo invocado por el contenedor para desactivar la instancia
     */
    public void ejbPassivate() {
        depura("Se pasiva el EJB");
    }

    /**
     * Metodo invocado por el contenedor para borrar la instancia
     */
    public void ejbRemove()  throws RemoveException {
        depura("Borramos el EJB para id ");
     }

    /**
     * Metodo invocado por el contenedor para cargar de BBDD los datos de la instancia
     */
    public void ejbLoad() throws javax.ejb.EJBException, java.rmi.RemoteException {

        depura("Cargamos datos el EJB ");
    }

     /**
     * Metodo invocado por el contenedor para almacenar los datos cambiados
     */
    public void ejbStore() throws javax.ejb.EJBException, java.rmi.RemoteException {
        depura("Guardamos datos el EJB");
    }


     /**
     * Metodo invocado por el contenedor para pasarnos y desactivar el contexto
     */
    public void setEntityContext(javax.ejb.EntityContext entityContext) throws javax.ejb.EJBException, java.rmi.RemoteException {
            depura("Establecemos el contexto");
            this.context = entityContext; // si se nos olvida fallara el ejbActivate
    }


    public void unsetEntityContext() throws javax.ejb.EJBException, java.rmi.RemoteException {
            depura("Des-establecemos el contexto");
            context = null;
    }


    public abstract String getConcepto();
    public abstract void setConcepto(String sConcepto);
    public abstract String getFecha();
    public abstract void setFecha(String sFecha);
    public abstract String getDireccion();
    public abstract void setDireccion(String sDireccion);
    public abstract String getTitular();
    public abstract void setTitular(String sTitular);
    public abstract String getCif() ;
    public abstract void setCif(String sCif);
    public abstract String getId();
    public abstract void setId(String iId);
    public abstract double getCantidad();
    public abstract void setCantidad(double dCantidad);

}
    

Despliegue de la aplicación

Añadimos el EJB como hicimos con los anteriores

En la lengüeta de Entity asignamos un nombre para nuestras consultas EJB (MICMP). Deberia ser un poco más estricto en la notación pero asi se ve mejor .... ;)

Al pinchar el botón de Deployment Settings, aparece la configuración de la base de datos.

Pulsamos Database Settings ...

Asignamos el nombre JNDI de la base de datos (ver más abajo)

Pincharemos el botón de generar Default SQL

Y ya tenemos lista para funcionar nuestra aplicación. Ahora vamos a configurar el entorno para poder usar MySql (en Windows)

Registro de MySql

Pinchamos en la opción de configurar el servidor

Registramos un nuevo driver y nombre JNDI para la base de datos que queremos utilizar

Hay un problema al hacer esto.... y es que las consultas SQL que genera el CMP entity Bean, tienen dobles comillas.

Esto hace que falle.... el truco esta en cambiar la configuración de MySql añadiendo un parámetro sql_mode=ansi

Dependiendo del sistema, se hace de un modo y otro. Nosotros como tenemos instalado MySql como un servicio en Windows, vamos a cambiar el fichero de configuración .

Ojo con ponerlo donde esta especificado y no meter espacios entre medias (en el fichero My.ini)

#This File was made using the WinMySQLAdmin 1.4 Tool
#03/06/2003 11:33:57

#Uncomment or Add only the keys that you know how works.
#Read the MySQL Manual for instructions

[mysqld]
sql_mode=ansi
basedir=C:/mysql
#bind-address=10.43.20.18
datadir=C:/mysql/data
#language=C:/mysql/share/your language directory
#slow query log#=
#tmpdir#=
#port=3306
#set-variable=key_buffer=16M
[WinMySQLadmin]
Server=C:/mysql/bin/mysqld-nt.exe
user=rcanales
    

Para que J2EE RI encuentre el driver JDBC de MySQL, hay que descargarselo de internet ... (podeis ver el tutorial dedicado a su instalación y prueba) y modificar el fichero userconfig.bat

Debemos añadir el trayecto donde lo hemos instalado

REM
REM Copyright 2002 Sun Microsystems, Inc. All rights reserved.
REM SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
REM

rem J2EE_CLASSPATH is appended to the classpath referenced by the EJB server.
rem J2EE_CLASSPATH must include the location of the JDBC driver classes
rem (except for the Cloudscape driver shipped with this release).
rem Each directory is delimited by a semicolon.
rem
set J2EE_CLASSPATH=C:\java\mysql-connector-java-3.0.7-stable\mysql-connector-java-3.0.7-stable-bin.jar
rem
rem JAVA_HOME refers to the directory where the Java(tm) 2 SDK
rem Standard Edition software is installed.
rem
rem set JAVA_HOME=
rem

    

Si ahora ejecutamos un código para probar nuestro EJB CMP.... hemos cambiado  en EJB de sesión .....

     public boolean insertaNuevaFactura(Factura pFactura)
    {

        depura("Comenzamos la insercion de elementos CMP");

        try
        {
            Context contexto = new InitialContext();
            depura("Hemos creado el contexto y vamos a buscar objeto CMP");

            iFacturaItemHomeCMP miHome = null;

            Object objetoGenerico = contexto.lookup("java:comp/env/ejb/entidadfacturacmp");

            depura("La clase original es " + objetoGenerico.getClass().getName());
            miHome = (iFacturaItemHomeCMP) PortableRemoteObject.narrow(objetoGenerico,iFacturaItemHomeCMP.class);

            iFacturaItemCMP miFactura = miHome.create( pFactura);

            miFactura = miHome.findByPrimaryKey("22");
            depura("Vemos si se recupera " + miFactura.getId());

            depura("La operacion ha finalizado");
        }
        catch(Exception e)
        {
            depura("Error al probar ejb de entidad: " + e.getMessage());
        }

        return true;
    }
    

Y tambien un servlet

            contexto = getInitialContext();
            Object objetoGenerico = contexto.lookup("java:comp/env/ejb/gestorfacturas");
            miHome = (iFacturasHome)PortableRemoteObject.narrow(objetoGenerico,iFacturasHome.class);

            iFacturas ejbGestorFacturas = miHome.create();
            depura(out,"Número de facturas en BBDD = " + ejbGestorFacturas.recuperaNumeroFacturas());

            depura(out,"Vamos a insertar un nuevo elemento con EJB CMP");
            ejbGestorFacturas.insertaNuevaFactura(new Factura("73","AdictosAlTrabajo","Consultoria Tecnologica","54332112s", "Calle del Olivo", "28/10/2003", 5644.21));
            ejbGestorFacturas.insertaNuevaFactura(new Factura("22","AdictosAlTrabajo2","Consultoria Tecnologica2","54332112s2", "Calle del Olivo2", "28/12/2003", 5543.21));
            depura(out,"La operacion se ejecuto satisfactoriamente");

    

Si consultamos la BBDD, veremos que se ha creado la tabla e insertados los elementos.

Podeis descargar todo el código aquí ...

Ya hemos cubierto otra fase ..... ahora tengo otra pregunta

¿Podemos intercambiar en el código el EJB con la persistencia controlada por el Bean y por el contenedor?

Sobre el Autor ..

Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Puedes opinar o comentar cualquier sugerencia que quieras comunicarnos sobre este tutorial; con tu ayuda, podemos ofrecerte un mejor servicio.


(Sólo para usuarios registrados)

» Registrate y accede a esta y otras ventajas «

Comentarios

  1. nelson
    2009-06-01 - 08:30:54 PM

    Excelente muy bueno. Preginta tienes un Tutorial mas amplio es decir que lo expliques desde 0, los componentes necesarios para que puedas hacer una aplicación para cliente y para servirdor gracias