domenica 28 dicembre 2014

Inserire modificare cancellare righe su Datatable Primefaces

Vai all'indice

Nel post Primefaces esempio introduttivo vi ho presentato l'oggetto Datatable di Primefaces. Come abbiamo visto lo strumento DataTable espone i dati in forma tabellare ed in modo versatile e interattivo. Inoltre, come si può vedere dallo Showcase di Primefaces, è possibile implementare interessanti caratteristiche come: filtri, ordine e gruppi secondo colonne specifiche, tabelle annidate, paginazione e molto altro. In questo post dimostrerò come inserire, modificare e cancellare righe su un oggetto Datatable contenente i dati di una lista di utenti. Non riporterò i file di configurazione pom.xml, web.xml e faces-config.xml poichè sono gli stessi già visti nell'esempio precedente.

La pagina index.xhtml contiene un form necessario per l'inserimento dei dati relativi ai singoli utenti, ed un oggetto Datatable dove vengono gestiti i dati degli utenti una volta inseriti.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      >
    <h:head>
        <title>Gestione utenti</title>
    </h:head>
    <h:body>
        <h:form id="form1">
            <p:growl id="messages" showDetail="true"/>
            <p:panel header="Gestione utenti" style="width: 800px;"> 
                <p:dataTable value="#{utenti.utentiList}" var="o"  widgetVar="50" style="width: 760px;" editable="true">
                    <f:facet name="header">  
                        Lista utenti  
                    </f:facet>
                    <p:ajax event="rowEdit" listener="#{utenti.onEdit}" update=":form1:messages" />  
                    <p:ajax event="rowEditCancel" listener="#{utenti.onCancel}" update=":form1:messages" /> 
                   <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Nome utente" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.nome}" />  
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.nome}" style="width:100%"/>  
                            </f:facet>  
                        </p:cellEditor> 
                    </p:column>

                    <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Ruolo" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.ruolo}" />  
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.ruolo}" style="width:100%"/>  
                            </f:facet>  
                        </p:cellEditor>
                    </p:column>
                     <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Data di nascita" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.data}" >  
                                <f:convertDateTime type="date" pattern="dd-MM-yyyy" timeZone="Europe/Berlin" />
                                </h:outputText>
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.data}" style="width:100%"> 
                                  <f:convertDateTime type="date" pattern="dd-MM-yyyy" timeZone="Europe/Berlin" />
                                </p:inputText>
                            </f:facet>  
                        </p:cellEditor>
                    </p:column>  
                    <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Via" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.via}" />  
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.via}" style="width:100%"/>  
                            </f:facet>  
                        </p:cellEditor>
                    </p:column> 
                    <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Città" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.citta}" />  
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.citta}" style="width:100%"/>  
                            </f:facet>  
                        </p:cellEditor>
                    </p:column>
                    <p:column>
                        <f:facet name="header">  
                            <h:outputText value="Telefono" />  
                        </f:facet>
                        <p:cellEditor>  
                            <f:facet name="output">  
                                <h:outputText value="#{o.telefono}" />  
                            </f:facet>  
                            <f:facet name="input">  
                                <p:inputText value="#{o.telefono}" style="width:100%"/>  
                            </f:facet>  
                        </p:cellEditor>
                    </p:column>                           
                    <p:column headerText="Gest" style="width:50px">  
                        <p:rowEditor />  
                                        
                        <h:commandLink  styleClass="ui-icon ui-icon-trash" action="#{utenti.delete(o)}"/>
                    </p:column> 
                </p:dataTable>
                <p:spacer height="30px;"/>
                <p:panelGrid columns="2">
                   <f:facet name="header">  
                        Nuovo utente
                    </f:facet>
                    <h:outputLabel for="nome" value="Cognome Nome: " />
                    <p:inputText  value="#{utenti.nome}"/>
                    <h:outputLabel for="ruolo" value="Ruolo: " />
                    <p:inputText value="#{utenti.ruolo}"/>
                    <h:outputLabel for="data" value="Data nascita: " />
                    <p:calendar id="popup" value="#{utenti.data}" />
                    <h:outputLabel for="via" value="Via: " />
                    <p:inputText  value="#{utenti.via}"/>
                    <h:outputLabel for="citta" value="citta: " />
                    <p:inputText  value="#{utenti.citta}"/>
                    <h:outputLabel for="telefono" value="Telefono: " />
                    <p:inputMask value="#{utenti.telefono}" mask="999-9999999"/>      
                    <f:facet name="footer">
                        <h:commandButton value="Aggiungi utente" action="#{utenti.addAction}"/>
                    </f:facet>
                </p:panelGrid>                
            </p:panel>
        </h:form>
    </h:body>
