Login
Cerca all'interno di JavaPortal
Help
Home Page Documentazione Forum Progetti Partner Pubblica!
Documentazione > Tutorial > STRIPES ///
Hide
Best Practices
EJB
Frameworks
Howto
J2EE
J2ME and Wireless
J2SE
JSP e Servlet
Java Application Server
Java IDE/Tools
Java Media
Java Security
Java Sys Admin
Java e XML
Java e SQL
OpenSource Java
Patterns
Repository
Tesi
UML
Web Services
Slide
White Paper di jws.it
project management
Eventi
Groovy

Hai una tesi in Java?
Tesine preparate
per esami?
Pubblica tutto su
JavaPortal!

Scrivi al nostro staff


Java Application Server day 2009


John Fitzgerald Kennedy
L'uomo è il computer più straordinario di tutti


Introduzione a Groovy


Rss Feed
Home Page
Articoli
News
Forum
Classi

  Visualizza Commenti (1) Aggiungi Commento    
Add to Shortcuts
 
Vota l'articolo
STRIPES ///
By Ivan De Martino
27 aprile 2009

  STRIPES ///
Program Configurazione
Program VIEW
Program ActionBean
Program Conclusioni

Lo scopo di questo articolo è mostrare i punti di forza di Stripes e, sviluppando una semplice applicazione di autenticazione, essere subito operativi con questo strumento.

Stripes è un presentation framework open source,  giunto alla versione 1.5. Sebbene siano già disponibili numerosi altri prodotti che agevolano lo sviluppo di applicazioni, Stripes merita una  particolare menzione, in quanto  si pone l'ambizioso obiettivo di semplificare uno dei  punti più critici dei framework: la  configurazione.

Perché la la configurazione è un aspetto così complesso nei framework? Perché è spesso distribuita su diversi files (il più delle volte xml),  richiede  tempi lunghi  in termini di apprendimento,  ha una sintassi articolata e complessa e rende difficile lo sviluppo in team.

Con Stripes invece è possibile partire “from scartch” in pochissimo tempo, in quanto la sua configurazione è veramente minimale. Inoltre, l'uso delle Annotation  rende questo framework  semplice ed intuitivo, senza sottovalutare il vantaggio di poterlo estendere con facilità.

Le principali caratteristiche di Stripes sono:

  • configurazione basata su Annotation;
  • convention over Configuration;
  • auto-discovery degli action beans e dei  form beans;
  • sviluppo modulare ed indipendente delle viste e dei modelli;
  • installazione e configurazione semplice e rapida;
  • facilità di estensione;
  • ricca disponibilità di taglibs;
  • supporto integrato e trasparente per il file uploading.

Il flusso tipico di Stripes può essere rappresentato come segue: 

 

Per analizzare le caratteristiche di Stripes, costruiamo una piccola applicazione (download codice di esempio). Partiremo con una welcome page che ci permetterà di accedere ad una form di autenticazione ed una form di registrazione.  La form di autenticazione verrà utilizzata per implementare una semplice validazione dei dati, mentre  gli  ActionBean  ci  mostreranno  la possibilità di poter intercettare in uno stesso ActionBean diversi eventi.

Con il nostro esempio avremo modo di:

  • verificare la  possibilità di gestire la validazione dei dati in modo semplice e rapido senza dover utilizzare configurazioni dedicate, ma solo le annotazioni;
  • utilizzare i java bean  per effettuare il binding dei dati;
  • implementare eventi diversi all'interno dello stesso ActionBean handler;
  • focalizzare l'attenzione sulle tre componenti principali di Stripes: configurazione, view, ActionBean. 

 



Configurazione top
Per essere immediatamente funzionante Stipes richiede la configurazione di uno StripesFilter e di una StripesDispatchServlet all'interno del file web.xml.

web.xml
...
    <filter>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <param-name>ActionResolver.Packages</param-name>
            <param-value>it.javaportal.stripes.action</param-value>
        </init-param>
    </filter>

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <servlet-name>DispatcherServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>    
...

Lo StripesFilter assicura che tutte le request verso Stripes siano intercettate nello stesso modo, anche le request multipart/form saranno trattate dagli ActionBean al pari i una qualsiasi request.
E' Importante notare il parametro di inizializzazione  ActionResolver.Packages.  E' utilizzato da Stripes per effettuare l'autodiscovery degli ActionBean all'interno del classpath, indica  all'interno di quali packages sono presenti i nostri ActionBean. Questo è l'unico parametro obbligatorio richiesto dallo StripesFilter.
Come altri framework, esiste un unico controller, la DispatcherServet, che  intercetta tutte le request “.htm” e le instrada verso gli appropriati ActionBean.

