Contesto
Il
client richiede all’applicazione una lista
di elementi il cui numero è sconosciuto e potrebbe
essere molto elevato.
A cosa serve
L’utilizzo dei metodi ejbFind non è consigliato
per operazioni di ricerca laddove il numero di elementi
non è noto a priori e potenzialmente elevato.
L’intento del pattern è di fornire un
meccanismo piu’ efficiente per potere iterare
una lista di elementi in un’architettura
distribuita. Il Value List Handler(VLH) permette
di controllare
la ricerca, memorizzare il risultato e restituire
i dati necessari a soddisfare la richiesta del
client.
Il pattern prevede due strategie [CJP]:
- Java
Object Strategy: il VLH è implementato
con una classe Java
- Stateful
Session Bean Stategy: il VLH è una
proprietà di un EJB Session Stateful
(lo stato conversazionale)
Spiegazione del funzionamento
Il VLH utilizza direttamente un DAO per effettuare
la query e riempire la lista adibita a contenerne
il risultato.
Dopo avere “popolato” la lista,
il VLH possiede un iteratore per scorrere
il risultato
(pattern
Iterator [GOF]) e restituisce i dati ad
hoc per soddisfare la richiesta del client.
Di seguito si riporta il caso in cui si richiede
una lista di prodotti senza utilizzare il pattern
VLH.
La pagina JSP attiva il ListRequestHandler
che invoca il metodo getProducts() dell’EJB ListerBean mediante
l’oggetto ServicesBusinessDelegate[BD] e memorizza
il risultato nell’opportuno view bean (ListProductView)
salvandolo nell’HTTP request: public class ListRequestHandler extends BaseRequestHandler
{
public void execute(..) {
try{
. . . .
ServicesBusinessDelegate proxy=
FactoryBusinessDelegate.getServicesBusinessDelegate(...);
ListProductModel res = proxy.getProducts(queryCriteria);
ListProductView view = new ListProductView(res);
request.setAttribute("prodotti", view);
this.pageName = "/jsp/ListaCD.jsp";
. . .
La pagina ListaCD.jsp visulizza il risultato della
ricerca effettuata:
<jsp:useBean id="prodotti" class="it.mokabyte.pattern.view.ListProductView" scope="request" />
< table>
< %
for(int i=0; i<prodotti.size(); ++i){
ProductView prod = prodotti.elementAt(i);
out.println("<tr>");
out.println("<th>"+prod.getBand()+"</th>");
out.println("<th>"+prod.getTitle()+"</th>");
. . .
}
. . .
%>
< /table>
L’EJB Session Stateless ListerBean si limita
a utilizzare il DAO per effettuare la query e a restituire
l’intero risultato:
public class ListerBean implements SessionBean {
public List getProducts(Criteria queryCriteria) throws BusinessException{
. . .
ProductDao dao = DaoFactory.getProductDAO();
return dao.readProducts(queryCriteria);
In questo caso l’intero risultato della ricerca
transita dal business tier al presentation tier. Nel
caso l’utente decida di “scartare” i
dati ricevuti o di effettuare una nuova query, le risorse
di tutti i tier sono state coinvolte.
Figura
1 -
Caso in cui non si utilizza il pattern ValueListHandler
Il
pattern VLH fornisce un meccanismo piu’ efficiente
per gestire le ricerche migliorando il trasferimento
dei dati dal business tier al presentation tier.
Il VLH effettua la ricerca e memorizza il risultato
in una collezione di oggetti(operazione di pre-fetch).
Le richieste del client vengono soddisfatte fornendo
un sottoinsieme del risultato al Presentation tier.
Di fatto si mette a disposizione del Presentation tier
un iteratore che agisce su di un lista che risiede
sul business tier.
Se il client, una volta ricevuta la prima “paginata” di
dati, non è interessato ai dati successivi,
si è evitato l’overhead del trasferimento
dell’intero risultato lungo la rete.
Figura 2 - Un esempio d utilizzo del pattern ValueListHandler
Si riportano i diagrammi UML relativi alla struttura
del pattern:
Figura
3 - Pattern ValueListHandler: Class Diagram
Figura 4 - Pattern ValueListHandler: Sequence Diagram
Presentazione del codice Java
Viene ora presentato un esempio di implementazione
del pattern VLH - Stateful Session Bean Stategy.
Figura 5 - Pattern ValueListHandler:
Class Diagram dell’ esempio
di implementazione
L’EJB Stateful PagerBean ha al suo interno una
proprietà di classe ValueListHandler
public class PagerBean implements SessionBean {
private ValueListHandler valueListHandler = null;
Il client (ListPagedRequestHandler) invoca, mediante
il PagerBusinessDelegate
public class ListPagedRequestHandler extends BaseRequestHandler
{
public void execute(…) {
PagerBusinessDelegate proxy =FactoryBusinessDelegate.getPagerBusinessDelegate(.
. . , queryCriteria);
i metodi del PagerBean per scorrere la lista in avanti
if(action.equals("FORWARD")){
Object obj = proxy.getNextElements(numOfPageItems);
page=(PageOM)obj;
}
e i metodi per scorrere la lista indietro
else
if(action.equals("BACK")){
Object obj = proxy.getPreviousElement(numOfPageItems);
page=(PageOM)obj;
}
La
classe PageOM è il Value Object della “pagina” (la
sottolista del risultato) dei dati da restituire al
client
public class PageOM implements Serializable {
List objects = null;
boolean hasNext;
boolean hasPrevious;
. . . . .
public ProductOM elementAt(int index) {return (ProductOM)objects.get(index);}
public List getList() {return objects;}
public boolean getHasPrevious(){return this.hasPrevious;}
public boolean getHasNext(){ return this.hasNext; }
. . . . .
}
Ottenuto
il risultato, il ListPagedRequestHandler crea l’opportuno view bean e indica la pagina
JSP che visualizzerà l’insieme dei dati
ricevuti
PageView pv = new PageView(page);
request.setAttribute("prodottiPaginati",
pv);
this.pageName = "/jsp/listaCDPaginati.jsp";
L’EJB PagerBean agisce da Session Facade per
la sua proprietà di classe ValueListHanlder.
Tale proprietà viene inizializzata in fase di
creazione dell’EJB.
public void ejbCreate(Criteria cri)throws CreateException
{
. . . .
this.valueListHandler = new ProductListHandler(this.criteria);
. . . .
}
Il costruttore del ProductListHandler utilizza il
ProductDao per riempire la lista del ValueListHandler
invocando il metodo ValueListHandler.setList()
public class ProductListHandler extends ValueListHandler{
/** Costruttore: legge il catalogo dei CD musicali secondo i criteri specificati
*/
public ProductListHandler(Criteria queryCriteria) throws IteratorException
{
try{
ProductDao dao = DaoFactory.getProductDAO();
List result = dao.readProducts(queryCriteria);
this.setList(result);
. . .
La
classe ValueListHandler ha al suo interno la collezione
degli elementi della ricerca e l’iteratore
che permette lo scorrimento della collezione stessa.
public class ValueListHandler implements ValueListIterator,
java.io.Serializable{
protected List list;
private ListIterator listIterator;
protected void setList(List list) throws IteratorException { this.list=list;
}
. . . . .
I metodi esposti permettono lo scorrimento della lista:
/** Restituisce una sotto lista dei successivi elementi
*/
public List getNextElements(int count) throws IteratorException {
LinkedList linkedList = new LinkedList();
if(this.listIterator != null) {
while(this.listIterator.hasNext() && (i<count)) {
obj = listIterator.next();
linkedList.add(obj);
}
. . .
return linkedList;
}
/** Restituisce una sotto lista dei precedenti elementi
*/
public List getPreviousElement(int count) throws IteratorException {
LinkedList linkedList = new LinkedList();
if(this.listIterator != null) {
while(this.listIterator.hasPrevious() && (i<count)) {
obj = listIterator.previous();
linkedList.add(obj);
}
. . .
return linkedList;
}
Un
caso d’uso
Il
caso d’uso presentato permette di isolare
il Presentation dai dettagli di ricerca, accesso e
scorrimento della lista dei dati. A
seconda delle esigenze applicativa la tecnica proposta
dal
VLH di pre-fetch del risultato e successiva “risposta
paginata” potrebbe risultare poco efficiente
in termini di tempo e risorse.
Esistono strategie alternative (ad esempio la ri-esecuzione
della query ogni qualvolta il client necessita nuovi
sottinsiemi del risultato della ricerca) e altre “estensioni” del
pattern VLH.
Ad esempio il pattern Data List Handler [DLH] indirizza
il problema dell’efficienza in modo specifico
per l’accesso a DBMS sfruttando gli scrollable
ResultSet JDBC 2.0.
Allegati
I sorgenti sono disponibili qui
Bibliografia
[CJP]Alur,Crupi,Malks: Core J2EE Patterns - Best Practices
and Design Strategies
[DP]Floyd Marinescu: EJB Design Patterns – Advanced
Patterns, Processes and idioms
[MEJB]Ed Roman, Scott Ambler, Tyler Jewell: Mastering
Enterprise JavaBeans
[SUN1]Sun Java Center J2EE Patterns:
http://developer.java.sun.com/developer/restricted/patterns/J2EEPatternsAtAGlance.html
[SUN2]Sun blueprints-Design Patterns Catalog:
http://java.sun.com/blueprints/patterns/j2ee_patterns/catalog.html
[GOF]Gamma,Helm,Johnson,Vlissides: Design Patterns-Elements of Reusable Object-Oriented
Software
[DLH] Claudio Fratarcangeli: Data List Handler pattern – TheServerSide.com
Giugno 12 2002
Riferimenti
[DAO] S.Rossini, L. Dozio Data Access Object Mokabyte
N.62-Aprile 2002
[FCT] S.Rossini, L. Dozio DAO Factory Mokabyte N.63-Maggio
2002
[FAC] S.Rossini, L. Dozio SessionFacade Mokabyte N.64-Giugno
2002
[BD] S.Rossini, L. Dozio Business Delegate Mokabyte
N.65-Luglio 2002
[SL] S.Rossini, L. Dozio Service Locator Mokabyte N.67-Ottobre
2002
[VO] S.Rossini, L. Dozio Value Object Mokabyte N.69-Dicembre
2002
[FC] S.Rossini, L. Dozio Front Controller Mokabyte
N.70-Gennaio 2003
[MVC] S.Rossini, L. Dozio Model-View-Conterol Mokabyte
N.70-Gennaio 2003
|