</html>

Il Datatable presentato in questo esempio permette di modificare i dati direttamente "inline" tramite un comando Ajax. Cliccando l'icona a forma di matita in fondo alla riga i campi diventano editabili. L'icona "check" permette di consolidare le modifiche effettuate sui dati, mentre l'icona a forma di "x" consente di uscire dalla modalità di "editing" senza modificare i campi. E' possibile cancellare un singolo record cliccando l'icona "trash" in fondo alla riga. Il risultato è rappresentato dall'immagine seguente:









Il backing bean "utentiBean" contiene la definizione delle variabili ed i metodi per l'inserimento, cancellazione e modifica dei dati acquisiti dalla pagina index.

@ManagedBean(name = "utenti")
@SessionScoped
public class utentiBean implements Serializable {

    private static final long serialVersionUID = 1L;
    public String nome;
    public String ruolo;
    private Date data;
    public String via;
    public String citta;
    public String telefono;
    utenteBean utente;


    public String getNome() {
       return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getRuolo() {
        return ruolo;
    }

    public void setRuolo(String ruolo) {
        this.ruolo = ruolo;
    }

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public String getVia() {
        return via;
    }

    public void setVia(String via) {
        this.via = via;
    }

    public String getCitta() {
        return citta;
    }

    public void setCitta(String citta) {
        this.citta = citta;
    }

    public String getTelefono() {
        return telefono;
    }

    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }

    public utenteBean getUtente() {
        return utente;
    }

    public void setUtente(utenteBean utente) {
        this.utente = utente;
    }
    private static final ArrayList<utenteBean> utentiList = new ArrayList<utenteBean>();

    public ArrayList<utenteBean> getUtentiList() {
        return utentiList;
    }

    public String addAction() {
        utenteBean utentetmp = new utenteBean(this.nome, this.ruolo, this.data, this.via, this.citta, this.telefono);
        utentiList.add(utentetmp);

        nome = "";
        ruolo = "";
        String dateStr = "1970-01-01T00:00:00.000+01:00";
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
        try  {
        data = sdf.parse(dateStr.replaceAll(":(?=..$)", "")); 
        } catch (ParseException e) { 
                System.out.println("Unparseable using " + sdf); 
        }
        via = "";
        citta = "";
        telefono = "";
        return null;
    }
    public void onEdit(RowEditEvent event) {  
        FacesMessage msg = new FacesMessage("Record modificato",((utenteBean) event.getObject()).getNome());  
        FacesContext.getCurrentInstance().addMessage(null, msg);  
    }  
       
    public void onCancel(RowEditEvent event) {  
        FacesMessage msg = new FacesMessage("Modifiche annullate");   
        FacesContext.getCurrentInstance().addMessage(null, msg); 
    }  
    public void delete(utenteBean std){
utentiList.remove(std);
FacesMessage msg = new FacesMessage("Record cancellato");   
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}


I dati degli utenti sono salvati in un'istanza Arraylist della classe "UtenteBean" di cui riporto la struttura di seguito.

public class utenteBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private String nome;
    private String ruolo;
    private Date data;
    private String via;
    private String citta;
    private String telefono;