Un altro file richiesto da Stripes è il file StripesResources.properties. Utilizzato per effettuare il lookup dei messaggi in fase di validazione, sia per le validazioni disponibili di default all'interno del framework, sia per quelle che saranno implementate in fase di sviluppo. Il file StripesResource.properties  deve essere disponibile all'interno del classpath.
Di seguito una porzione del file StripesResources.properties:

#STRIPES VALIDATION MESSAGES
validation.required.valueNotPresent={0} is a required field
validation.minlength.valueTooShort={0} must be at least {2} characters long
validation.maxlength.valueTooLong={0} must be no more than {2} characters long
.....
......
validation.file.postBodyTooBig=Total upload size of {3} KB exceeds the maximum size of {2} KB  
# CUSTOM VALIDATION MESSAGES
custom.validation.error.valueNotValid={0} value {1} is not a possible value


L'ultimo messaggio riportato sarà utilizzato nella validazione custom all'interno del nostro ActionBean di esempio.

VIEW top
Stripes di default supporta l'utilizzo delle JSP come tecnologia standard per le views. E'  possibile  integrare con estrema facilità altre tecnologie come FreeMarker, noto componente java basato su template per la generazione di pagine html . Inoltre sono a  disposizione una serie di taglibs simili ai corrispettivi html tags per agevolare e semplificare lo sviluppo delle pagine di view.
La prima pagina che visualizziamo e la jsp di la welcome-page:




Il codice della pagina index.jsp è il seguente
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
      <title>Stripes Sample</title>
  </head>
    <body>
        <h1>Welcome to stripes sample</h1>
        <stripes:link event="login" beanclass="it.javaportal.stripes.action.HomeActionBean">
            Login
        </stripes:link><br/><br/>
        <stripes:link event="register" beanclass="it.javaportal.stripes.action.HomeActionBean">
            Register
        </stripes:link>
    </body>
</html

Attraverso le taglib, messe a disposizione da Stripes, abbiamo creato due link che effettuano una richiesta verso l' url associata all' ActionBean  it.javaportal.stripes.action.HomeActionBean, comunicando anche l'evento definito all'interno dell'attributo event.
 l'html di output sarà:
     <a href="/Home.htm?login=">Login</a>
   <a href="/Home.htm?register=">Register</a>

Il framework, in fase di runtime, converte l'attributo beanClass nell' url a cui è associato. A questo punto una domanda sorge spontanea “ma dove è definita questa  url?”  La risposta la troveremo  di seguito, in una annotation all'interno della definizione della classe che ci consentirà di associare l'url all'ActionBean. Da notare che i due link puntano alla stessa url, li differenzia un parametro che è il valore immesso nell'attributo event. Questo valore ci consentirà di invocare l'handler corretto all'interno dell'ActionBean.

La pagina di registrazione è html puro e non utilizza nulla che debba essere commentato (il codice sorgente di register.jsp è presente all'interno dell'esempio allegato).
L'ultima pagina del nostra applicazione è una form di login con due text input e due tasti di submit. I due tasti di submit  consento di generare rispettivamente l'evento  “login”  ed un altro generico evento da noi chiamato “other”. Come  nella welcome-page, per dimostrare la possibilità di avere più di un handler nell'ActionBean, abbiamo usato l'evento “other”  per reindirizzare l'utente alla form di registrazione.
Inoltre per agevolare la comprensione, il campo password è stato definito come text. 

Il codice della nostra pagina login.jsp è il seguente:
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
<%@ taglib prefix="dyna" uri="http://stripes.sourceforge.net/stripes-dynattr.tld" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>FIRTS STRIPES SAMPLE</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
      </head>
  <body>
    <div id="main">
    <stripes:errors/>
    <stripes:form beanclass="it.javaportal.stripes.action.LoginActionBean">
        <table align="center">
            <tr>
                <td>login:</td>
                <td><stripes:text name="credentials.userName"/></td>
            </tr>
            <tr>
                <td>password: </td>
                <td><dyna:text name="credentials.password" extra="extraAttr"/></td>
            </tr>
            <tr>
                <td colspan="2">
                    <stripes:submit name="submit" value="login"/>
                    <stripes:submit name="other" value="other"/>
                </td>
            </tr>
        </table>
        FAIL &egrave; un valore non valido per il campo login
    </stripes:form>
      </div>
  </body>
