MokaByte 71- Febbraio 2003 
Il pattern Value List Handler
di
Stefano Rossini

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

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it