martedì 20 aprile 2010

Alias e Validazione in Struts2


Continuo con la mia serie di post su Struts2 ed oggi voglio parlarvi degli "Alias" e della "Validazione" dei campi di un form.

Gli Alias Name in Struts2 non sono altro che il nome che diamo ad una determinata action quando la mappiamo.


Ricordate il mappaggio della ConcatenaAction:
<action name="concatena" class="concatenaAction">
<result name="success" type="tiles">concatena</result>
</action>

<action name="concatena_submit" method="submit" class="concatenaAction">
<result name="success" type="tiles">concatena</result>
</action>

avevamo mappato quest'ultima con due alias "concatena" e "concatena_submit" in modo da richiamare i metodi execute e submit..

Ma perchè mapparla per ogni metodo e quindi intervenire sempre sullo struts.xml? Un pò scocciante e brutto vero?
La soluzione sta proprio nello sfruttare gli alias.

Struts2 ci viene incontro con l'uso delle wildcard che sostituisce con quello che trova nelle url di richiesta. Facciamo un esempio così capite meglio.

Aprite il vosto progetto e quindi lo struts.xml al posto delle action sopra definite mettete solo questa:

<action name="concatena_*" method="{1}" class="concatenaAction">
<result name="success" type="tiles">concatena</result>.
</action>

ora fate una prova e vedrete che funziona.

Vediamo cosa fa struts. Abbiamo due casi di invocazione della action:

  1. Alla richiesta dell'url /struts2tutorial/concatena.action ossia l'esecuzione del metodo 'execute'
  2. Alla richiesta dell'url /struts2tutorial/concatena_submit.action ossia l'esecuzione del metodo 'submit'

Nel primo caso in realtà siamo solo fortunati poichè non ha usato le wildcard ma ha solo usato il primo mapping che inizia con 'concatena'.

Nel secondo caso struts ha usato la wildcard.Abbiamo detto nel mappaggio di struts che tutto ciò che comincia con "concatena_" e seguito da un qualcosa "*" deve eseguirla la concatenaAction. Deve poi pigliare il primo "{1}" qualcosa e mettorlo al posto dell'attributo method. Ho detto primo perchè potevamo avere + di un qualcosa. Ad esempio:
se mappavamo concatena_*_* e ci arrivava l'url concatena_submit_pippo avevamo che {1} corrisponde a "submit" e {2} a "pippo". Flessibile vero immaginate le utilità ad esempio per le breadcrumb di navigazione. Questo significa anche che possiamo mettere tt i metodi di una funzionalità in una sola classe action.

Comunque facciamo le cose per bene dato che il metodo execute funziona per puro caso. Possiamo sovrascrivere o utilizare il metodo "input" che ereditiamo dalla superclasse ActionSupport in modo da avere un metodo iniziale, di ingresso, alla funzione della action magari per impostare dei dati preparatori (nel mio caso dei messaggi) il quale è utile anche nella validazione come spiegherò + avanti. Quindi nello struts.xml mettiamo:

<action name="concatena_*" method="{1}" class="concatenaAction">
<result name="input" type="tiles">concatena</result>
<result name="submit" type="tiles">concatena</result>
</action>

e la classe ConcatenaAction diventa:

/**
*
*/
package com.blogspot.piergiuseppe82.struts2intro.action;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.blogspot.piergiuseppe82.struts2intro.bl.ConcatenaBl;
import com.opensymphony.xwork2.ActionSupport;

/**
* @author placava
*
*/
@SuppressWarnings("serial")
@Component("concatenaAction")
@Scope("request")
public class ConcatenaAction extends ActionSupport {
private static final String SUBMIT = "submit";
@Autowired
private ConcatenaBl concatenaBl;
private String primaParola;
private String secondaParola;
private String risultato;

public String getRisultato() {
return risultato;
}

public void setRisultato(String risultato) {
this.risultato = risultato;
}
@Override
public String input() throws Exception {
addActionMessage("Inserisci due parole e io le concateno");
return super.input();
}

public String submit() throws Exception {
risultato = concatenaBl.concatena(primaParola, secondaParola);
addActionMessage("Risultato eseguito con successo. Prova ancora.");
return SUBMIT;
}

public String getPrimaParola() {
return primaParola;
}

public void setPrimaParola(String primaParola) {
this.primaParola = primaParola;
}

public String getSecondaParola() {
return secondaParola;
}

public void setSecondaParola(String secondaParola) {
this.secondaParola = secondaParola;
}

public ConcatenaBl getConcatenaBl() {
return concatenaBl;
}

public void setConcatenaBl(ConcatenaBl concatenaBl) {
this.concatenaBl = concatenaBl;
}
}