</html>


Stripes ha una serie di jstl che rendono intuitiva la scrittura delle view. Le jstl offrono un supporto   immediato per:
  • la gestione degli errori di validazione;
  • la corretta action da impostare nei tag form;
  • la creazione di link (vedi index.jsp);
  • la creazione dei tag html.
In breve:
il tag <stripes:error> fornisce un supporto di default per mostrare gli errori di validazione. E' possibile modificare la visualizzazione o gestire diversamente la visualizzazione degli stessi.

Il tag <stripes:form> crea una html form che sarà utilizzato per l'invio della request  all'aActionBean indicato nell'attributo beanclass.

Il tag <stripes:text...> crea un html type input. Nel  nostro esempio abbiamo due input di tipo text. Il loro valore è rispettivamente quello delle proprietà userName e password dell'oggetto Credential esposto dall'ActionBean.

Il tag <stripes:submit ...> crea un html button. Nel nostro esempio sono i due bottoni  per gli eventi “login” ed “other” definiti nell'ActionBean.

Esistono due tipologie di taglibs:
  1. le standard: non consento l'utilizzo di attributi non standard, cioè non definiti nel Tag Library Definition
  2. le Dynamic Attributes: accettano anche attributi arbitrari, non standard, per esempio le librerie Ajax.

Nella nostra applicazione, il campo di immissione password è generato utilizzando la taglib  dynattr,ed è stato aggiunto un attributo non standard al campo.

La form mostrata all'utente sarà





Nella form, i campi login e password sono obbligatori.  Il campo login genera un errore di validazione qualora contenga il valore “FAIL”.
Se tentiamo di effettuare la login senza aver immesso i dati all'interno della form, all'utente saranno notificati gli errori di validazione secondo le regole definite all'interno dell'ActionBean:
 


Viene notificato un errore anche quando i campi sono  valorizzati ma il campo login contiene il valore FAIL:




In caso di dati corretti, si  visualizza una pagina di benvenuto con il valore immesso nel campo login.



 

ActionBean top

Un ActionBean è un controller che,  a fronte di una submit, riceve la request dell'utente e ne processa i dati.
Per permettere allo StripesDispatcher di iniettare l'oggetto ActionBeanContext, ogni ActionBean deve necessariamente implementare l'interfaccia Stripes ActionBean o estendere una classe che la implementi. Questa implementazione rende possibile accedere agli oggetti HttpServletRequest, HttpServletResponse e ServletContext.

Il ciclo di vita di una request associata ad un ActionBean può essere così descritto:
  1. in base alla url richiesta si rende disponibile un ActionBean e si iniettata l'istanza di ActionBeanContext;
  2. si risolve il metodo handler che si occupa di elaborare la richiesta per quel determinato evento;
  3. si  effettua un bind dei valori dalla HttpServletRequest all'ActionBean, se prevista è eseguita la validazione dei dati;
  4. si  invoca un qualsiasi altro metodo di validazione custom;
  5. si invoca il metodo handler precedentemente risolto;
  6. si  esegue l'oggetto Resolution restituito dall'handler.


Analizziamo in dettaglio gli ActionBean.

Il primo  è l'ActionBean HomeActionBean:

@UrlBinding("/Home.htm")
public class HomeActionBean implements ActionBean {

    ActionBeanContext actionBeanContext;
    
    public void setContext(ActionBeanContext actionBeanContext) {
        this.actionBeanContext = actionBeanContext;
    }

    public ActionBeanContext getContext() {
        return this.actionBeanContext;
    }
   
    @HandlesEvent(value = "login")
    public Resolution view() {
        return new RedirectResolution("/Login.htm");
    }

    @HandlesEvent(value = "register")
    public Resolution register(){
         return new RedirectResolution("/Register.htm");
    }
}


La senconda è la  LoginActionBean:

@UrlBinding("/Login.htm")
public class LoginActionBean implements ActionBean {

  
    @ValidateNestedProperties({
            @Validate(field    = "userName",required = true,on = { "submit" }) ,
            @Validate(field    = "password",required = true,on = { "submit" })
    })
    private Credentials credentials;


    private ActionBeanContext context;

