La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Toni Navarrete Enginyeria del Software II – UPF 2005

Presentaciones similares


Presentación del tema: "Toni Navarrete Enginyeria del Software II – UPF 2005"— Transcripción de la presentación:

1 Toni Navarrete Enginyeria del Software II – UPF 2005
Disseny de la persistència Enterprise Java Beans i la persistència manegada pel contenidor Toni Navarrete Enginyeria del Software II – UPF 2005

2 Tutorial de J2EE de Sun Aquesta presentació està basada en bona part en el tutorial de J2EE 1.4 de Sun, que podeu baixar de:

3 EJB EJB=Enterprise Java Bean
Escrit en Java, un EJB és un component de servidor que encapsula lògica de negoci d’una aplicació La lògica de negoci és el codi que satisfà els propòsits d’una aplicació Per exemple, en una aplicació de gestió d’inventaris, un ejb pot implementar la lògica de negoci amb mètodes anomenats controlarNivellInventari i ferComandaProducte Un altre exemple: mantenir un “carretó de la compra” Un EJB corre a un EJB-container, que és una part d’un servidor d’aplicacions

4 Arquitectura de tres capes
Browser HTTP Capa de presentació Web server CORBA/RMI/... Capa de negoci Application server JDBC Capa de dades File system Base de dades

5 No confondre EJB amb Java Bean.
EJB versus Java Bean No confondre EJB amb Java Bean. Un EJB és un "deployable component". El terme indica que existeix un ambient d’execució. Aquest ambient és el EJB-container. En ell, el component és independent Un Java Bean ha d’estar integrat amb altres components per ser funcional

6 Arquitectura d’un servidor d’aplicacions
Exemples: J2ee server (RI, només per desenvolupament) Tomcat (servlet engine) + Jboss (EJB-container) “Fully-J2EE-compliant”: WebLogic, Websphere, Jrun, Oracle 9i Application Server, Sun ONE Application Server

7 Tres tipus d’EJB Session EJBs Messaging EJBs
Un Session EJB permet implementar una lògica concreta, sol·lictiada per un client (que pot ser un JSP/Servlet, un applet o altre EJB) N’hi ha que no guarden el seu estat (stateless session ejb), per exemple, un ejb que implementa una operació que no requereix guardar dades del client, com una cerca, i n’hi ha que sí (statefull session ejb), per exemple, un “carretó de la compra” Messaging EJBs Ofereixen funcionalitats de sistemes de missatgeria asíncrona No els estudiarem

8 Tres tipus d’EJB Entity EJBs
Un Entity ejb, al contrari que un session ejb, treballa conjuntament amb un repositori persistent de dades (típicament una BD) Així, un entity ejb pot llegir i escriure informació externa al ejb-container (a una BD) Exemples: clients, comandes, productes... Típicament un entity ejb està mapejat amb una taula d’una BDR, i cada instància del bean es correspondrà amb una fila El ejb container dóna suport de pooling sense haver de programar-ho

9 Dos tipus de Entity EJB Bean Managed Persistence
El propi EJB s’encarrega de definir la lògica per accedir (manipular i consultar) a la BD. És a dir, s’ha de programar manualment, típicament utilitzant JDBC per sota Container Managed Persistence El propi ejb-container és qui s’encarrega de definir la lògica per accedir a la BD Molt transparent! Aparentement, un “bean managed ejb” sembla que no té massa sentit, però hi ha casos en què la lògica d’accés pot ser molt complexa i pot interessar fer-ho manualment

10 Estructura d’un EJB Un EJB està format per una classe, dues interfícies i un fitxer de “deployment”, agrupats en un un fitxer jar Remote interface (Converter) Home interface (ConverterHome) El propi ejb (ConverterEJB o ConverterBean)

11 Remote interface La interfície remota defineix els mètodes de negoci que un client pot cridar. Els mètodes de negoci s’implementarien a la classe del ejb Extèn EJBObject Un exemple (d’un session ejb): package converter; import javax.ejb.EJBObject; import java.rmi.RemoteException; import java.math.*; public interface Converter extends EJBObject { public BigDecimal dollarToYen(BigDecimal dollars) throws RemoteException; public BigDecimal yenToEuro(BigDecimal yen) }

