mercoledì 25 febbraio 2015

Implementazione di una relazione uno-a-molti

Vai all'indice

Il prossimo passo nella costruzione della webapp Prototype è la gestione degli Uffici e l'integrazione con la classe Utente. La struttura delle entità è la stessa proposta nel post Hibernate relazione uno a molti, nel quale si esemplifica la relazione uno a molti tra due tabelle di un database. Nella specifica relazione utenti/uffici ogni utente appartiene ad un solo ufficio, mentre ad ogni ufficio possono appartenere molti utenti.
Per la gestione delle operazioni di inserimento, cancellazione e modifica creo una nuova pagina ufficio.xhtml a cui associo il backing bean ufficiBean. La logica di sviluppo è del tutto simile a quella già descritta per la gestione degli utenti, ma molto più semplice, in quanto l'elaborazione è limitata alla gestione di due campi. Per questo motivo non mi soffermo oltre su questo aspetto, tuttavia chi è interessato può trovare tutto il codice su GitHub.



       <h:selectOneMenu id="ufficio" value="#{utenti.seluff}" effect="fold">
             <f:selectItems value="#{utenti.ufficio1Value}"/>
       </h:selectOneMenu>

Il managed bean utentiBean subisce sostanziali modifiche per la gestione del nuovo campo. Innanzitutto definisco un oggetto Map a cui assegno il nome ufficio1List e nel quale carico i dati da inserire nell'oggetto selectOneMenu. Nel codice seguente riporto il metodo per il caricamento della mappa partendo dall'estrazione della tabella Ufficio:

 public Map ufficio1List = new HashMap();
     public Map getUfficio1Value() {
        int indi=0;
        for (Ufficio uff : uffix) {
             ufficio1List.put(uff.getNomeUfficio(), Integer.toString(uff.getUfficioId()));
             indi = indi + 1;
        }
     return ufficio1List;
  }

Nei metodi addAction e onEdit, che rispondono rispettivamente agli eventi di caricamento e modifica dei dati degli utenti, definisco il collegamento tra gli oggetti Utente e Ufficio.

Ufficio uff = ufficioDao.getUfficio(Integer.parseInt(seluff));

Nell'entità di appoggio utenteBean, che raggruppa i dati estratti dalle tabelle Utente e DettaglioUtente per il caricamento dell'oggetto datatable, definisco il nuovo campo nomeUff in cui salvo la denominazione dell'ufficio da esporre come output al momento del caricamento.

La WebApp aggiornata è scaricabile da GitHub.

Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!

martedì 3 febbraio 2015

Approfondimenti sulla validazione degli utenti

Vai all'indice

Nel post precedente vi ho esposto come ho definito il controllo accessi per l'applicazione "prototype". Nei prossimi paragrafi vi fornirò alcuni dettagli sulle modifiche all'applicazione utili alla gestione degli utenti loggati. A conclusione dell'articolo mi soffermerò sulle regole di navigazione in JSF.
In testa alla pagina index inserisco un nuovo oggetto toolbar in cui riporto lo username dell'utente loggato e i due pulsanti di logoff e cambio password.







<p:toolbar>
        <f:facet name="left"> 
           <h:outputText value="Utente attivo: #{loginBean.uname}" style="color:#2779BD;"/>
        </f:facet>
        <f:facet name="right">
           <p:commandButton action="#{utenti.changePass}" value="Cambio password"  ajax="false">    
           </p:commandButton>
           <p:commandButton action="#{loginBean.logout}" value="Logout"  ajax="false">     
           </p:commandButton>  
        </f:facet>
</p:toolbar>

La pagina changepass riverifica le credenziali di accesso e richiede un doppio inserimento della nuova password. Una funzione di controllo verifica che i due valori  inseriti coincidano ed esegue un test sulla sicurezza della nuova password.