  public utenteBean(String nome, String ruolo, Date data, String via, String citta, String telefono) {
        this.nome = nome;
        this.ruolo = ruolo;
        this.data = data;
        this.via = via;
        this.citta = citta;
        this.telefono = telefono;
 }

public String getNome() {
return nome;
}

public void setNome(String nome) {
this.nome = nome;
}

public String getRuolo() {
return ruolo;
}

public void setRuolo(String ruolo) {
this.ruolo = ruolo;
}

public Date getData() {
return data;
}

public void setData(Date data) {
this.data = data;
}

public String getVia() {
return via;
}

public void setVia(String via) {
this.via = via;
}

public String getCitta() {
return citta;
}

public void setCitta(String citta) {
this.citta = citta;
}

public String getTelefono() {
return telefono;
}

public void setTelefono(String telefono) {
this.telefono = telefono;
}    
    
}


Questo esempio ci dimostra la potenza dello strumento Datatable di Primefaces nella gestione di dati tabellari. Il prossimo passo sarà di utilizzare nel Datatable i dati provenienti da un database, inoltre grazie all'integrazione con Spring e Hibernate renderemo la nostra una vera e propria applicazione enterprise.

Anche questo esempio è scaricabile da GitHub.

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

domenica 7 dicembre 2014

Autenticazione sicura con Primefaces

Vai all'indice

L'obiettivo di questo post è creare una pagina di autenticazione sicura con Primefaces. Per fare questo userò la libreria javax.servlet.Filter che protegge le risorse all'interno di un determinato percorso dell'applicazione.
La pagina login.xhtml acquisisce le chiavi di accesso, se le credenziali sono corrette si accede alle pagine home.xhtml ed esempio.xhtml. Se tentiamo di accedere senza autenticazione ad una di queste due pagine, il filtro ci rimanda alla pagina di login.

La costruzione della webapp, del file pom.xml e web.xml è la stessa già vista nel post Primefaces esempio introduttivo, mentre cambia la struttura del faces-config che riporto di seguito:

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
    <navigation-rule>
        <from-view-id>/login.jsf</from-view-id>
        <navigation-case>
            <from-outcome>home</from-outcome>
            <to-view-id>/home.jsf</to-view-id>
        <redirect>     
        </redirect>
        </navigation-case>
 </navigation-rule>
</faces-config>

Di seguito riporto la pagina di accesso login.xhtml ed il bean associato.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Pagina di login</title>
    </h:head>
    <h:body>
        <h:form id="loginForm">          
            <p:growl id="msg" showDetail="true" life="3000" />
            <p:panel header="Login" style="width: 360px;">
                <h:panelGrid id="loginPanel" columns="2">
                    <h:outputText value="Username" />
                    <p:inputText id="username" value="#{loginBean.uname}" ></p:inputText>
                    <p:spacer></p:spacer> 
                    <p:message for="username" ></p:message>
                    <h:outputText value="Password" />
                    <p:password id="password" value="#{loginBean.password}"  feedback="false"></p:password>
                    <p:spacer></p:spacer>
                    <p:message for="password"></p:message>
                    <p:spacer></p:spacer>
                    <p:commandButton action="#{loginBean.loginProject}" value="Login" update="loginForm" ajax="true"></p:commandButton>
                </h:panelGrid> 
            </p:panel>
        </h:form>
    </h:body> 
</html>

package it.Beans;

import it.Dao.UserDAO;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

@ManagedBean(name = "loginBean")
@SessionScoped

public class LoginBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private String password;
    private String message, uname;

    public String loginProject() {
        boolean result = UserDAO.login(uname, password);
        if (result) {
            // Richiama la sessione Http e salva username
            HttpSession session = Util.getSession();
            session.setAttribute("username", uname);

            return "home";
        } else {

            FacesContext.getCurrentInstance().addMessage(
                    null,
                    new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Credenziali di accesso non valide!",
                    "Riprova di nuovo!"));

            // manda un messaggio di sessione non valida

            return "login";
        }
    }

    public String logout() {
      HttpSession session = Util.getSession();
      session.invalidate();
      return "login";
     }

     // metodi getter e setter
}


