Download J2ee

Document related concepts
no text concepts found
Transcript
Los Enterprise Java Beans son
como los Servlets
• Son trozos de código que extienden un
servidor
• “Viven” en un contenedor apropiado
• El contenedor decide cuándo se crean y se
destruyen
• No son contactados directamente por el
cliente
Existen 3 Clases principales
• Session Beans:
– Implementan procesos, orientados a acciones
(cálculo de un valor)
• Entity Beans:
– Están asociados a datos persistentes. Representan
una instancia de un dato almacenado
• Message Driven Beans:
– Parecidos a Session beans pero son “despertados”
o contactados por mensajes que pueden incluso ser
asínctonos
Refinando la clasificación
• Session Beans:
– Sin estado: son contactados una vez por los clientes, ejecutan una
acción y no queda traza de lo que se hizo
– Con estado: en una “sesión” pueden ser contactados varias veces
por el mismo cliente para desarrollar una “conversación”. Será
necesario mantener algún tipo de información para recordar lo que
va haciendo el cliente
• Entity Beans:
– Persistencia controlada por el Bean: el programador debe incluir
código de modo de asegurarse que el enttity bean represente a un
dato en una tabla
– Persistencia controlada por el container: el container se preocupa
de asociar el bean a un dato de una tabla
Qué se necesita escribir para
implementar un bean
• Los Archivos Java (programados por el desarrollador de la
aplicación)
– La interfaz EJBObject: en esta interfaz se especifican los business
methods que implementa el bean, es decir, todos aquellos métodos
que no tienen que ver con crear, recuperar, destruir o localizar un
bean. Típicamente los que diseña el programador
– La interfaz EJBHome: aquí están los métodos para para crear,
destruir y localizar un bean
– El EJBean: este archivo implementa todos los métodos del bean.
Estos incluyen (de alguna manera) los declarados por los dos
archivos anteriores y otros métodos propios de la interfaz bean
(obligación de escribirlos, aunque no hagan nada)
– En la última versión hay tembién EJBLocalObject y
EJBLocalHome, para hacer más eficientes las invocaciones entre
beans de un mismo container
Qué se necesita escribir para
implementar un bean
• Los Archivos NO Java (generalmente generados con
ayuda de herramientas del aplication server)
– El Deployment descriptor: un archivo declarativo donde se
especifican algunas cualidades del bean,
• Bean management and lifecicle requirements: si es un session, entity
o message-driven bean
• Persistencia (para entity beans) si será CMP o BMP
• Transacciones: cómo se manejan las transacciones
• Seguridad: control de accesos
– Archivos propios de requeridos por la implementación del
aplication server: serán para sacar provecho de algunas
características específicas de este
– Todo esto se debe combinar en un archivo jar, que se instala en el
aplication server en un lugar específico (estilo servlets)
Cómo administra el container el
cliclo de vida de los beans
• Los beans son creados y destruidos por el container.
Cuando un bean se levanta con el container (el bean debe
estar ahí cuando se echa a andar el server) se crean
instancias del bean (bean pool) las cuales son “asignadas”
a los clientes. Qué bean es entregado a qué cliente lo
decide el container
• Si se necesitan más beans estos son creados por el
container (create)
• Si hay demasiados estos son destruidos (Remove)
• El container puede decidir además hacer “dormir” o
“despertar” a los beans según las necesidades (activate,
passivate) para
El papel de cada uno de las 3
clases de objetos
• Cuando un cliente desea contactar a un bean localiza un
un ejbHome Object que correspoda al de un bean deseado.
• Este proceso es bien dependiente de las “condiciones locales” pero
normalmente requiere hacer un lookup a un servidor de nombres
(normalmente provisto por el servidor de aplicaciones también) por
medio de la API JNDI
• Una vez que tiene una referencia a este lo usa para
fabricar un objeto EJB, al cual le aplica los métodos
• El EJBObjet se contactará con un bean adecuado para que
dé el servicio (esto lo hace el contenedor)
El papel de cada uno de las 3
clases de objetos
Bean Pool
3 contacta home
ejbHome
cliente
5- retorna referencia
4 crea ejbObject
6 invoca método
1-ubicar
2 retorna referencia
Naming
ejbObject
7 contacta bean
El Hello World EJB
• Haremos un EJB y un cliente que lo contacte e invoque el
método String hello() que devorverá el string “Hello
World”
• Este será un Session Bean sin estado (obvio)
• El primer archivo es el Hello.java que es la interfaz que
EJBObject que declara los “buisness methods”
import javax.ejb.*;
import java.rmi.*;
public interface Hello extends EJBObject {
public string hello() throws RemoteException;
}
La interfaz EJBObject
• Extiende java.rmi.Remote
• tiene los siguientes métodos
–
–
–
–
–
EJBhome getEJBHome()
Object getPrimaryKey() //para entity beans
void remove()
Handle getHandle()
boolean isIdentical()
El Hello World EJB
• El archivo HelloHome.java declara la interfaz con el home
object. En este caso sólo necesitamos declarar un método
para la creación (no necesita parámetros, es sin estado)
import javax.ejb.*;
import java.rmi.*;
public interface HelloHome extends EJBHome {
Hello create() throws RemoteException, CreateException;
}
• Notar que el método create retorna un objeto del tipo
Hello (EJBObject) que es el que se usará para invocar los
métodos
La interfaz EJBHome
• Extiende java.rmi.Remote
• tiene los siguientes métodos
–
–
–
–
EJBMetaData getEJBMetaData()
HomeHandle getHomeHandle()
void remove(Handle handle)
void remove(Object primaryKey)
El Hello World EJB
•
El archivo HelloBean.java implementa los métodos necesarios: por cada
create declarado en Home debe implementar un ejbCreate con los mismos
parámetros. Además debe implementar los business methods (hello no más en
este caso) y los métodos propios de los session beans
import javax.ejb.*;
public class HelloBean extends SessionBean {
private SessionContext ctx;
public void ejbCreate() {}
public String hello() {
return(“hello world!”);
}
public ejbRemove() {} //llamado antes de eliminar el bean
public ejbActivate(){} //llamado al despertar un bean
public ejbPassivate(){} //llamado al poner a dormir el bean
//en este caso no nos sirve pero en otros puede servir
//especialmente en los BMP entity bean
public setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
}
El Deployment descriptor
•
Es un archivo xml donde se le dan declarativamente algunas propiedades al
bean, generado por los tools del aplication developer
<!DOCTIPE ejb-jar PUBLIC .....
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Hello</ejb-name>
<home>HelloHome</home>
<remote>Hello</remote>
<ejb-class>HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
El cliente
import javax.naming.*;
import java.util.*;
import javax.rmi.*;
public class HelloClient {
public static void main(String args[) throws Exception {
Properties props = System.getproperties();
Context ctx = new InitialContext(props);
Object obj = ctx.lookup(“HelloHome”);
HelloHome home = (HelloHome)PortableRemoteObject.narrow
(obj,HelloHome.class);
Hello hello = home.create();
System.out.println(hello.hello());
hello.remove();
}
}
• El lookup se realiza en el recurso de naming (provisto por el
container) que se le da al cliente cuando se lo echa a andar
• Cuando el EJB se sube al contenedor, este registra al Home object
(bind) con el seudónimo “HelloHome” (nombre de clase)
Un Session Servlet con Estado
• Cuando un cliente contacta a un stateful servlet no es tan
conveniente que el container los destruya cuando estime
conveniente ya que el mismo servlet tiene que estar al
servicio del mismo cliente, y el container no puede saber
cuando termina el cliente de contactar al servlet sino hasta
que lo destruye explicitamente.
• Tampoco puede mantenerlos indefinidamente en el
container ya que consumen recursos
• La solución pasa por “pasivarlos” y “activarlos”
• Pasivarlos: pasan de emoria principal a secundaria
• Activarlos: pasan de memoria secundaria a principal
(swapping)
Un Session Servlet con Estado
• El container implementa una “política” de pasivacionactivación por ejemplo, Least Used reciently
• Un bean involucrado en una transaccón o sirviendo a un
cliente no puede ser pasivado
• Se usa serialización
• el método ejbPassivate es llamado antes de copiar el bean
al disco
• el método ejbActivate es llamado cuando se activa
• En cada método se liberan/recuperan recursos que no se
pueden serializar por ej. conexiones a bases de datos,
archivos abiertos (que pasa si esta leyendo en medio del
archivo), conexiones a sockets
El Count Bean
• Tendrá un método count() que incrementa una variable
llamada val
• Esta será la variable que determinará que es un bean de
estado
//interfaz remota
import javax.ejb.*;
import java.rmi.*;
public interface Count extends EJBObject {
public int count() throws RemoteException;
}
//el home interface
import javax.ejb.*;
import java.rmi.*;
public interface CountHome extends EJBHome {
Count create(int val) throws RemoteException, CreateException;
}
El Count Bean
import javax.ejb.*;
public class CountBean extends SessionBean {
public int val;
private SessionContext ctx;
public int count() {
return ++val;
}
public void ejbCreate(int val) {
this.val = val;
}
public
public
public
public
}
}
ejbRemove() {} //llamado antes de eliminar el bean
ejbActivate(){} //llamado al despertar un bean
ejbPassivate(){} //llamado al poner a dormir el bean
setSessionContext(SessionContext ctx) {
this.ctx = ctx;
El Count Bean
<!DOCTIPE ejb-jar PUBLIC .....
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Count</ejb-name>
<home>CountHome</home>
<remote>Count</remote>
<ejb-class>CountBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
Estados de un Bean
Cliente
invoca
create
en un
home
Interface
Cliente llama a remove()
en el ejbObject o se le
da un timeout al cliente
No existe
El container llega a un límite
de su capacidad: swapping
1- Class.newInstance()
2- setSessionContext()
3- ejbCreate(...)
ejbRemove()
Timeout del cleinte
ejbActivate()
Activo
Pasivo
ejbPassivate()
Liente llama a un método del
Bean pasivado
Los Entity beans
• Un bean representa a un dato (fila) en una base de datos
• Hay que pensar en ellos como si fueran uno solo con el dato en
memoria secundaria
• Debe existir un mecanismo para automáticamente transferir los datos
de la memoria secundaria al EJB y vice-versa
• Esto se hace a través de llamadas a los métodos ejbLoad() y ejbStore()
• Estos métodos son llamados por el container cuando estima que es
necesario
• distintos beans pueden representar al mismo dato en disco
• ejbActivate() y ejbPassivate() se llaman cuando un entity bean es
puesto/sacado de un pool de beans, por lo que hay que programas la
adquisición y liberación de reucursos
• Como además se debe guardar el estado del bean en memoria
secundaria, por lo cual se llama siempre a ejbStore abtes de pasivar y
a ejbLoad antes de activar
Las 2 maneras de lograr
persistencia de los beans
• En un bean-manajed persistence entity bean el programador debe
escribir las instrucciones para que las variables del entity bean sean
las correspondientes a un dato en una base de datos (saving, loading,
and finding)
• Estas instrucciones van en los métodos de creación (ejbCreate(...)),
destrucción (ejbRemove()), localización (ejbFind(...)), carga
(ejbload()) y almacenamiento (ejbStore())
• Esto generalmente se hace via instrucciones JDBC
• En los container-managed persistence beans de esto se encarga el
container, sólo basta dar algunas directrices para la localización de los
datos en un archivo especial (según yo, esto sería una de las gracias
más grandes de j2ee)
Creación y destrucción de Beans
• Cuando un entity bean es creado por una llamada al método ejbCreate
se debe crear también este dato en la base de datos, si se trata de un
bean-managed persistence bean, aquí se deben programar las
instruccónes SQL para insertar una fila en una tabla
• De la misma manera, cuando un entity bean es removido, se llama a
ejbRemove y aquí se debe programas la instrucción SQL que borre la
fila correspondiente
• A cada clase de entity bean que se crea hay que asociarle un objeto
que represente la clave primaria de ese tipo de objeto (por ejemplo un
string. Por convención se usa el nombre del bean terminado en PK
(por ejemplo CuentaPK)
• El método ejbCreate de un entity bean debe devolver un siempre un
objeto de este tipo luego de haber creado el dato
Esquema de creación de un entity bean
1- create()
2- ejbCreate()
cliente
Home
4- retorna una
referencia al EJB object
5- creación del
objeto EJB
4- retorna un objeto
que representa la clave
primaria del ejb creado
EJB Object
CONTAINER
Bean
3- se crea el
dato en la base
de datos
Base
de
Datos
Creación y destrucción de Beans
• Si, por ejemplo, tenemos un Bean que se llamará Account, el home object
será de la clase AccountHome, el EJB Object se llamará Account y el
EJBean se llamará AccountBean y el objeto que representa a la clave
primaria se llamará AccountPK
• Para un un método de creación en el AccountHome de la siguiente forma:
– public Account create(String id, String nomb)...
• le corresponderá un método en el AccountBean de las siguiente forma:
– public AccountPK ejbCreate(String id, String nomb)..
• El método remove() se puede aplicar tanto al EJB object como al home
object, en ambos casos se terminará llamando a ejbRemove() que debe
hacerse cargo de borrar el dato de la base de datos
Encontrando Beans (en BMP)
• Como sucede en el manejo directo de bases de datos, muchas veces vamos a
querer encontrar beans, es decir, tener referencia a uno o mas beans que
reflejen datos que ya se encuantran en la base de datos
• Estas se hacen por medio de los métodos findXXX en el home y su
correspondiente ejbFindXXX en el Bean
• Ejemplo para uno: home retorna un EJBobject y el bean un PrimaryKey
– public Account findAnAccountFor(String name) en el home
– public AccountPK ejbFindAnAccountFor(String name) en el Bean
• Ejemplo para varios: home retorna una colección de EJB y el Bean de keys
– public Collection findAllAccountsFor(String name) en el home
– public Collection ejbFindAllAccountsFor(String name) en el Bean
• SIEMPRE debe implementarse al menos el siguiente
– public Account findByPrimaryKey(AccountPK key)
– public AccountPK ejbFindByPrimaryKey(AccountPK key)
El Contexto
• El objeto Context es pasado al bean por el container cuando llama a
setSessionContext o setEntityContext según corresponda. Este contiene
información acerca del contexto del bean
• Si el bean lo necesita, debería mantener una referencia (como se hizo en
el primer ejemplo)
• Los métodos que se pueden llamar son:
– getEJBObject() retorna el EJBObject asociado al bean
– getPrimaryKey() sólo para entity beans (obvio), retorna el key del dato
asociado a esta instancia. Esto es necesario porque un bean no sabe en
principio a que dato está asociado (el EJBObject si)
• Es muy útil en los bean managed persistence entity beans cuando se
programa EjbLoad() para saber qué dato hay que recuperar de la base de
datos (con un select) y asociarlo al bean. También para ejbRemove() para
saber qué fila de la tabla se debe borrar en la base de datos
La Interfaz entity bean
• Cuando se programa un Entity bean hay que programar los siguientes
métodos, (aparte de los “business methods)
–
–
–
–
–
–
–
–
–
–
setEntityContext(EntityContext ctx)
unsetEntityContext() se llama antes de destruirse el bean
ejbFindXXX(...) para encontrar datos según lo especificado en el home
ejbHomeXXX(...) para business methods no asociados a datos (como session)
ejbCreate(...) según lo especificado en el home
ejbRemove()
ejbActivate()
ejbPassivate()
ejbLoad()
ejbStore()
El EJBObject para cuentas
Account
import javax.ejb.*;
import java.rmi.*;
public interface Account extends EJBObject {
public void depositar(int monto) throws RemoteException;
public boolean girar(int monto) throws RemoteException;
public int getSaldo() throws RemoteException;
public String getOwner() throws RemoteException;
public void setOwner(String name) throws RemoteException;
public String getAccountID() throws RemoteException;
public void setAccountID(String ID) throws RemoteException;
}
El Home Interface AccountHome
import
import
import
public
}
java.util.Collection;
javax.ejb.*;
java.rmi.*;
interface AccountHome extends EJBHome {
Account create(String ID, String name)
throws RemoteException, CreateException;
public Account findByPrimaryKey(AccountPK ac)
throws RemoteException, FinderException;
public Collection findByOwnerName(String name)
throws RemoteException, FinderException;
public double getTotelBankValue() throws RemoteException;
El Primary Key AccountPK
import java.io.Serializable;
public class AccountPK implements Serializable {
public String accountID;
public AccountPK(String id) {
accountID = id;
}
public AccountPK() {}
public toString() {
//requerido !!!
return accountID;
}
public hashCode() {
// requerido !!!
return accountID.hashCode();
}
public equals(Object account) { // requerido !!!
return ((AccountPK)account).accountID.equals(accountID);
}
}
El Bean AccountBean (1)
import
import
import
import
java.sql.*;
java.naming.*;
javax.ejb.*;
javax.util.*;
public class AccountBean implements EntityBean {
EntityContext ctx;
String accountID;
String owner;
int saldo;
public void depositar(int monto) {
saldo = saldo + monto;
}
public boolean girar(int monto) {
if (monto >= saldo) {
saldo = saldo - monto;
return true;
}
return false;
}
....
El Bean AccountBean (2)
...
public int getSaldo() {
return saldo;
}
public String getOwner() {
return owner;
}
public void setOwner(String name) {
owner = name;
}
public String getAccountID() {
return accountID;
}
public void setAccountID(String id) {
sccountID = id
}
...
El Bean AccountBean (3)
...
public Connection getConnection() throws Exception {
Class.forName(“com.informix.jdbc.IfxDriver”);
String url = “jdbc:informix-sqli://”+
“hostname/CGE_HOLD:INFORMIXSERVER=servername”;
Connection con =
DriverManager.getConnection(url,”nbaloian”,”123”);
return con;
}
public int ejbHomeGetTotalBankValue() {
try {
Connection conn = getConnection();
PreparedStatement psmt = conn.prepareStatement(
“select sum(saldo) as total from accaounts”);
ResultSet rs = psmt.executeQuery();
psmt.close(); conn.close();
return rs.getInt(“total”);
} catch (Exception e) { //arreglar el pastel
}
}
El Bean AccountBean (4)
...
public void ejbActivate() {
public void ejbPassivate() {
} // es necesario escribirla
} // igual
public void ejbRemove() {
AccountPK pk = (AccountPk) ctx.getPrimaryKey();
String id = pk.acountID;
try {
Connection conn = getconnection();
PreparedStatement psmt = conn.prepareStatement(
“delete from accounts where id = ?”);
psmt.setString(1,id);
if(psmt.executeUpdate() == 0)
System.out.println(“problemas”);
psmt.close(); conn.close();
} catch (Exception e) { e.printStackTrace()}
}
...
El Bean AccountBean (5)
...
public void ejbLoad() {
AccountPK pk = (AccountPk) ctx.getPrimaryKey();
String id = pk.acountID;
try {
Connection conn = getconnection();
PreparedStatement psmt = conn.prepareStatement(
“select ownerName, balance from accounts where id = ?”);
psmt.setString(1,id);
ResultSet rs = psmt.executeQuery();
rs.next();
ownerName = rs.getString(“ownername”);
saldo = rs.getInt(“saledo”);
psmt.close();
conn.close();
} catch (Exception e) { e.printStackTrace()}
}
...
El Bean AccountBean (6)
...
public void ejbStore() {
try {
Connection conn = getconnection();
PreparedStatement psmt = conn.prepareStatement(
“update accounts set ownerName = ?, saldo = ?”+
“where id = ?”);
psmt.setString(1,owner);
psmt.setString(2,saldo);
psmt.setString(3,accountID);
psmt.executeUpdate();
psmt.close();
conn.close();
} catch (Exception e) { e.printStackTrace()}
}
public setEntityContext(EntityContext ctx) {
this.ctx = ctx;
}
public
}
...
unsetEntityCOntext() {
this.ctx = null;
El Bean AccountBean (7)
...
public AccountPK ejbCreate(String id, String name)
throws CreateException {
accountID = id;
ownerName = name;
saldo = 0;
try {
Connection conn = getconnection();
PreparedStatement psmt = conn.prepareStatement(
“insert into accounts (id, ownerName, saldo) values (?,?,?)”);
psmt.setString(1,accountID);
psmt.setString(2,owner);
psmt.setString(3,saldo);
psmt.executeUpdate();
psmt.close(); conn.close();
return new AccountPK(accountID);
} catch (Exception e) { e.printStackTrace()}
}
...
El Bean AccountBean (8)
...
public AccountPK ejbPostCreate(String id, String name)
throws CreateException {
}
// por cada create hay que escribir un PostCreate que se llama
// justo después de la creación
public AccountPK ejbFindByPrimaryKey(AccountPK key) throws
FinderException {
try {
Connection conn = getConnection();
PreparedStatement psmt = conn.prepareStatement(
“select id from account where id = ?”);
psmt.setString(1,key.toString());
ResultSet rs = psmt.executeQuery();
rs.next();
psmt.close(); conn.close();
return key();
catch (Exception e) {....}
}
...
...
El Bean AccountBean (9)
public AccountPK ejbFindByOwnerName(String n) throws
FinderException {
try {
Connection conn = getConnection();
PreparedStatement psmt = conn.prepareStatement(
“select id from account where ownerName = ?”);
psmt.setString(1,n);
ResultSet rs = psmt.executeQuery();
Vector v = new Vector();
while (rs.next()) {
String id = rs.getString(“id”);
v.addElement(new AccountPK(id));
}
psmt.close(); conn.close();
return v;
catch (Exception e) {....}
}
} //por fin !!!
...
El Deployment descriptor
<!DOCTIPE ejb-jar PUBLIC .....
<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>Account</ejb-name>
<home>AccountHome</home>
<remote>Account</remote>
<ejb-class>AccountBean</ejb-class>
<persistence-type>Bean</persistence-type>
<primary-key-class>AccountPK</ primary-key-class >
<reentrant>false</reentrant>
<resource-ref>
<res-ref-name>jdbc/ejPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</entity>
</enterprise-beans>
<assembly-descriptor>
....para transacciones...
</assembly-descriptor>l
</ejb-jar>
Los CMP Entity Beans
• La idea principal es no tener que escribir
ningun código de persistencia con la base de
datos
• Mucho del código migra del Bean al
Deployment descriptor (pero muy
simplificado)
• Juega un papel importante el EJB-QL, que es
un lenguaje estilo SQL orientado a objetos
con el cual se especifican muchas cosas.
Principalen diferencias con BMP
• Lo que uno escribe es una superclase del bean, que será extendida
automáticamente por el sistema para añadirle el código de persistencia
• Por esto, la declaración de un CMP es abstract !!!
• No se declaran Campos del bean (variables). Estas van especificadas en el
Deployment descriptor y aparecen en la clase extendida
• Por eso mismo, tampoco se escriben los métodos set/get finales, sólo se
declaran en forma abstracta (como en una interfaz)
• los métodos find también se declaran en horma abstracta. La forma de
cómo localizan los beans se da por medio del EJB-QL en el deployment
descriptor
• también se pueden definir métodos abstractos ejbSelectXXX que serán
usados al interior del bean. Estos no sólo pueden ubicar beans sino que
campos de ellos (por ejemplo, el saldo de todas las cuentas que
pertenecen a un owner dado)
Métodos a declarar en el Bean
• setEntityContext() igual que en los BMP
• ejbFindXXX(...) se declaran en forma abstracta, la forma cómo deben
trabajar se especifica en el deployment descriptor con el EJB-QL
• ejbSelectXXX(...) igual que para el punto anterior, pero estos no son
visibles desde el EJBObject, son par auso interno del bean
• ejbHomeXXX(...) para declaración de métodos “estáticos”
• ejbCreate(...) no se debe escribir código que inserta datos en la base de
datos. Sólo se usan los métodos setXXX para poner el valor a los campos
según lo pasado por los parámetros (o no)
• ejbPostCreate(...) igual que en BMP
• ejbActivate() igual que en BMP
• ejbLoad() no hacer cosas que tengan que ver con cargar el dato, esto lo
implementa el container. (pero adquirir recursos)
• ejbStore() idem anterior (pero liberar recursos)
• ejbRemove() idem anterior
• ejbUnsetEntityContent() igual que para BMP
El EJBObject para Product
import javax.ejb.*;
import java.rmi.*;
public interface Product extends EJBObject {
public String getName() throws RemoteException;
public void setName(String name) throws RemoteException;
public String getDescription() throws RemoteException;
public void setDescription(String desc) throws RemoteException;
public double getBasePrice() throws RemoteException;
public void setBasePrice(double price) throws RemoteException;
public String getProductID() throws RemoteException;
public void setProductID(String id) throws RemoteException;
}
El Home Interface ProductHome
import
import
import
public
}
java.util.Collection;
javax.ejb.*;
java.rmi.*;
interface ProductHome extends EJBHome {
Product create(String ProductID, String name,
String description, double price)
throws RemoteException, CreateException;
poublic Product findByPrimaryKey(ProductPK key)
throws RemoteException, FinderException;
public Collection findByName(String name)
throws RemoteException, FinderException;
public Collection findByDescription(String desc)
throws RemoteException, FinderException;
public Collection findByBasePrice(double price)
throws RemoteException, FinderException;
public Collection findExpensiveProducts(double price)
throws RemoteException, FinderException;
public Collection findCheapProducts(double price)
throws RemoteException, FinderException;
public Collection findAll(String name)
throws RemoteException, FinderException;
El Primary Key ProductPK
import java.io.Serializable;
public class ProductPK implements Serializable {
public String productID;
public ProductPK(String id) {
productID = id;
}
public productID() {}
public toString() {
//requerido !!!
return productID;
}
public hashCode() {
// requerido !!!
return productID.hashCode();
}
public equals(Object prod) { // requerido !!!
return ((AccountPK)prod). productID.equals(productID);
}
}
El Bean ProductBean (1)
import java.sql.*;
public abstract class ProducttBean implements EntityBean {
EntityContext ctx;
public
public
public
public
public
public
public
public
abstract
abstract
abstract
abstract
abstract
abstract
abstract
abstract
public
public
public
public
public
....
void
void
void
void
void
String getName();
void setName(String name);
String getDescription();
void setDescription(String desc);
double getBasePrice();
void setBasePrice(double price);
String getProductID();
void setProductID(String id);
ejbActivate() {}
ejbPasivate() {}
ejbRemove() {}
ejbLoad() {}
ejbStore() {}
El Bean ProductBean (2)
...
public void setEntityContext(EntityContext ctx) {
this.ctx = ctx;
}
public void unsetEntityContext() {this.ctx = null;}
public void ejbPostCreate(String id, String name
String desc, double price) {}
public String Create(String id, String name
String desc, double price) {
setProductID(id);
setName(name);
setDescription(desc);
setBasePrice(price);
return id; //sorry esta en el libro
}
}
El Deployment descriptor es
bastante grande, claro
<!DOCTIPE ejb-jar PUBLIC .....
<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>Product</ejb-name>
<home>ProductHome</home>
<remote>Product</remote>
<ejb-class>ProductBean</ejb-class>
<persistence-type>Container</persistence-type>
<primary-key-class>ProductPK</ primary-key-class >
<reentrant>false</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>ProductBean</abstract-schema-name>
<cmp-field>
<field-name>productID</field-name>
</cmp-field>
<cmp-field>
<field-name>name</field-name>
</cmp-field>
<cmp-field>
<field-name>description</field-name>
</cmp-field>
<cmp-field>
<field-name>basePrice</field-name>
</cmp-field>
El Deployment descriptor es
bastante grande, claro
<query>
<query-method>
<method-name>findByName</method-name>
<method-params>
<method-param>java.lang.String</method-param>
<method-params>
<query-method>
<ejb-sql>
<![CDATA[SELECT OBJECT (a) FROM ProducBean AS a WHERE name = ?1>
</ejb-sql>
</query>
<query>
<query-method>
<method-name>findExpensiveProducts</method-name>
<method-params>
<method-param>double</method-param>
<method-params>
<query-method>
<ejb-sql>
<![CDATA[SELECT OBJECT (a) FROM ProducBean AS a WHERE basePrice > ?1>
</ejb-sql>
</query>
</entity>
</enterprise-beans>
El Deployment descriptor es
bastante grande, claro
<assembly-descriptor>
....para transacciones...
</assembly-descriptor>l
</ejb-jar>