Potete pure obiettare il fatto che sia submit che input puntano alla stesso results di tipo tiles. Avete ragione! Ma ho detto è meglio fare le cose per bene poichè se dovessimo far puntare un result da un'altra parte dovremmo andare a riscrivere il codice della ConcatenaAction invece così dobbiamo solo cambiare una stringa nello struts.xml e del quale si ha una visione + completa dell'applicativo. Da notare, inoltre, che io per convenzione uso sempre come result il nome del metodo in modo da sapere cosa è stato eseguito.


Ora parliamo della validazione.

La validazione in struts2 è devvero semplice, molto flessibile (grazie a OGNL) ed ovviamente è anche semplice creare dei validator custom.
Struts2 per la validazione usa un interceptor (sii ok ne parlo al prossimo post) il quale viene eseguito prima di un qualsiasi metodo di una action e richiama un xml (che vedremo come deve essere chiamato e fatto) che sta nello stesso package della action. Se l'xml è presente e i campi postati rispettano le regole di validazione allora struts esegue il metodo richiesto altrimenti va ad aggiungere degli errori di campo alla action (fieldErrors lo vedrete meglio in quello custom). Se la action contiene dei fieldErrors (ricordatevi questa definizione) per defualt struts2 ritorna il result name 'input'. Quindi il result input deve essere definito.
Se l'xml non è presente non valida e chiama il metodo richiesto. L'unico metodo che skippa (sempre per default) è il metodo input (ma se ne possono aggiungere, sempre lavorando sulla configurazione dell'interceptor :D) per questo vi dicevo che era utile, di solito in ingresso ad una funzionalità non dobbiamo validare nulla. Ci sono altri modi per skippare una validazione su un metodo ma ne parlo + avanti nel post.

L'xml che contiene le regole di validazione, come dicevo, deve stare nel package della action ed avere come nome il nome della classe action se guito da -validation.xml. Quindi:

<NomeDellaClasse-validation.xml>

nel nostro caso andiamo a mettere quindi nel package 'com.blogspot.piergiuseppe82.struts2intro.action' il file 'ConcatenaAction-validation.xml' con il seguente contenuto:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="primaParola">
<field-validator type="requiredstring" short-circuit="true">
<message><![CDATA[Devi inserire la Prima Parola.]]> </message>
</field-validator>
</field>
<field name="secondaParola">
<field-validator type="requiredstring" short-circuit="true">
<message> <![CDATA[Devi inserire la Seconda Parola.]]> </message>
</field-validator>
</field>
</validators>

L'xml è molto semlice come root abbiamo il tag <validators> all'interno dibbiamo definire per ogni campo o attributo della classe (forse è meglio) che vogliamo validare un un tag

<field name="nomeAttributo">

</field>

dove nel name ci va il nome dell'attributo della classe legata all'xml.

Per ogni <field> ci possono essere uno o più <field-validator> (come vedremo + avanti). Nel nostro caso solo uno per campo e di uguale tipo "requiredstring" un tipo standard di struts che non fa altro che verificare se un campo è nullo o stringa vuota. short-circuit (nel nostro caso è superfluo ma sapete com'è siamo nell'era del ctrl+c ctrl+v) se abilitato serve a non far eseguire altri validator, per lo stesso attributo, se quello dove definito fallisce la validazione.
Ogni <field-validator> può contenere un <message> (o altro come vedremo) e al suo interno ci sta il messaggio da visualizzare nella jsp in caso di errore.

Deployate e testate la funzione di concatenamento lasciando i campi vuoti, vedrete apparire sopra le caselle i messaggi che avete definito nell'xml.

Ecco il mio risultato:

Ah già da me li vedete in rosso e a lato nell'area messaggi.. Bè ho cambiato il css e la baseFrame.jsp.

Ecco il mio intro.css:

body {font-family:Arial, Helvetica, sans-serif; font-size: 12px; color:#4c4b4b;}


a {background-color:inherit; color:#286ea0; font-weight:700; text-decoration:none;font-size:13px;}
a:hover {background-color:inherit; color:#286ea0; text-decoration:none;font-size:13px;}
a img {border:0;}
p {font-size: 10px;font-family:sans-serif;}

div.header{
width:752px;
background-color:#286ea0;
padding:10px 0 0px 50px;
margin:10px 0 0 15px;
color:white;
font-size: 30px;
}

div.header p{
padding:0px 0 10px 20px;
font-weight:italic;
font-size: 14px;
}

div.footer{
width:752px;
margin:10px 0 0 15px;
background-color:#286ea0;
padding:0px 0 0px 50px;
color:white;
clear: left;
}

div.content{
width:752px;
float: left;
margin:10px 0 0 15px;
background-color:inherit;
padding:0px 0 0px 50px;
}


div.main{
float: left;
}
div.areaMessaggi{
float: left;
margin-left:80px;
background-color: silver;
padding-top: 10px;
padding-left: 10px;
padding-right:10px;
}
.errorMessage {
color:red;
}

.actionMessage {
color:green;
}


Vedete le ultime due definizioni di classi. La prima "errorMessage" e quella che i tag di struts danno ai div di errore per default (vedremo in un altro post come cambiare grafica). La seconda è quella per gli action message.

Ed ecco invece la baseFrame.jsp come è diventata:



<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pergiuseppe 82 - Java e Oltre</title>
<link rel="stylesheet" type="text/css" href="css/intro.css" media="all">
</head>
<body>
<tiles:insertAttribute name="header" flush="false"/>

<div class="content">

<tiles:insertAttribute name="frame" flush="false"/>

<div class="areaMessaggi">

<strong>AREA MESSAGGI</strong>
<s:actionmessage/>
<s:fielderror/>
</div>

</div>

<tiles:insertAttribute name="footer" flush="false"/>
</body>
</html>

Prima di <tiles:insertAttribute name="frame" ..... ho inserito:

<div class="content">

e dopo:

<div class="areaMessaggi">

<strong>AREA MESSAGGI</strong>com.blogspot.piergiuseppe82.struts2intro.action

<s:actionmessage/>
<s:fielderror/>

</div>

</div>


Che come potete vedere ora <s:actionmessage/> sta quì e lo tolto dalla concatenaFrame.jsp (dato che sarà utile in un'altra funzione + avanti l'ho messo nel baseFrame per non riscriverlo ogni volta :D )
In aggiunta trovate il tag struts

<s:fielderror/>

quetso tag non fa altro che visualizzare in elenco i messaggi di errore nelle validazioni di campi e che io ho messo nell'area messaggi come riepilogo.

Bene, fatto un esempio basilare, facciamo un qualcosa di più significativo per far capire meglio la validazione in struts2. Voglio farvi vedere diversi tipi di validazione e una custom con una classe creata da noi.

Diamo vita ad una nuova action che ci serve per testare il contenuto di un form con campi eterogenei e con diversi tipi di validazione. Quindi nel packge com.blogspot.piergiuseppe82.struts2intro.action aggiungete la classe action TestValidazioneAction:

/**
*
*/
package com.blogspot.piergiuseppe82.struts2intro.action;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.opensymphony.xwork2.ActionSupport;

/**
* @author placava
*
*/
@SuppressWarnings("serial")
@Component("testValidazioneAction")
@Scope("request")
public class TestValidazioneAction extends ActionSupport {
private static final String SUBMIT = "submit";
private String testoTest;
private String emailTest;
private boolean checkTest;
private int intTest;
private List<String> selectTestList;
private String selectTest;
private String testRadio;
private String parola;


@Override
public String input() throws Exception {
addActionMessage("Valorizza i campi così possso validarli.");
return super.input();
}

public String submit() throws Exception {
addActionMessage("Validazione eseguita con successo!");
return SUBMIT;
}

public String getTestoTest() {
return testoTest;
}

public void setTestoTest(String testoTest) {
this.testoTest = testoTest;
}

public String getEmailTest() {
return emailTest;
}

public void setEmailTest(String emailTest) {
this.emailTest = emailTest;
}

public boolean isCheckTest() {
return checkTest;
}

public void setCheckTest(boolean checkTest) {
this.checkTest = checkTest;
}

public int getIntTest() {
return intTest;
}

public void setIntTest(int intTest) {
this.intTest = intTest;
}

public List<String> getSelectTestList() {
selectTestList = new ArrayList<String>();
selectTestList.add("--scegli--");
selectTestList.add("Juventus");
selectTestList.add("Milan");
selectTestList.add("Inter");
selectTestList.add("Roma");
return selectTestList;
}

public void setSelectTestList(List<String> selectTestList) {
this.selectTestList = selectTestList;
}

public String getSelectTest() {
return selectTest;
}

public void setSelectTest(String selectTest) {
this.selectTest = selectTest;
}

public String isTestRadio() {
return testRadio;
}

public void setTestRadio(String testRadio) {
this.testRadio = testRadio;
}

public String getParola() {
return parola;
}

public void setParola(String parola) {
this.parola = parola;
}

}

notate il getSelectList che fornisce l'elenco delle opzioni di una select che visualizzeremo nella jsp. Se vi chidete perchè non l'ho valorizzata nel metodo input provate dopo aver finito il tutorial e capirete perchè....

Ed ecco quindi la testValidazioneFrame.jsp da mettere in WebContent > frame:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib prefix="s" uri="/struts-tags"%>



<div class="main">

<s:form action="testvalidazione_submit" method="post">

<s:textfield name="testoTest" label="Testo" />

<s:textfield name="emailTest" label="Email" />

<s:checkbox name="checkTest" label="Una Checkbox" labelposition="left"/>

<s:radio list="#{'si':'SI','no':'NO','bu':'FORSE'}" name="testRadio" label="Un Radio" />

<s:textfield name="intTest" label="Un Intero" />

<s:select list="selectTestList" name="selectTest" label="Select Test"></s:select>

<s:textfield name="parola" label="Parola*" />

<s:submit name="submit" value="Valida"/>

</s:form>

*Non deve essere palindroma
</div>

ci stanno un bel po di esempi di tag struts2 che rederizzano tag html. Da notare l'attributo list del tag <s:radio... il suo valore è un esempio di come definire una mappa in OGNL direttamente in una jsp. Se volevo usare una lista dovevo scrivere list="{'SI','NO','FORSE'}". Ovviamente nel rendering del tag html radio ci troveremmo gli stessi valori sia come etichetta che come valore a differenza della mappa. Osservate pure <s:select e riguardate la action basta fare 2+2 per capire come funzionano.

Nello struts.xml aggiungete il mappaggio della action:

...
<action name="testvalidazione_*" method="{1}" class="testValidazioneAction">
<result name="input" type="tiles">testValidazione</result>
<result name="submit" type="tiles">testValidazione</result>
</action>

....

quindi il la defnizione di testValidazione in tiles.xml:

...

<definition name="testValidazione" extends="baseFrame">
<put-attribute name="frame" value="/frames/testValidazioneFrame.jsp" />
</definition>
...

Ora faccio un riepilogo, prima di implementare la validazione, degli attributi della action che devono essere validati e che regola devono avere:
  • testoTest - Non deve esser vuoto
  • emailTest - Non deve essere vuoto e deve essere una email valida
  • checkTest - Deve essere selezionato
  • intTest - Deve essere un intero compreso tra 1 e 10
  • selectTest - Deve essere selezionata una opzione diversa da '-scegli-' e l'opzione deve essere in lista (controllo che fanno in pochi ma risolve dei bug enormi anche di sicurezza)
  • testRadio - Deve essere selezionato si o no
  • parola - No deve essere vuota e non deve essere di tipo palindroma (questo è quello custom)

Diamo vita alla nostra classe custom di validazione. In nuovo package 'com.blogspot.piergiuseppe82.struts2intro.validators' mettiamo la classe CheckPalindroma.java:

/**
*
*/
package com.blogspot.piergiuseppe82.struts2intro.validators;



import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

/**
* @author placava
*
*/
public class CheckPalindroma extends FieldValidatorSupport {

private boolean palindroma;

public boolean isPalindroma() {
return palindroma;
}


public void setPalindroma(boolean palindroma) {
this.palindroma = palindroma;
}
public void validate(Object object) throws ValidationException {
String fieldName = getFieldName();
String parola = (String)this.getFieldValue(fieldName, object);
if(controllaPalindroma(parola)!=isPalindroma())
addFieldError(fieldName, object);
}


private boolean controllaPalindroma(String parola){
if(parola==null || parola.length()<=1)
return true;
for(int i = 0; i<parola.length() / 2; i++){
if(parola.charAt(i)!= parola.charAt(parola.length()-i-1)){
return false;
}
}
return true;
}

}

Come vedete un classe custom di validazione di un campo deve estendere FieldValidatorSupport che obbliga a implementare il metodo 'validate(Object object)'. L'oggeto passato al metodo validate è l'instanza della action che che contiene il metodo da eseguira in caso di validazione positiva. Il nome dell'attributo della action che stiamo validando lo recuperiamo con l'istruzione

String fieldName = getFieldName();

Invece con l'struzione:

String parola = (String)this.getFieldValue(fieldName, object);

recuperiamo il valore dell'attributo.

Recuerato il necessario verifichiamo la condizione che 'se la parola è palindroma e non doveva essere tale o non è palindroma e doveva essere tale' aggiungiamo un errorField (vi ricordate prima quando spiegavo come funzionava la logica di validazione in struts2) alla action con l'istruzione:

addFieldError(fieldName, object);//Per quale attributo e a quale action

PS: gli errorfield si possono aggiungere anche durante l'esecuzione di un metodo come avete avisto con addActionMessage.

Si ma chi ci dice se deve o non deve essere palindroma? E dovo lo imposto tale parametro?

Ce lo di ce l'attributo booleano 'palindroma' presente nella classe del CheckPalindroma e lo impostiamo nel file delle regole di validazione della action come vedremo + avanti.

Ora pensiamo a dire a struts2 che ci sta un nuovo validatore. Per fare ciò dobbiamo mettere nella cartella 'src' il file 'validators.xml' dato che struts2 a runtime lo va a cercare di default in 'WEB-INF > classes' con il seguente contenuto:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">

<validators>
<validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
<validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
<validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
<validator name="expression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
<validator name="checkPalindroma" class="com.blogspot.piergiuseppe82.struts2intro.validators.CheckPalindroma"/>
</validators>

Basta guardare il tag di checkPalindroma per capire come si mappa un nuovo validatore. Sopra ho rimappato gli altri validatori standard di struts2 che utilizzo in questo applicativo ed una cosa che va sempre fatta quando si deve riscrivere un proprio file validators.xml.


Non ci rimane che creare il nostro file di validazione quindi nel package della action mettiamo il TestValidazioneAction-validation.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="testoTest">
<field-validator type="requiredstring" short-circuit="true">
<message><![CDATA[Il Testo e' obbligatorio]]> </message>
</field-validator>
</field>
<field name="emailTest">
<field-validator type="requiredstring" short-circuit="true">
<message> <![CDATA[Il campo Email e' obbligatorio]]> </message>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^[a-z0-9A-Z._-]+@[a-z0-9A-Z._-]+.[a-z]{2,4}</param>
<message><![CDATA[La EMAIL inserita non rispecchia un indirizzo valido]]></message>
</field-validator>
</field>
<field name="checkTest">
<field-validator type="expression" short-circuit="true">
<param name="expression">checkTest == true</param>
<message><![CDATA[Devi spuntare la checkbox]]></message>
</field-validator>
</field>
<field name="testRadio">
<field-validator type="requiredstring" short-circuit="true">
<message> <![CDATA[Devi selezionare un valore dal radio]]> </message>
</field-validator>
<field-validator type="expression" short-circuit="true">
<param name="expression">testRadio=='si' or testRadio=='no'</param>
<message><![CDATA[Devi essere deciso nelle risposte SI o NO?]]></message>
</field-validator>
</field>
<field name="selectTest">
<field-validator type="expression" short-circuit="true">
<param name="expression">selectTest != '--scegli--' and selectTestList.contains(selectTest)</param>
<message><![CDATA[Devi selezionare un valore della select]]></message>
</field-validator>
</field>
<field name="intTest">
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message><![CDATA[Il numero intero deve essere compreso fra 1 e 10]]></message>
</field-validator>
</field>
<field name="parola">
<field-validator type="requiredstring" short-circuit="true">
<message> <![CDATA[Devi inserire la parola]]> </message>
</field-validator>
<field-validator type="checkPalindroma" short-circuit="true">
<param name="palindroma">false</param>
<message><![CDATA[La parola non deve essere di tipo palindroma]]></message>
</field-validator>
</field>
</validators>

Come vedete oltre al <field-vlidator> di tipo 'requiredString' che avete visto prima abbiamo anche:

  • regex - dove va passato il parametro con name 'expression' e che contiene la regex di validazione.
  • expression - dove va passato il parametro con name 'expression' e che contiene la condizione in OGNL che si deve verificare affinchè la validazione abbia esito positivo.
  • int - dove vanno passati i parametri (opzionali) con name 'min' e 'max' che indicano valore minimo e valore massimo dell'intero.
  • checkPalindroma - questo è il nostro validator custom e con il parametro con nome palindroma definiamo con 'true' o 'false' se l'attributo parola deve essere palindroma o no per passare la validazione (ricordate? con questo capite pure come funzionano i param).

Fate attenzione anche all'expression del campo selectTest notate come controllo in OGNL se la lista contiene il valore selezionato e come uso un metodo dell'oggeto List.

Bene compilate deployate e testate ecco il mio risultato:
Ed ecco invece compilando i campi correttamente:


Approfondiamo un pochino.
Vi ricordate quando parlavo dei modi per saltare la validazione in struts2 bene ne esistono diversi, ma ne elenco due per il momento. Facciamo una classe Action di esempio

public class PippoAction extends ActionSupport {
....

public String input() throws Exception {
return super.input();
}

public String save() throws Exception {
return SAVE;
}

public String update() throws Exception {
return UPDATE;
}

public String list() throws Exception {
return UPDATE;
}

public String edit() throws Exception {
return UPDATE;
}

......
}

e abbiamo il nostro bel PippoAction-validation.xml. Sappiamo che in questo modo l'interceptor di struts valida i dati prima di eseguire un qualsiasi metodo della action (tranne per input), ma se volessimo validare con le regole contenute nell'xml solo in caso di 'submit' e 'update'? Il modo + semplice è usare la annotation @SkipValidation sugli altri metodi, ecco come:

public class PippoAction extends ActionSupport {
....

public String input() throws Exception {
return super.input();
}

public String save() throws Exception {
return SAVE;
}

public String update() throws Exception {
return UPDATE;
}

@SkipValidation
public String list() throws Exception {
return UPDATE;
}

@SkipValidation
public String edit() throws Exception {
return UPDATE;
}

......
}

Altro metodo è non usare le annotation e cambiare nome all'xml e usare gli alias nel suo nome. Supponiamo che la action di sopra (senza le annotations) è mappata nello struts.xml in questo modo
...
<action name="pippo_*" method="{1}" class="pippoAction">
<result name="input"...
</action>
...

basta cambiare il nome dell'xml in PippoAction-pippo_save-validation.xml. In questo caso la validazione viene eseguita solo in caso di 'save'. Se vogliamo validare pure 'update' dobbiamo creare un altro file PippoAction-pippo_update-validation.xml. Come potete intuire questa tecnica non conviene utilizzarla per saltare la validazione ma più per personalizzare la validazione nei diversi metodi: magari se vogliamo che in fase di 'save' vengono validati dei campi e in 'update' invece no.

Spero di essere stato chiaro e utile.

I files di progetto eclipse come al solito li trovate QUI.

Bye!Bye!

Nessun commento:

Posta un commento