La classe LoginBean verifica che le credenziali inserite siano corrette, in tal caso richiama la sessione Http e salva lo username nella sessione corrente. In caso di credenziali errate visualizza un messaggio di errore.

Riporto di seguito le pagine visualizzate dopo la login e protette dal filtro.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Homepage</title>
    </h:head>
    <h:body>
        <h:form>       
            <h1>Benvenuto, #{loginBean.uname}</h1>
            <p>questa è la home page del sito.</p>
            <p:link outcome="esempio" value="Vai alla pagina di esempio"></p:link><br/><br/>
        <p:commandButton action="#{loginBean.logout}" value="Logout"  ajax="false"></p:commandButton>
    </h:form>
    </h:body>
</html>


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Pagina di esempio</title>
    </h:head>
    <h:body>
        <h:form>       
            <h1>Benvenuto, #{loginBean.uname}</h1> 
            <p>questa è una pagina di esempio.</p>
            
            <p:link outcome="home" value="Vai alla homepage"></p:link><br/><br/>
        <p:commandButton action="#{loginBean.logout}" value="Logout"  ajax="false"></p:commandButton>
    </h:form>
    </h:body>
</html>


package it.Dao;
  
public class UserDAO {      
     public static boolean login(String user, String password) {

    if (user.equals("admin") && password.equals("test")) 
            {
               return true;
            }
            else {
                return false;
            }
    }
}

La classe UserDAO simula la chiamata al database per recuperare le chiavi di accesso.

package it.Beans;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class Util {
      public static HttpSession getSession() {
        return (HttpSession)
          FacesContext.
          getCurrentInstance().
          getExternalContext().
          getSession(false);
      }
       
      public static HttpServletRequest getRequest() {
       return (HttpServletRequest) FacesContext.
          getCurrentInstance().
          getExternalContext().getRequest();
      }
}

La classe Util definisce i metodi HttpSession e HttpServletRequest.
HttpServletRequest oltre a permettere l’accesso a tutte le informazioni relative allo header http, permette di ricavare i parametri passati insieme all’invocazione del client.
HttpSession permette di memorizzare le informazioni provenienti dal client all’interno di una sessione salvata sul server al quale viene affidato un identificativo di sessione.

package it.Filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebFilter(filterName = "AuthFilter", urlPatterns = {"*.jsf"})
public class AuthFilter implements Filter {