    public Credentials getCredentials() {
        return credentials;
    }

    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
    }

    public void setContext(ActionBeanContext actionBeanContext) {
        this.context = actionBeanContext;
    }

    public ActionBeanContext getContext() {
        return context;
    }

    @DefaultHandler
    @DontValidate
    public Resolution init(){
        return new ForwardResolution("WEB-INF/jsp/login.jsp");  
    }


    @HandlesEvent(value = "submit")
    public Resolution login() {
        return new ForwardResolution("WEB-INF/jsp/hello.jsp");
    }

    @ValidationMethod(on = "submit")
    public void extraValidation(ValidationErrors errors) {
        if(credentials.getUserName().equals("FAIL")){
            ValidationError error = new LocalizableError("custom.validation.error.valueNotValid",new Object[]{credentials.getUserName()});
            errors.add("credentials.userName",error);
        }
    }

    @HandlesEvent( value = "other")
    public Resolution otherHandler() {
        return new RedirectResolution("/Register.htm");
    }
}


Si può notare la presenza nel codice di esempio di diverse annotation.

L'annotazione @UrlBinding esegue un bind del path specificato, ogni qual volta  il client richiede questo specifico path l'ActionBean a cui è associato viene invocato.

L'annotazione @ValidateNestedProperties è utilizzata per la validazione di oggetti complessi. Nell'esempio riportato sono validate le proprietà userName e password dell'oggetto Credential, ma solo quando è generato l'evento submit.
Qualora l'utente immetta dati che non rispettano le regole di validazione, viene  effettuato un ridirezionamento sulla pagina sorgente ed uno o più messaggi di errore sono visualizzati. I messaggi di errore sono basati sul tipo di validazione eseguita e sul campo validato.

L'annotazione @DefaultHandler marca il metodo a cui è applicata come handler di default, qualora non sia specificato nessun evento all'interno della request o sia specificato un evento che non è possibile associare a nessun altro handler.

L'annotazione @HandlesEvent marca il metodo a cui è applicata come handler dell'evento specificato.  Ad esempio nella LoginActionBean @HandlesEvent( value = "other") indica che quando viene generato l'evento “other” il metodo otherHandler si occupa di gestire la richiesta.

L'annotazione @ValidationMethod determina l'esecuzione del metodo a cui è applicata ed è utilizzata per definire validazioni custom.
L' esecuzione avverrà prima di eseguire l'handling dell'evento dichiarato nell'attributo on (on = "submit").

Analizzando  l'esecuzione dell'evento sumbit, nella nostra form di login possiamo sintetizzare i seguenti step:
  • l'utente effettua la submit dei dati;
  • Il framework imposta i valori ed effettua la validazione definita nella annotazione ValidateNestedProperties;
  • in caso di errori di validazione viene ridirezionata la pagina sorgente;
  • in caso di nessun errore, viene richiesta l'esecuzione dell'handler associato all'evento specificato, nel nostro caso all'evento sumbit è associato il metodo  login();
  • poiché l'evento submit è marcato come da validare nell'annotation ValidationMethod, viene eseguito il metodo  extraValidation;
  • in caso di errori di validazione viene ridirezionata la pagina sorgente;
  • in caso di nessun errore viene eseguito il metodo handler.

L'annotazione @DontValidate dichiara che nessuna validazione deve essere eseguita quando viene generato quello specifico evento, o meglio quando viene invocato il metodo associato a quello specifico evento. 


Conclusioni top
Lontano dall'essere una completa panoramica di Stripes, questo articolo fornisce le basi per iniziare a lavorare con  questo interessante framework. Aiutandoci con il codice di esempio della nostra applicazione di autenticazione, abbiamo messo  in evidenza la semplicità e immediatezza della  configurazione.
Oltre alla configurazione, abbiamo analizzato anche la validazione. Infatti in Stripes, la validazione è molto veloce, ricca di controlli di default già disponibili ed è facilmente customizzabile.

Ritengo che una caratteristica importante di Stripes è la comodità di poter avere in un unico ActionBean diversi handler, senza dover ricorrere a workarounds quali: campi hidden, specifici parametri della request o if/else all'interno delle Action.  Questa caratteristica di Stripes permette di implementare tutte le operazioni di C.R.U.D. associate ad un'entità in un unico ActionBean.


Sul sito ufficiale di Stripes è possibile consultare  un wiki che fornisce un'esaustiva panoramica di tutte le funzionalità di questo giovane e promettente framework. 

 Attachments List
Generic Documentstripes_sample.zip
Username:
Password:
To sign up for an account, click register... Register
Hide





Powered By



Campagna Anti-IF


Skin


PARTNER
Zio Budda
HostingJava


LICENZA



Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons

Sitemap  © 2002-2004 Copyright Information. Privacy . Today is domenica 1 agosto 2010