12 Home interface La interfície home defineix els mètodes que permeten a un client crear, trobar i eliminar un ejb Extèn EJBHome En l’exemple, conté només un mètode de creació, que retorna un objecte que implementa la interfície remota package converter; import java.io.Serializable; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface ConverterHome extends EJBHome { Converter create() throws RemoteException, CreateException; }

13 La classe ejb La classe ejb ha d’implementar els mètodes de negoci definits a la interfície remota i els mètodes relacionats amb el cicle de vida (ejbCreate, ejbActivate...) Constructor sense arguments obligatori Implementa les interfícies SessionBean o EntityBean Exemple: package converter; import java.rmi.RemoteException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import java.math.*; public class ConverterBean implements SessionBean { BigDecimal yenRate = new BigDecimal(" "); BigDecimal euroRate = new BigDecimal("0.0077"); public BigDecimal dollarToYen(BigDecimal dollars) { BigDecimal result = dollars.multiply(yenRate); return result.setScale(2,BigDecimal.ROUND_UP); } public BigDecimal yenToEuro(BigDecimal yen) { BigDecimal result = yen.multiply(euroRate); public ConverterBean() {} public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {}

14 Una aplicació client (ConverterClient.java)
S’ha de crear el naming context inicial, part de JNDI (Java Naming and Directory Interface) Context initial = new InitialContext(); Un naming context és un conjunt de bindings entre noms i objectes. El context inicial és el punt de començament per fer la resolució de noms. Totes les operacions de noms són relatives a un determinat context. Ara obtenim el naming context de l’aplicació client Context myEnv = (Context)initial.lookup("java:comp/env"); I recuperem l’objecte lligat al nom ejb/SimpleConverter Object objref = myEnv.lookup("ejb/SimpleConverter");

15 Una aplicació client (ConverterClient.java)
ejb/SimpleConverter és el nom lògic que fa referència a la interfície home d’un ejb, en el nostre cas de ConverterHome object Els noms dels ejbs han d’estar sembre en el subcontext java:com/env/ejb A partir de la referència obtenim un objecte ConverterHome (narrow the reference) ConverterHome home = (ConverterHome) PortableRemoteObject.narrow(objref, ConverterHome.class);

16 Una aplicació client (ConverterClient.java)
Ara es crea la instància del ejb, cridant el mètode create definit a ConverterHome. Aquest mètode retorna un objecte de tipus Converter (que implementa la interfície remota Converter) i que recordem que té els mètodes de negoci als quals pot cridar el client Converter currencyConverter = home.create(); Ara ja es poden cridar els mètodes de negoci: BigDecimal param = new BigDecimal ("100.00"); BigDecimal amount = currencyConverter.dollarToYen(param);

17 Codi del client import converter.*; import javax.naming.Context;
import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; import java.math.BigDecimal; public class ConverterClient { public static void main(String[] args) { try { Context initial = new InitialContext(); Object objref = initial.lookup ("java:comp/env/ejb/SimpleConverter"); ConverterHome home = (ConverterHome)PortableRemoteObject.narrow(objref, ConverterHome.class); Converter currencyConverter = home.create(); BigDecimal param = new BigDecimal ("100.00"); BigDecimal amount = currencyConverter.dollarToYen(param); System.out.println(amount); amount = currencyConverter.yenToEuro(param); System.exit(0); } catch (Exception ex) { System.err.println("Caught an unexpected exception!"); ex.printStackTrace(); } Codi del client

18 Codi del client index.jsp (1/2)
page import="converter.Converter, converter.ConverterHome, javax.ejb.*, java.math.*, javax.naming.*, javax.rmi.PortableRemoteObject, java.rmi.RemoteException" %> <%! private Converter converter = null; public void jspInit() { try { InitialContext ic = new InitialContext(); Object objRef = ic.lookup("java:comp/env/ejb/TheConverter"); ConverterHome home = (ConverterHome)PortableRemoteObject.narrow(objRef, ConverterHome.class); converter = home.create(); } catch (RemoteException ex) { ... } %> <html> <head> <title>Converter</title> </head> Noteu que diferents clients poden utilitzar diferents noms lògics

19 Codi del client index.jsp (2/2)
<body bgcolor="white"> <h1><center>Converter</center></h1> <hr> <p>Enter an amount to convert:</p> <form method="get"> <input type="text" name="amount" size="25"> <br> <p> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </form> <% String amount = request.getParameter("amount"); if ( amount != null && amount.length() > 0 ) { BigDecimal d = new BigDecimal (amount); %> <p><%= amount %> dollars are <%= converter.dollarToYen(d) %> Yen. <p><%= amount %> Yen are <%= converter.yenToEuro(d) %> Euro. } </body> </html>

20 Eina deploytool del J2EE RI Cal definir els bindings de noms JDNI
Deployment Eina deploytool del J2EE RI Cal definir els bindings de noms JDNI ejb/SimpleConverter en l’aplicació client ejb/TheConverter en l’aplicació web Web context: /converter

21 Execució Cal posar en marxa el j2ee container:
j2ee –verbose (versions anteriors a 1.4) Vegeu documentació per 1.4 (en Windows es fa des de “Inicio”-”Programas”) Fem el deploy (implementación en la versió en castellà) Executem Client web Aplicació client ConverterAppClient.jar s’obté en fer el deploy appclient -client ConverterAppClient.jar

22 Interfícies locals i interfícies remotes
El que hem vist és quan el client remot hi accedeix Una altra possibilitat és que hi accedeixin objectes locals (de la mateixa JVM), s’utilitzen altres interfícies, tot i que són equivalents: LocalHome (LocalConverterHome) Local Interface (LocalConverter) De nou, Local defineix els mètodes de negoci i LocalHome els del cicle de vida i “finders” En cas de dubte: remot (es poden declarar les dues però no és gens comú) Cas particular: els ejb d’entitat que són container-managed i tenen relacions amb altres ejb, han de tenir interfaces locals i no remotes

23 Remote vs local interfaces
The decision on whether to allow local or remote access depends on the following factors: Container-Managed Relationships If an entity bean is the target of a container-managed relationship, it must use local access. Tight or Loose Coupling of Related Beans Tightly coupled beans depend on one another. For example, a completed sales order must have one or more line items, which cannot exist without the order to which they belong. The OrderEJB and LineItemEJB beans that model this relationship are tightly coupled. Tightly coupled beans are good candidates for local access. Since they fit together as a logical unit, they probably call each other often and would benefit from the increased performance that is possible with local access. Type of Client If an enterprise bean is accessed by J2EE application clients, then it should allow remote access. In a production environment, these clients almost always run on different machines than the J2EE server. If an enterprise bean's clients are web components or other enterprise beans, then the type of access depends on how you want to distribute your components. Component Distribution J2EE applications are scalable because their server-side components can be distributed across multiple machines. In a distributed application, for example, the web components may run on a different server than the enterprise beans they access. In this distributed scenario, the enterprise beans should allow remote access.

24 Importància de les interfícies
Unes interfícies ben dissenyades simplifiquen el desenvolupament i manteniment d’aplicacions J2EE Fent bones interfícies, a més d’amagar la compexitat interna de la capa d’EJBs als clients, permet que els canvis interns en els beans no afectin als clients Per exemple, fins i tot si canviem un bean d’entitat de BMP a CMP, no caldrà canviar el codi del client Lògicament, sí caldrà canviar el client en el moment en què es canvïin la definició dels mètodes de les interfícies Conclusió: dissenyar amb esment les interfícies per evitar posteriors canvis en els clients

25 EJBs d’entitat Quan el client invoca un mètode create, el EJB container invoca el corresponent mètode ejbCreate. Típicament un mètode ejbCreate en un bean d’entitat fa les següents tasques: Inserta l’estat de l’entitat a la BD Inicialitza les variables d’instància Retorna la primary key

26 Interfície remota És la que conté els mètodes de negoci que invocarà el client Exemple: public interface SavingsAccount extends EJBObject { public void debit(BigDecimal amount) throws InsufficientBalanceException, RemoteException; public void credit(BigDecimal amount) throws RemoteException; public String getFirstName() public String getLastName() public BigDecimal getBalance() }

27 Interfície home Conté la definició de:
Mètode create: és el que permet crear la instància de la interfície remota al client: public SavingsAccount create(String id, String firstName, String lastName, BigDecimal balance) throws RemoteException, CreateException; Es correspon amb el mètode ejbCreate definit a la classe del Bean Mètodes de find Mètodes de home

28 Exemple de mètode create
A la interfície home public SavingsAccount create(String id, String firstName, String lastName, BigDecimal balance) throws RemoteException, CreateException; private void insertRow (String id, String firstName, String lastName, BigDecimal balance) throws SQLException { String insertStatement = "insert into savingsaccount values ( ? , ? , ? , ? )"; PreparedStatement prepStmt = con.prepareStatement(insertStatement); prepStmt.setString(1, id); prepStmt.setString(2, firstName); prepStmt.setString(3, lastName); prepStmt.setBigDecimal(4, balance); prepStmt.executeUpdate(); prepStmt.close(); } public String ejbCreate(String id, String firstName, String lastName, BigDecimal balance) throws CreateException { if (balance.signum() == -1) { throw new CreateException ("A negative initial balance is not allowed."); } try { insertRow(id, firstName, lastName, balance); } catch (Exception ex) { throw new EJBException("ejbCreate: " + ex.getMessage()); this.id = id; this.firstName = firstName; this.lastName = lastName; this.balance = balance; return id; A la classe ejb

29 Mètodes finder Els mètodes finder permeten els clients localitzar beans d’entitat La classe ejb ha d’implementar tots els mètodes de finder que s’hagin especificat a la interfície home A la interfície els mètodes finder sempre han de començar per find, mentre que a la classe del bean ho han de fer per ejbFind i han de ser públics (i no poden ser ni finals ni estàtics) Els paràmetres han de coincidir entre els ejbFind i els find El tipus de retorn dels mètodes find (de la interfície home) ha de ser la interfície remota del bean, o una col·lecció d’aquests El tipus de retorn dels mètodes ejbFind (de la classe del bean), és sempre una primary key o bé una col·lecció de primary keys Nota: el client crida els mètodes find, mentre que els ejbFind els crida el container ejbFindByPrimaryKey és obligatori d’implementar (els altres depenen de la lògica de negoci)

30 Exemple de mètodes finder
A la interfície home public SavingsAccout findByPrimaryKey(String id) throws FinderException, RemoteException; public Collection findByLastName(String lastName) throws FinderException, RemoteException; public Collection findInRange(BigDecimal low, BigDecimal high) throws FinderException, RemoteException; public Collection ejbFindByLastName(String lastName) throws FinderException { Collection result; try { result = selectByLastName(lastName); } catch (Exception ex) { throw new EJBException("ejbFindByLastName " + ex.getMessage()); } return result; public Collection ejbFindInRange(BigDecimal low, BigDecimal high) result = selectInRange(low, high); throw new EJBException("ejbFindInRange: " + public String ejbFindByPrimaryKey(String primaryKey) throws FinderException { boolean result; try { result = selectByPrimaryKey(primaryKey); } catch (Exception ex) { throw new EJBException("ejbFindByPrimaryKey: " + ex.getMessage()); } if (result) { return primaryKey; else { throw new ObjectNotFoundException ("Row for id " + primaryKey + " not found."); A la classe ejb

31 private boolean selectByPrimaryKey(String primaryKey)
throws SQLException { String selectStatement = "select id " + "from savingsaccount where id = ? "; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setString(1, primaryKey); ResultSet rs = prepStmt.executeQuery(); boolean result = rs.next(); prepStmt.close(); return result; }

32 private Collection selectByLastName(String lastName)
throws SQLException { String selectStatement = "select id " + "from savingsaccount where lastname = ? "; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setString(1, lastName); ResultSet rs = prepStmt.executeQuery(); ArrayList a = new ArrayList(); while (rs.next()) { String id = rs.getString(1); a.add(id); } prepStmt.close(); return a;

33 private Collection selectInRange(BigDecimal low, BigDecimal high)
throws SQLException { String selectStatement = "select id from savingsaccount " + "where balance between ? and ?"; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setBigDecimal(1, low); prepStmt.setBigDecimal(2, high); ResultSet rs = prepStmt.executeQuery(); ArrayList a = new ArrayList(); while (rs.next()) { String id = rs.getString(1); a.add(id); } prepStmt.close(); return a;

34 Mètodes de Home Un mètode home conté la lògica de negoci que s’aplica a tots els beans d’entitat d’una classe. En canvi, els mètodes de negoci s’apliquen a instàncies individuals, que tenen un id únic Típicament, un mètode home localitza una col·lecció d’instàncies bean i invoca mètodes de negoci a mesura que va iterant la col·lecció Estan declarats a la interfície home i s’implementen a la classe del bean A la interfície home no tenen cap prefixe Al bean, sempre comencen pel prefix ejbHome, seguit del nom del mètode a la interfície home. Sempre han de ser públics (i no poden ser estàtics)

35 Exemple de mètode home A la interfície home public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal charge) throws InsufficientBalanceException, RemoteException; public void ejbHomeChargeForLowBalance(BigDecimal minimumBalance, BigDecimal charge) throws InsufficientBalanceException { //cobra una comissió a aquells comptes que tenen un balanç inferior a un cert valor try { SavingsAccountHome home = (SavingsAccountHome)context.getEJBHome(); Collection c = home.findInRange(new BigDecimal("0.00"), minimumBalance.subtract(new BigDecimal("0.01"))); Iterator i = c.iterator(); while (i.hasNext()) { SavingsAccount account = (SavingsAccount)i.next(); if (account.getBalance().compareTo(charge) == 1) { account.debit(charge); } } catch (Exception ex) { throw new EJBException("ejbHomeChargeForLowBalance: " + ex.getMessage()); A la classe ejb

36 Classe EJB Resumint, la classe EJB haurà d’implementar:
Interfície EntityBean Zero o més mètodes ejbCreate i ejbPostCreate També mètodes ejbRemove, ejbLoad, ejbStore, ejbActivate i ejbPassivate Mètodes finder i mètodes de home Mètodes de negoci (els definits la interfície remota) El container invoca ejbCreate quan el client invoca create de la interfície Home. Immediatament després de cridar ejbCreate, el container invoca ejbPostCreate. Així, a diferència d’ejbCreate, ja pot invocar els mètodes getPrimaryKey i getEJBObject de la interfície EntityContext

37 public class SavingsAccountBean implements EntityBean {
private String id; private String firstName; private String lastName; private BigDecimal balance; private EntityContext context; private Connection con; private String dbName = "java:comp/env/jdbc/SavingsAccountDB"; public void debit(BigDecimal amount) throws InsufficientBalanceException { if (balance.compareTo(amount) == -1) { throw new InsufficientBalanceException(); } balance = balance.subtract(amount); public void credit(BigDecimal amount) { balance = balance.add(amount); public String getFirstName() { return firstName; public String getLastName() { return lastName; public BigDecimal getBalance() { return balance; ... //finders, home i cicle de vida

38 Classe EJB (cont.) El mètode ejbRemove provoca que s’esborri una instància del bean, i que s’elimini el seu estat de la BD El crida el container quan el client crida el mètode remove Exemple: public void ejbRemove() { try { deleteRow(id); } catch (Exception ex) { throw new EJBException("ejbRemove: " + ex.getMessage()); } ... private void deleteRow(String id) throws SQLException { String deleteStatement = "delete from savingsaccount where id = ? "; PreparedStatement prepStmt = con.prepareStatement(deleteStatement); prepStmt.setString(1, id); prepStmt.executeUpdate(); prepStmt.close();

39 Cicle de vida d’un bean d’entitat

40 Exemple de classe client
public class SavingsAccountClient { public static void main(String[] args) { try { Context initial = new InitialContext(); Object objref = initial.lookup("java:comp/env/ejb/SimpleSavingsAccount"); SavingsAccountHome home = (SavingsAccountHome)PortableRemoteObject.narrow(objref, SavingsAccountHome.class); BigDecimal zeroAmount = new BigDecimal("0.00"); SavingsAccount duke = home.create("123", "Duke", "Earl", zeroAmount); duke.credit(new BigDecimal("88.50")); duke.debit(new BigDecimal("20.25")); BigDecimal balance = duke.getBalance(); System.out.println("balance = " + balance); duke.remove(); SavingsAccount joe = home.create("836", "Joe", "Jones", zeroAmount); joe.credit(new BigDecimal("34.55")); SavingsAccount jones = home.findByPrimaryKey("836"); jones.debit(new BigDecimal("2.00")); balance = jones.getBalance(); SavingsAccount pat = home.create("456", "Pat", "Smith", zeroAmount); pat.credit(new BigDecimal("44.77")); SavingsAccount john = home.create("730", "John", "Smith", zeroAmount); john.credit(new BigDecimal("19.54")); SavingsAccount mary = home.create("268", "Mary", "Smith", zeroAmount); mary.credit(new BigDecimal("100.07")); Collection c = home.findByLastName("Smith"); Iterator i=c.iterator(); while (i.hasNext()) { SavingsAccount account = (SavingsAccount)i.next(); String id = (String)account.getPrimaryKey(); BigDecimal amount = account.getBalance(); System.out.println(id + ": " + amount); } ... Exemple de classe client

41 Dos tipus d’EJB d’entitat
BMP (Bean-Managed Persistence) La persistència es manega directament pel propi bean, incloent la connexió a la BD i el codi SQL necessari Exemple SavingAccounts CMP (Container-Managed Persistence) Serà el container qui s’encarregarà de la persistència

42 Interfície remota (local) amb CMP
Com amb BMP, declara els mètodes de negoci S’usa la interfíe Local (no remota): public interface LocalPlayer extends EJBLocalObject { public String getPlayerId(); public String getName(); public String getPosition(); public double getSalary(); public Collection getTeams(); public Collection getLeagues() throws FinderException; public Collection getSports() throws FinderException; }

43 Interfície Home amb CMP
Com amb BMP, declara el mètode create, finders i homes public interface LocalPlayerHome extends EJBLocalHome { public LocalPlayer create (String id, String name, String position, double salary) throws CreateException; public LocalPlayer findByPrimaryKey (String id) throws FinderException; public Collection findByPosition(String position) public Collection findByHigherSalary(String name) public Collection findBySalaryRange(double low, double high) public Collection findByLeague(LocalLeague league) public Collection findBySport(String sport) public Collection findByCity(String city) public Collection findAll() public Collection findNotOnTeam() public Collection findByPositionAndName(String position, String name) throws FinderException; public Collection findByTest (String parm1, String parm2, String parm3) }

44 La classe del bean amb CMP
Ha de ser pública i abstracta Haurà d’implementar: La interfície EntityBean Zero o més mètodes ejbCreate i ejbPostCreate Els mètodes home Els mètodes de negoci També inclou: La declaració, com a mètodes abstactes, dels mètodes d’accés get i set per a tots els atributs persistents i per als camps de relació Els atributs no es declaren, només els seus getters i setters La declaració, com a mètodes abstractes, dels mètodes de select Per tant, NO ha d’implementar: Els mètodes finder Nota: Mai pot incloure mètodes finalize

45 Finds i selects Diferències entre finds i selects
Son semblans, ja que tots dos serveixen per fer seleccions: Un mètode select retorna una interfície local o remota (o una col·lecció d’interfícies) Consulta la BD El descriptor de deployment especifica una consulta en EJB QL para cada mètode select La classe bean no implementa els mètodes select Però es diferencien en: Un mètode select pot retornar un camp persistent (o una col·lecció d’ells) d’un ejb d’entitat relacionat. Un mètode de finder només pot retornar una interfície local o remota (o una col·lecció d’elles) Els mètodes de select no s’exposen en cap interfície, amb la qual cosa no es poden invocar des dels clients, només es poden cridar des de dins del propi ejb, típicament des d’un altre mètode de negoci Els mètodes de select es declaren com a abstractes a la classe ejb. Els finder si BMP s’implementen a la ejb, si CMP no.

46 Exemple de Bean // EntityBean methods
public String ejbCreate (String id, String name, String position, double salary) throws CreateException { Debug.print("PlayerBean ejbCreate"); setPlayerId(id); setName(name); setPosition(position); setSalary(salary); return null; } public void ejbPostCreate (String id, String name, String position, double salary) throws CreateException { } public void setEntityContext(EntityContext ctx) { context = ctx; public void unsetEntityContext() { context = null; public void ejbRemove() { Debug.print("PlayerBean ejbRemove"); public void ejbLoad() { Debug.print("PlayerBean ejbLoad"); public void ejbStore() { Debug.print("PlayerBean ejbStore"); public void ejbPassivate() { } public void ejbActivate() { } } // PlayerBean class Exemple de Bean public abstract class PlayerBean implements EntityBean { private EntityContext context; // Access methods for persistent fields public abstract String getPlayerId(); public abstract void setPlayerId(String id); public abstract String getName(); public abstract void setName(String name); public abstract String getPosition(); public abstract void setPosition(String position); public abstract double getSalary(); public abstract void setSalary(double salary); // Access methods for relationship fields public abstract Collection getTeams(); public abstract void setTeams(Collection teams); // Select methods public abstract Collection ejbSelectLeagues(LocalPlayer player) throws FinderException; public abstract Collection ejbSelectSports(LocalPlayer player) // Business methods public Collection getLeagues() throws FinderException { LocalPlayer player = (team.LocalPlayer)context.getEJBLocalObject(); return ejbSelectLeagues(player); } public Collection getSports() throws FinderException { return ejbSelectSports(player);

47 EJB QL El llenguatge Enterprise JavaBeans Query Language ("EJB QL") permet definir les queries corresponents als mètodes finder i select d’un bean d’entitat amb CMP EJB QL és una extensió de SQL92 que permet navegar sobre les relacions definides en el esquema abstracte d’un bean d’entitat Una query EJB QL pot “abarcar” l’esquema abstracte d’altres beans que estiguin empaquetats en el mateix fitxer EJB JAR La query EJB QL es defineix en el deployment descriptor del bean d’entitat. Típicament, una eina tradueix aquestes queries al llenguatge d’accés que utilitza el magatzem de dades (normalment SQL) Gràcies a aquesta traducció, els beans d’entitat amb CMP són portables (el seu codi no està lligat a cap magatzem de dades específic)

48 EJB QL La sintaxi és molt semblant a SQL
Clàusules SELECT, FROM i WHERE Exemple: seleccionar tots els objectes de Player: SELECT OBJECT(p) FROM Player p Això es correspon amb el mètode abstracte: findall() Exemple: seleccionar els players que juguen a una certa posició i tenen un cert nom: SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.position = ?1 AND p.name = ?2 findByPositionAndName(String position, String name)

49 EJB QL Exemple: seleccionar els players que pertanyen a algun equip d’una certa ciutat: SELECT DISTINCT OBJECT(p) FROM Player p, IN (p.teams) AS t WHERE t.city = ?1 Això es correspon amb el mètode abstracte: findByCity(String city) Exemple: seleccionar els players que no tenen cap equip: SELECT OBJECT(p) FROM Player p WHERE p.teams IS EMPTY findNotOnTeam()

50 EJB QL Exemple: seleccionar les lligues a les quals juga l’equip d’un cert jugador SELECT DISTINCT t.league FROM Player p, IN (p.teams) AS t WHERE p = ?1 Això es correspon amb el mètode abstracte: ejbSelectSports(LocalPlayer player)

51 EJB QL i SQL al deployment
Quan es genera el fitxer de deployment, s’ha d’especificar quina query EJB QL es correspon amb cada mètode abstracte find i select declarat a la classe del bean i a la interfíce Home Sobre un container concret, això es traduirà automàticament a SQL Normalment queda guardat a un fitxer de configuració de l’aplicació En el cas de RI: sun-j2ee-ri.xml

52 EJB QL i SQL al deployment. Exemple de fitxer amb EJB QL
<ejb-jar> <display-name>TeamJAR</display-name> <enterprise-beans> <entity> <display-name>PlayerBean</display-name> <ejb-name>PlayerBean</ejb-name> <local-home>team.LocalPlayerHome</local-home> <local>team.LocalPlayer</local> <ejb-class>team.PlayerBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.String</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Player</abstract-schema-name> <cmp-field> <description>no description</description> <field-name>position</field-name> </cmp-field> <field-name>playerId</field-name> <field-name>name</field-name> <field-name>salary</field-name> <primkey-field>playerId</primkey-field> ... ... <query> <description></description> <query-method> <method-name>findAll</method-name> <method-params /> </query-method> <ejb-ql>select object(p) from Player p</ejb-ql> </query> <method-name> ejbSelectSports </method-name> <method-params> <method-param> team.LocalPlayer </method-param> </method-params> <ejb-ql>select distinct t.league.sport from Player p, in (p.teams) as t where p = ?1</ejb-ql> </enterprise-beans> </ejb-jar>

53 EJB QL i SQL al deployment. Exemple de fitxer amb SQL
<j2ee-ri-specific-information> ... <ejb> <ejb-name>PlayerBean</ejb-name> <jndi-name>MyPlayer</jndi-name> <ejb20-cmp> <sql-statement> <method> <method-intf>LocalHome</method-intf> <method-name>findAll</method-name> <method-params /> </method> <sql>SELECT "p"."playerId" FROM "PlayerBeanTable" "p" </sql> </sql-statement> <method-intf>Bean</method-intf> <method-name>ejbSelectSports</method-name> <method-params> <method-param>team.LocalPlayer</method-param> </method-params> <sql>SELECT DISTINCT FROM "PlayerBeanTable" "p" , "TeamBeanTable" "t" , "PlayerBean_teams_TeamEJB_playersTable" , "LeagueBeanTable" , "LeagueEJB_teams_TeamEJB_leagueTable" WHERE (("p"."playerId" = ? )) AND (("p"."playerId" = AND = "t"."teamId")) AND (("t"."teamId" = AND = </j2ee-ri-specific-information>

54 Permet definir de forma abstracta els mètodes find i select
Conclusions sobre CMP Permet definir de forma abstracta els mètodes find i select S’implementen en EJB QL de forma que sigui independent del gestor (i del container) Els mètodes de negoci del bean no accedeixen mai directament a les dades, sinó que ho fan mitjançant els mètodes getters, setters i selects, tots abstractes La lògica de negoci és independent de la capa de dades

55 Resum : diferències entre BMP-CMP
Difference Container-Managed Bean-Managed Class definition Abstract Not abstract Database access calls Generated by tools Coded by developers Persistent state Represented by virtual persistent fields Coded as instance variables Access methods for persistent and relationship fields Required None findByPrimaryKey method Handled by container Customized finder methods Handled by container, but the developer must define the EJB QL queries Select methods Return value of ejbCreate Should be null Must be the primary key

56 Recordatori dels diferents Java Archives
JAR (Java ARchives) JAR ("Java Archives") és un format desenvolupat per Sun que permet agrupar les classes Java per a la seva distribució. S’utilitza sovint en qualsevol “ambient” de Java, ja que redueix la càrrega d’administració degut a que només cal distribuïr un únic fitxer. També comprimeix (redueix temps de baixada) WAR (Web ARchives) WARS o "Web Archive" és una especificació de Sun que permet agrupar un conjunt de classes, servlets, JSPs, documents HTML,... que formen una aplicación web en Java Permet interoperabilitat entre diferents Application servers EJB-JAR (EJB Java ARchives) Un EJB-JAR és la manera en què és distribuïts un ejb (amb les seves interfaces) EAR (Enterprise ARchives) Un EAR simplement és un WAR i diversos EJB-JAR agrupats Es genera amb el deploytool del J2EE SDK


Descargar ppt "Toni Navarrete Enginyeria del Software II – UPF 2005"

Presentaciones similares


Anuncios Google