    public AuthFilter() {
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {   
        try {

            // verifica se la variabile sessione è impostata
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            res.setDateHeader("Expires", 0); // Proxies.
            HttpSession ses = req.getSession(false);
            //  permette all'utente di procedere se ci sono i presupposti
            String reqURI = req.getRequestURI();
            if (reqURI.indexOf("/login.jsf") >= 0 || (ses != null && ses.getAttribute("username") != null)
                    || reqURI.indexOf("/public/") >= 0 || reqURI.contains("javax.faces.resource")) {
                chain.doFilter(request, response);
            } else // utente non loggato ma tenta di accedere ad una pagina non permessa viene rimandato alla pagina di login
            {
                res.sendRedirect(req.getContextPath() + "/login.jsf");  // L'utente anonimo viene rimandato alla pagina di login
            }
        } catch (Throwable t) {
            System.out.println(t.getMessage());
        }    
    
    }
    
    @Override
    public void destroy() {
    }
}

La classe AuthFilter permette all'utente di procedere se ci sono i presupposti e se le credenziali sono corrette, se utente non loggato tenta di accedere alle pagine protette viene rimandato alla pagina di login.
I filtri sono delle classi di utilità molto importanti in quanto consentono di creare un flusso di operazioni particolari senza modificare la struttura principale del nostro software.
Come dimostrato dal nostro esempio anch'essi possono beneficiare delle annotation (vedi @WebFilter), liberandoci dalla necessità di configurare un apposito descrittore nel file web.xml.

Il progetto è ora completo. Lanciando l'applicazione verrà visualizzata la pagina di login:


Anche questo esempio è scaricabile da GitHub.

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

sabato 25 ottobre 2014

Introduzione a Spring con esempio pratico

Vai all'indice

Questo post, ha l'obiettivo di introdurre Spring, attualmente il Framework più usato per lo sviluppo di applicazioni Java Enterprise.
Per fare questo integrerò Spring nello stesso esempio sviluppato nei primi post che trattavano il Framework Hibernate:

Hibernate relazione uno a uno
Hibernate relazione uno a molti
Hibernate relazione molti a molti

Cercherò di mantenere una struttura dell'applicazione simile e utilizzerò lo stesso database Apache Derby descritto negli esempi appena citati,  in modo che sia chiara la differenza dello sviluppo  con e senza l'utilizzo di Spring. La figura seguente descrive la struttura del DB:


Come prima cosa creo un nuovo progetto Maven utilizzando l'archetipo: maven-archetype-quickstart, Riporto di seguito le dipendenze del POM.xml:


<dependency>
 <groupid>org.hibernate</groupid>
 <artifactid>hibernate-entitymanager</artifactid>
 <version>4.2.0.Final</version>
</dependency>
<dependency>
 <groupid>org.springframework</groupid>
 <artifactid>spring-core</artifactid>
 <version>3.2.2.RELEASE</version>
</dependency>
<dependency>
 <groupid>org.springframework</groupid>
 <artifactid>spring-context</artifactid>
 <version>3.2.2.RELEASE</version>
</dependency>
<dependency>
 <groupid>org.springframework</groupid>
 <artifactid>spring-orm</artifactid>
 <version>3.2.2.RELEASE</version>
</dependency>
<dependency>
 <groupid>org.apache.derby</groupid>
 <artifactid>derbyclient</artifactid>
 <version>10.10.1.1</version>
</dependency>
<dependency>
 <groupid>junit</groupid>
 <artifactid>junit</artifactid>
 <version>3.8.1</version>
 <scope>test</scope>
</dependency>

Dato che il DB è lo stesso e l'applicazione usa Hibernate, le entità utilizzate rimangono le medesime degli esempi sopra citati, per questo motivo riporto solo i nomi delle classi, chi desidera può scaricarle da GitHub:

Utente.java
Dettaglioutente.java
Ufficio.java
Applicazione.java


Passo ora a definire le classi DAO (Data Access Object), ovvero le classi che eseguono l'accesso ai dati del database con operazioni di CRUD (Inserimento, cancellazione, aggiornamento).
Per implementare il DAO ho bisogno dell'EntityManager, che viene iniettato direttamente dall' IoC attraverso l'uso della annotation @PersistenceContext. L’EntityManager ha il compito di tradurre le entità in record nel database. Se richiediamo l’aggiornamento di un'entità, l'EntityManager modifica i record corrispondenti del DB, se invece ne richiediamo la cancellazione provvede a rimuoverli. Viceversa quando richiamiamo un record presente nel database, l'EntityManager crea un oggetto entity bean, lo popola con i dati relazionali e lo restituisce.
Il Persistence Context gestisce l'insieme di tutte le modifiche e i cambiamenti di stato occorsi sugli oggetti entità invocate tramite EntityManager in un dato intervallo di tempo. Le classi DAO usano l'annotazione JPA @Transactional, in questo modo i metodi censiti all'interno di essa eseguiranno un commit sul database se tutte le istruzioni vanno a buon fine, in caso contrario verrà eseguito un rollback. Per attivare il comportamento transazionale è necessario inserire l’elemento <tx:annotation-driven transaction-manager="transactionManager"/> all'interno del file di applicationcontext.xml che vedremo più avanti.
Riporto i tre servizi per la gestione delle operazioni sulle entità.


package it.test.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

import it.test.entity.*;


/**
 * Implementazione servizio DAO su Ufficio
 *  
 * @author Mauro Cognolato
 */
@Transactional
public class UfficioDaoImpl {

@PersistenceContext
private EntityManager em;


public int save(Ufficio ufficio) {
em.persist(ufficio);
return ufficio.getUfficioId();
}

public void deleteUfficio(Integer id) {
em.remove(getUfficio(id));
}

public Ufficio getUfficio(Integer id) {
return em.find(Ufficio.class, id);
}

public void aggUffUte(Utente ute, Ufficio uff) {
        uff.getUtenti().add(ute);
        em.merge(uff);
}

public List<Ufficio>getAll() {
return em.createQuery("SELECT p FROM Ufficio p", Ufficio.class).getResultList();
}

}



package it.test.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;


import it.test.entity.*;

/**
 * Implementazione servizio DAO su Utente
 *  
 * @author Mauro Cognolato
 */
@Transactional
public class UtenteDaoImpl {

@PersistenceContext
private EntityManager em;


public int save(Utente utente) {
em.persist(utente);
return utente.getuserId();
}

public void deleteUtente(Integer id) {
em.remove(getUtente(id));
}

public Utente getUtente(Integer id) {
return em.find(Utente.class, id);
}

public void aggUte(Utente ute) {
        em.merge(ute);
}

public List<Utente>getAll() {
return em.createQuery("SELECT p FROM Utente p", Utente.class).getResultList();
}

public void saveDetUte(Utente ute, Dettaglioutente dettUte) {
ute.setDettaglioutente(dettUte);
dettUte.setUtente(ute);
em.persist(ute);
em.flush();
// riallinea l'entitࡡi valori del DB
em.refresh(ute);
}

}



package it.test.dao; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.transaction.annotation.Transactional; import it.test.entity.Applicazione; /** * Implementazione servizio DAO su Applicazioni * * @author Mauro Cognolato */
@Transactional public class ApplicazioneDaoImpl { @PersistenceContext private EntityManager em; public int save(Applicazione applicazione) { em.persist(applicazione); em.flush(); em.refresh(applicazione); return applicazione.getAppid(); } public void deleteApplicazione(Integer id) { em.remove(getApplicazione(id)); } public void deleteApplicazioni() { List<Applicazione> appes = getAll(); for (Applicazione appe : appes) { em.remove(appe); } } public Applicazione getApplicazione(Integer id) { return em.find(Applicazione.class, id); } public List<Applicazione>getAll() { return em.createQuery("SELECT p FROM Applicazione p", Applicazione.class).getResultList(); } }


Passiamo ai file di configurazione di Spring. Il persistence.xml definisce le persistence-unit, ovvero l'insieme di tutte le classi entità di un singolo Datasource che sono gestite dall'EntityManager.


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

<persistence-unit name="jpaData" />

</persistence>

ApplicationContext.xml è il principale file di configurazione di Spring e contiene tutte le specifiche dell'applicazione, analizziamo i bean dichiarati: come prima cosa notiamo la referenziazione delle classi DAO appena definite.
Nell'elemento DataSource sono definiti i parametri di connessione al database Derby. In questo esempio sono in chiaro, ma solitamente i valori vengono gestiti in un file di properties.
L'entityManagerFactory è responsabile della creazione delle istanze dell'EntityManager. Essa richiama la classe LocalContainerEntityManagerFactoryBean che viene configurata per la gestione di JPA e Hibernate. Tra i parametri possiamo notare la definizione della persistent-unit del file persistence.xml visto in precedenza. Tramite l'entityManagerFactory appena creato viene definito anche il transactionManager che coordina la transazionalità delle risorse.



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

<tx:annotation-driven />
<context:annotation-config />

<bean id="utenteDao" class="it.test.dao.UtenteDaoImpl" />
<bean id="ufficioDao" class="it.test.dao.UfficioDaoImpl" />
<bean id="applicazioneDao" class="it.test.dao.ApplicazioneDaoImpl" />

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.apache.derby.jdbc.ClientDriver</value>
<!-- value>org.apache.derby.jdbc.EmbeddedDriver</value -->
</property>
        <property name="url">
            <value>jdbc:derby://localhost:1527/derby/derbyDB</value>
        </property>
        <property name="username">
            <value>tst</value>
        </property>
        <property name="password">
            <value>test</value>
        </property>
</bean>

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="jpaData" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

</beans>


In conclusione creiamo la classe app che contiene il metodo main per eseguire e testare l'applicazione. Come prima cosa istanzio i servizi Dao, procedo quindi con la definizione degli oggetti entità e la popolazione del database, quindi stampo a video alcuni campi per sincerarmi che le operazioni siano andate a buon fine.

L'utente Rossi Mario vive a Milano e lavora nell'ufficio Vendite
  Abilitato all'applicazione: GIS - Sistema territoriale
  Abilitato all'applicazione: SAP - Sistema gestionale


Come ultimo step ripulisco il database, da notare che eliminando l'oggetto ufficio di conseguenza vengono eliminati tutti gli utenti associati per i vincoli di constraint.


package it.test;

import java.sql.Date;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import it.test.dao.UtenteDaoImpl;
import it.test.dao.UfficioDaoImpl;
import it.test.dao.ApplicazioneDaoImpl;
import it.test.entity.Ufficio;
import it.test.entity.Utente;
import it.test.entity.Applicazione;
import it.test.entity.Dettaglioutente;

/**
 * Metodo per testare l'applicazione
 * 
 * @author Mauro Cognolato
 */
public class App {

