MokaByte 87 - Luglio/Agosto 2004 
Sviluppare applicazioni web J2EE
con Jakarta Struts
VII parte: Validator
di
Alfredo Larotonda

Jakarta Struts è il framework più diffuso per lo sviluppo di applicazioni web J2EE. In questo articolo descriviamo il Validator, un framework per la validazione dei dati.

Introduzione
Abbiamo già esaminato nei precdenti articoli gli strumenti messi a disposizione da Struts per effettuare la validazione dei dati immessi in un form HTML. Il metodo validate() della classe org.apache.struts.action. ActionForm costituisce il punto nel quale vengono effettuati i controlli lato server sui dati immessi. Abbiamo visto come il framework provveda a rivisualizzare la pagina con i dati immessi in precedenza affinché si possano correggere gli errori rilevati.
Questo meccanismo che pure allevia di molto il compito dello sviluppatore presenta alcuni inconvenienti. Il codice di validazione è spesso duplicato nell'applicazione e un cambiamento delle regole di validazione implica una modifica ai sorgenti. Per ovviare a questi problemi è stato sviluppato il Validator, un componente del Jakarta Common Project che può essere usato come un add-in di Struts.

 

Il Validator
Il Validator è un framework che fornisce gli strumenti per effettuare in modo automatico e dichiarativo i controlli formali sui campi digitati in un form HTML.
Usando il Validator non è necessario scrivere alcun codice di validazione nel metodo validate() degli ActionForm, ma è il Validator stesso che fornisce questa funzione purchè i form bean dell'applicazione estendano uno degli ActionForm del Validator stesso. .
Il Validator è costiuito da un insieme di classi predisposte per eseguire tutti i più comuni controlli di validazione in genere usati nelle applicazioni, ma.esiste anche la possibilità di creare routine di validazione non fornite dal Validator. Il Validator inoltre supporta sia la validazione server-side che quella client-side mediante opportune funzioni JavaScript, cosa non fornita dal meccanismo standard degli ActionForm di Struts.
La configurazione delle routine di validazione da applicare ad un campo di un form è fatta mediante un file di configurazione XML, quindi esternamente all'applicazione ed è facilmente modificabile al mutare delle esigenze applicative. Nel fifle validator-rules.xml vengono dichiarate tutte le routine di validazione disponibili, i loro nomi logici e il codice JavScript corrispondente a ciascuna routine di validazione per l'esecuzione dei controlli client-side.
Nel file validation.xml si specifica come queste routine vengano applicate ai vari campi di input dei form dell'applicazione, ai quali si fa riferimento mediante i nomi dei form beans dichiarati nello struts-config.xml.
Utilizzare il Validator con Struts significa eseguire i seguenti step:

  1. Abilitare il Validator plug-in
  2. Configurare i due file XML appena citati, validator-rules.xml e validation.xml
  3. Creare form bean che estendano gli ActionForm del Validator.

Configurare il Validator per l'uso con Struts
Il Validator viene configurato come un plug-in di Struts. Per abiliare il Validator bisogna aggiungere nello struts-config.xml le seguenti righe;

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>

In questo modo Struts all'avvio dell'applicazione carica e inizializza il Validator; si può notare come vengano definiti i percorsi dei due file XML di configurazione del Validator.
Il validator-rules.xml dichiara le routine di validazione messe a disposizione dal Validator. Esistono una serie di routine fornite dalla versione standard del Validator che coprono la gran parte delle comuni esigenze per ciò che riguarda i controlli formali da eseguire sui campi di input di un form. Il file in genere non va quindi modificato a meno che non si vogliano definire delle proprie routine.
Di seguito è riportato un esempio di una sezione del file validator-rules.xml riguardante la definizione della routine di validazione corrispondente al criterio 'required', ovvero di obbligatorietà di un campo del form. Come si può vedere ad ogni regola è associato un nome logico, required in questo caso, è definita la classe Java che effettua la validazione e il metodo che viene mandato in esecuzione con i suoi parametri.
Il nome logico della routine sarà usato come riferimento nel file validation.xml che vedremo.
Inoltre nel tag <javascript> è racchiusa la routine JavaScript per la validazione client-side.


<form-validation>
<global>
<validator name="required"
classname="org.apache.struts.validator.FieldChecks"
method="validateRequired"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
msg="errors.required">
<javascript>
<![CDATA[
function validateRequired(form) {
var isValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
oRequired = new required();
for (x in oRequired) {
var field = form[oRequired[x][0]];

if (field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'file' ||
field.type == 'select-one' ||
field.type == 'radio' ||
field.type == 'password') {

var value = '';

// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
if (si >= 0) {
value = field.options[si].value;
}
} else {
value = field.value;
}

if (trim(value).length == 0) { {
if (i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid = false;
}
}
}

if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}

return isValid;
}

// Trim whitespace from left and right sides of s.
function trim(s) {
return s.replace( /^\s*/, "" ).replace( /\s*$/, "" );
}

]]>
</javascript>
</validator>
</global>
</form-validation>


Come già accennato per utilizzare il Validator i form bean dell'applicazione non devono estendere la classe ActionForm standard di Struts ma la classe org.apache.struts.validator.ValidatorForm che fornisce l'implementazione del metodo validate(). In questo caso non è più necessario scrivere il codice di validazione perché è il Validator che lo fa per noi. La configurazione dei form bean all'interno dello struts-config.xml è identica a quella fatta in precedenza utilizzando la classe ActionForm standard di Struts.
Un esempio di form bean e della sua dichiarazione è il seguente:

