SWF: Model Data Validation
Dopo aver visto come SWF realizza il mapping tra i dati di un modello e i campi di un form, vediamo ora come creare il meccanismo di validazione che consente di verificare il valore di ciascun campo inserito all’interno di un form. In questo articolo abbiamo visto come viene realizzata il binding dei dati e teniamolo come punto di partenza per iniziare a vedere il meccanismo della validazione.
Riprendiamo il codice sorgente del file di configurazione del flow e la pagina HTML all’interno della quale è presente il form:
<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> <var name="flight" class="it.devme.flight.Flight" /> <view-state id="start" view="flight/insertFlightInfo" model="flight"> <transition on="next" to="confirm" /> </view-state> <view-state id="confirm" view="flight/showFlightInfo" /> </flow>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>DevMe - SWF Flight info test - </title>
</head>
<body>
<h1>Flight information </h1>
<p>Inserisci le informazioni sul volo:</p>
<form:form id="flightDetails" modelAttribute="flight">
<table>
<tr>
<td>Numero del volo: </td>
<td><form:input path="number"/></td>
</tr>
<tr>
<td>Ora di partenza: </td>
<td><form:input path="time"/></td>
</tr>
<tr>
<td>Gate: </td>
<td><form:input path="gate"/></td>
</tr>
<tr>
<td>Volo in ritardo: </td>
<td><form:radiobutton path="isDelayed" value="false" />
<form:radiobutton path="isDelayed" value="true" /></td>
</tr>
<tr>
<td><input type="submit" name="_eventId" value="next"></td>
</tr>
</table>
</form:form>
</body>
</html>Bene. Come già ampiamente discusso, il flow definito dal file XML di sopra è molto semplice. Abbiamo una sola transizione da uno stato all’altro, ovvero si naviga da una pagina ad un altra pagina. Supponiamo ora, di voler validare i dati del form della pagina di partenza, e spostarsi nella pagina di arrivo, solo se non esistono errori di validazione secondo il nostro personale schema di validazione. Il nostro schema, prevede per semplicità che almeno uno dei tre campi presenti nel form sia indicato, e che se indicato il numero del volo questi dovrà essere un valore numero e eventuali caratteri alfabetici verranno rigettati.
Iniziamo con la modifica del file XML di definizione del flow:
<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> <var name="flight" class="it.devme.flight.Flight" /> <view-state id="start" view="flight/insertFlightInfo" model="flight"> <transition on="next" to="confirm" > <action method="bindAndValidate" bean="flightAction" /> </transition> </view-state> <view-state id="confirm" view="flight/showFlightInfo" /> </flow>
Il metodo bindAndValidate in sostanza richiama la nostra classe validator, la quale effettua i controlli che andremo a definire. Da notare che il riferimento nel tag action, punta ad un metodo all’interno della nostra classe Action che in realtà non esiste, ma che viene ereditato dalla superclasse FormAction. Definendo all’interno del file XML di definizione del bean il riferimento alla nostra classe Validatore, autormaticamente verrà richiamata all’invocazione del metodo bindAndValidate. Il codice della classe che si occupa di effettuare la validazione è il seguente:
package it.devme.flight; public class FlightValidator implements Validator { public boolean supports(Class clazz) { return clazz.equals(Flight.class); } public void validate(Object target, Errors errors) { Flight flight = (Flight) target; if (flight.getNumber()==0 && flight.getTime()==null && flight.getGate.equals("")) { errors.rejectValue("gate", "Attenzione, è necessario specificare almeno 1 tra: numero del volo, ora di partenza, Gate"); } if (errors.getErrorCount()==0) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "gate", "Il campo gate non può essere vuoto."); } } }
Vediamo cosa è stato fatto. Intanto osserviamo che FlightValidator implementa la classe Validator, quindi definisce alcuni metodi essenziali che sono supports e validate. Il primo assicura il supporto al Bean indicato al suo interno. Il secondo implmenta la logica di validazione. Nel nostro caso vogliamo che almeno uno dei tre campi venga inserito, e che il campo Gate sia diverso da vuoto. Il primo controllo verifica la prima delle nostre condizioni; il secondo if, verifica prima che non ci siano stati errori in precedenza, e in caso positivo effettua il controllo di validazione sul campo Gate.
Vediamo ora come modifichiamo il file HTML per presentare il messaggio di errore:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>DevMe - SWF Flight info test - </title>
</head>
<body>
<h1>Flight information </h1>
<p>Inserisci le informazioni sul volo:</p>
<form:form id="flightDetails" modelAttribute="flight">
<table>
<tr>
<td>Numero del volo: </td>
<td><form:input path="number"/></td>
</tr>
<tr>
<td>Ora di partenza: </td>
<td><form:input path="time"/></td>
</tr>
<tr>
<td>Gate: </td>
<td><form:input path="gate"/></td>
<td><form:errors path="gate"/></td>
</tr>
<tr>
<td>Volo in ritardo: </td>
<td><form:radiobutton path="isDelayed" value="false" />
<form:radiobutton path="isDelayed" value="true" /></td>
</tr>
<tr>
<td><input type="submit" name="_eventId" value="next"></td>
</tr>
</table>
</form:form>
</body>
</html>Per semplicità il nostro messaggio di errore comparirà sempre nello stesso posto, ovvero sotto il campo Gate. Così nel primo caso di errore, darà contezza del fatto che almeno uno dei campi di precedenti deve essere indicato, mentre nel secondo caso, sarà indicativo del campo stesso. Come vedete, l’aggiunta del tag <form:errors/> fa in modo di collegare eventuali codici di errori con il campo presentato in pagina.
Alla prossima. Stay tuned!
Tempo fa in questo
Rieccoci qui per continuare il discorso iniziato nel post precedente su SFW, il framework per la creazione di applicazioni web. Dopo aver definito gli elementi facenti parte della definizione di un flusso (flow) vediamo come è possibile definirlo, attraverso la sua specifica XML. Come detto in precedenza, il flow ha inizio grazie al flow executor un componente interno di SWF. L’executor da inizio al flow a partire dallo stato configurato come attributo nel tag root della definizione del flow:
In questo articolo voglio far vedere come nascondere l’href di un immagine in una pagine JSP, pur visualizzando l’immagine come elemento HTML in modo standard. 