    public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new  
     ClassPathXmlApplicationContext("applicationContext.xml");
   
    //Istanzio le classi DAO
    UtenteDaoImpl daoUte = (UtenteDaoImpl) context.getBean("utenteDao");
    UfficioDaoImpl daoUff = (UfficioDaoImpl) context.getBean("ufficioDao");
    ApplicazioneDaoImpl daoApp = (ApplicazioneDaoImpl) context.getBean("applicazioneDao");

    // Definisco un oggetto Ufficio e gli assegno il valore 
    Ufficio uff = new Ufficio();
    uff.setNomeUfficio("Vendite");
    daoUff.save(uff);
    int idUff = uff.getUfficioId();
   
    // Istanzio e salvo gli oggetti utente e dettaglioutente
        Dettaglioutente dettUte = new Dettaglioutente( new Date(821212), "via Roma 11", "Milano", "0612345678");
        Utente ute = new Utente("Mario", "Rossi", "Amministratore");
        daoUte.saveDetUte(ute, dettUte);
        
        // Creo gli oggetti Applicazione
        Applicazione app1 = new Applicazione("SAP", "Sistema gestionale");
        daoApp.save(app1);
        Applicazione app2 = new Applicazione("GIS", "Sistema territoriale");
        daoApp.save(app2);