<p:toolbar>
            <h:form id="loginForm">          
            <p:growl id="msg" showDetail="true" life="3000" />
            <p:panel header="Cambio password" style="width: 360px;">
                <h:panelGrid id="loginPanel" columns="2">
                    <h:outputText value="Username" />
                    <p:inputText id="username" value="#{cambioBean.uname}" ></p:inputText>
                    <h:outputText value="Password" />
                    <p:password id="password" value="#{cambioBean.password}" feedback="false">
                    </p:password>
                    <p:spacer></p:spacer>
                    <p:spacer></p:spacer> 
                   
                    <h:outputLabel for="pwd1" value="Nuova password: " />
                    <p:password id="pwd1" value="#{cambioBean.password1}" match="pwd2" label="Password 1" feedback="true" required="true" />

                    <h:outputLabel for="pwd2" value="Riperti password: " />
                    <p:password id="pwd2" value="#{cambioBean.password2}" label="Password 2" feedback="true" required="true" />
                    <p:spacer></p:spacer>
                    <p:spacer></p:spacer>                   
                    <p:commandButton action="#{cambioBean.modiPass}" value="Cambio password" update="loginForm" ajax="true"></p:commandButton>
                </h:panelGrid> 
            </p:panel>
        </h:form>


Nel backing-bean cambioPass.java inserisco il controllo delle credenziali di accesso, la codifica e l'aggiornamento del valore della nuova password nel database.

    public String modiPass() {
        
        boolean trovato = utenteDao.login(uname, password);
        if (trovato) {
        Utente result = utenteDao.estrlogin(uname, password);
            String hashed = "";
            try {hashed = hspass.createHash(password2);}
            catch(Exception ex) {System.out.println("Anomalia conversione password");}
        result.setPassword(hashed);
            utenteDao.aggUte(result);
            return "index";
        } else {
            FacesContext.getCurrentInstance().addMessage(
                    null,
                    new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Credenziali di accesso non valide!",
                    "Riprova di nuovo!"));

            return "changepass";
        }
    }


Approfondimento sulle regole di navigazione in JSF.


Il framework JSF fornisce le navigation-rules che permettono di definire la navigazione da una vista all'altra in un'applicazione web. Le regole di navigazione sono definite nel file di configurazione solitamente denominato faces-config.xml, tuttavia è possibile assegnare un altro nome specificando le direttive nel file web.xml.

 <navigation-rule>
        <from-view-id>/login.jsf</from-view-id>
        <navigation-case>
            <from-outcome>index</from-outcome>
            <to-view-id>/index.jsf</to-view-id>
        <redirect>     
        </redirect>
        </navigation-case>
 </navigation-rule>


Il codice specifica che la pagina login verrà redirezionata verso la pagina index.jsf

  <navigation-rule> 
    <from-view-id>/login.jsp</from-view-id> 
    <navigation-case> 
            <from-outcome>index</from-outcome>
            <to-view-id>/index.jsf</to-view-id>
    </navigation-case> 
    <navigation-case> 
            <from-outcome>goodbye</from-outcome>
            <to-view-id>/goodbye.jsf</to-view-id>
    </navigation-case> 
  </navigation-rule> 


Il codice specidica che la pagina login.jsf ha due output associati a due pagine specifiche.

Il modello di navigazione JSF ci permette di utilizzare dei pattern ovvero dei percorsi che terminano con un "*", in questo caso si vuole applicare una regola a tutte le pagine contenute nella cartella pages.

  <navigation-rule> 
    <from-view-id>/pages/*</from-view-id> 
    <navigation-case> 
            <from-outcome>index</from-outcome>
            <to-view-id>/index.jsf</to-view-id>
    </navigation-case> 
    <navigation-case> 
            <from-outcome>goodbye</from-outcome>
            <to-view-id>/goodbye.jsf</to-view-id>
    </navigation-case> 
  </navigation-rule>   


Questa regola di navigazione verrà applicata per ogni pagina contenuta nel percorso /pages/.

Di seguito un esempio di modello di navigazione JSF più articolato.

  <navigation-rule> 
    <from-view-id>/pages/*</from-view-id> 
    <navigation-case> 
            <from-outcome>goodbye</from-outcome>
            <to-view-id>/goodbye.jsf</to-view-id>
    </navigation-case> 
  </navigation-rule> 
  <navigation-rule> 
    <from-view-id>/pages/login.jsf</from-view-id> 
    <navigation-case> 
            <from-outcome>index</from-outcome>
            <to-view-id>/index.jsf</to-view-id>
    </navigation-case>  
  </navigation-rule> 


In questo caso abbiamo due regole di navigazione: la prima generica per tutte le pagine contenute nel percorso /pages/, la seconda diversa per la pagina login.jsf. In questo caso la regola specifica ha la precedenza sulla regola riferita al path generico.

La WebApp aggiornata è scaricabile da GitHub.

Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!