import org.apache.struts.validator.ValidatorForm;

public class LogonForm extends ValidatorForm {
private String username;
private String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

<form-beans>
<form-bean name="logonForm"
type="it.prove.LogonForm"/>
</form-beans>

La classe è simile ad un ActionForm di Struts tranne l'estensione di una classe diversa. Inoltre in questo caso non bisogna implementare i metodi reset() e validate() che sono invece implementati dalla classe ValidatorForm
Il nome dato al form bean nello struts-config.xml è usato nel validation.xml per far riferimento al form in questione. Il validation.xml viene usato per dichiarare i controlli che verranno effettuati sui campi di input di un form dell'applicazione. In relazione al form definito in precedenza il validation.xml potrebbe essere fatto come segue:


<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
DTD Commons Validator Rules
Configuration 1.0//EN"
"http://jakarta.apache.org/
commons/dtds/validator_1_0.dtd">

<form-validation>
<formset>
<form name="logonForm">
<field property="username"
depends="required">
<arg0 key="label.username"/>
</field>
<field property="password"
depends="required">
<arg0 key="label.password"/>
</field>
</form>
</formset>
</form-validation>


Per ogni form dell'applicazione va definito un elemento <form></form> in cui l'attributo name corrisponde al nome del form bean dichiarato nello struts-config.xml. Gli elementi <field></field> dichiarano i controlli da eseguire per i campi del form. Nell'esempio si dichiara che i campi username e password sono obbligatori mediante l'attributo depends.
Per i messaggi di errore associati a ciascuna routine di validazione il Validator utilizza il file ApplicationResource.properties di Struts. In questo file vengono definiti i messaggi di errore associati a ciascun criterio di validazione definito nel validator-rules.xml :

errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0. errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.

I messaggi hanno dei segnaposto per renderne variabile il contenuto a seconda del campo controllato. Il valore che il Validator sostituisce al segnaposto è fornito nel validation.xml nella sezione dedicata al form specifico. Nel caso del required dell'esempio precedente verrà inserita la descrizione corrispondente alla key="label.password" fornita nella sezione <arg0></arg0> del field corrispondente.

 

Validazione client-side
Il Validator foirnisce anche il supporto alla validazione client-side dei form dell'applicazione. Le funzioni JavaSctipt associate ai diversi criteri di validazione sono definite nel file validator-rules.xml come già visto. Per abilitare la validazione client-side è sufficiente inserire nelle pagine JSP dell'applicazione il seguente tag:
<html:javascript formName="logonForm"/>

Il validator genererà dinamicamente le routine di validazione per il form specificato nell'attributo formName del tag <html:javascript>.
Nel nostro caso genererà la funzione validateLogonForm() che effettuerà la validazione del form purchè la si colleghi al submit dello stesso come segue:

<html:form action="logonAction" onsubmit="return validateLogonForm (this)">

Chiaramente il submit del form non avverrà se i controlli sui campi non hanno successo.
La validazione JavaScript consente di evitare i round-trip con il server dovuti a successivi submit del form conseguenti ad errori di validazione sui campi digitati nel caso in cui i controlli vengano eseguiti esclusivamente lato server. In ogni caso comunque il Validator esegue anche i controlli lato-server una volta che il submit del form viene effettuato. Ciò garantisce che i controlli formali vengano effettuati anche nel caso in cui i controlli JavaScript lato client vengano disattivati, cosa non da poco visto che in genere nelle applicazioni web che eseguono i controlli formali sui campi lato client , le validazioni non vengono eseguite anche lato server come in realtà dovrebbe essere fatto. Ciò conferisce una maggiore robustezza ed affidabilità all'applicazione ed è uno dei principali benefici dell'uso del Validaor.

 

Conclusioni
In questo articolo abbiamo fatto una panomarica generale sul Validator. Abbiamo tralasciato alcuni aspetti interessanti, come ad esempio l'uso dei form dinamici, ma si è cercato di evidenziare gli aspetti fondamentali del Validator ed i benefici di un suo utilizzo. Utilizzare il Validator nella scrittura di una applicazione web J2EE è senz'altro a mio parere un'ottima scelta poiché consente un notevole risparmio di ripetitivo codice di validazione ed una standardizzazione degli algoritmi di controllo. Inoltre la possibilità di configurare esternamente al codice i tipi di controlli da effettuare sui campi dei form conferisce grande flessibilità e manutenibilità all'applicazione stessa.

 

Bibliografia
[1] Chuck Cavaness - "Programming Jakarta Struts", O'Reilly, 2003
[2] James Goodwill, Richard Hightower - "Professional Jakarta Struts" - Wrox 2004
[3] Richard Hightower - "Jakarta Struts Live" - SourceBeat 2004


Alfredo Larotonda, laureato in Ingegneria Elettronica, lavora da diversi anni nel settore IT. Dal 1999 si occupa di Java ed in particolare dello sviluppo di applicazioni web J2EE. Dopo diverse esperienze di disegno e sviluppo ora si occupa in particolare di aspetti architetturali per progetti rivolti al mercato finanziario ed industriale. E' Web Component Developer e Business Component Developer certificato SUN per la piattaforma J2EE e Programmer per la piattaforma Java.


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