        // Creo un collegamento tra il nuovo utente e l'ufficio
        daoUff.aggUffUte(ute, uff);
        
        // Creo un collegamento tra il nuovo utente e la applicazioni create
        ute.getApplicazioni().add(app1);
        ute.getApplicazioni().add(app2);
        
        // Aggiorno l'utente
        daoUte.aggUte(ute);

        // Recupero e stampo a video gli oggetti
        List<Utente> utenti = daoUte.getAll();
        String nomeUff = uff.getNomeUfficio();
        for (Utente utente : utenti) {
System.out.println("L utente " + utente.getCognome() + " " + utente.getNome() + " vive a " + utente.getDettaglioutente().getCitta() + " e lavora nell'ufficio " + nomeUff);
       for (Applicazione appx : utente.getApplicazioni()) {
        System.out.println("Abilitato all'applicazione: " + appx.getNomeapp() + " - " + appx.getDescrizioneapp());
       }
}
        
        // Pulisco il Database
        // Eliminando l'oggetto uff elimino anche tutti i dettagli associati
        daoUff.deleteUfficio(idUff);
        // Elimino le istanze delle applicazioni
        daoApp.deleteApplicazioni();
        
    }
    
}


In questo post ho introdotto l'utilizzo del framework Spring. Nel prossimo esempio inseriremo un framework di presentazione per la visualizzazione e manipolazione dei dati e di conseguenza trasformeremo l'applicazione in web application.
Potete consultare l'intero progetto su GitHub

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