Creare una semplice web application con JAVA, Eclipse, Tomcat, Hibernate e PostgreSQL – Parte #4

Questo è il quarto di una serie di articoli, la parte precedente si trova qui: Creare una semplice web application con JAVA, Eclipse, Tomcat, Hibernate e PostgreSQL – Parte #3

Cosa potrebbe essere andato storto finora?
Riprendiamo lo sviluppo della nostra web application di esempio concentrandoci per un attimo su quali sono i problemi che si potrebbero incontrare con le funzionalità che abbiamo implementato e gli errori che si potrebbero verificare nel codice e nelle configurazioni sviluppate finora.
Vediamo, ed esempio, gli effetti di una errata configurazione dei driver per il database relazionale scelto (PostgreSQL nel nostro caso) nel file di Hibernate, piuttosto che il tentativo di fare una getParameter di un parametro che in realtà non esiste nell’oggetto HttpServletRequest, finendo con un errore dovuto alla violazione di un constraint definito sulla tabella durante un’operazione di inserti di un nuovo record.

Errore configurazione Hibernate
Un possibile errore che prendiamo in considerazione è quello che si verifica se sbagliamo ad inserire le informazioni di configurazione di Hibernate, relative al RDBMS (Relational DataBase Management System) che vogliamo utilizzare e alle credenziali per l’accesso all’istanza del nostro database, nel file hibernate.cfg.xml.
Supponiamo ad esempio di configurare erroneamente l’utilizzo di PostgreSQL, valorizzando in modo sbagliato la property hibernate.connection.driver_class. Andiamo nel file di configurazione di Hibernate e sostituiamo quindi la riga

<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>

con la riga

<property name="hibernate.connection.driver_class">com.postgresql.Driver</property>

(Si tratta peraltro di un errore già visto realmente, frutto di un copia/incolla da una precedente configurazione del driver per MySql nel cui passaggio a PostgreSQL è rimasta l’estensione “com” invece di “org”)

Hibernate cfg xml Driver error
Lanciando la nostra applicazione con questa configurazione otteniamo ovviamente un errore che ci segnala come non riesca a trovare il driver per il database per che gli abbiamo indicato:

Grave: Servlet.service() for servlet [com.dede.app1st.controller.AddUser] in context with path [/WebTest] threw exception
org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [com.postgresql.Driver]

Nell’immagine seguente il risultato che ci viene mostrato da Tomcat.
Hibernate cfg xml unable to load Driver class

Un altro possibile errore è relativo al fatto che le credenziali per l’accesso al database inserite nel file di configurazione di hibernate non siano corrette. Se proviamo ad esempio a modificare il valore della proprietà “hibernate.connection.password” assegnandole il valore “davis” al posto del valore “dede”, che è la password che abbiamo definito in fase di creazione del database, otteniamo la seguente eccezione:

Grave: Servlet.service() for servlet [com.dede.app1st.controller.AddUser] in context with path [/WebTest] threw exception
org.hibernate.exception.JDBCConnectionException: Error calling Driver#connect
. . .
. . .
Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "postgres"

L’immagine seguente ci illustra nuovamente l’errore ottenuto:
Web Application Hibernate password errata

Get di un parametro che non esiste nella request
Un altro errore che si può commettere nel codice sviluppato finora (negli articoli precedenti) è quello di cercare di estrarre dalla richiesta il valore di un parametro fornendo un valore sbagliato del nome stesso del parametro.
Il valore di un parametro lo abbiamo estratto dall’oggetto HttpServletRequest invocando su di esso il metodo getParameter, definito nell’interfaccia ServletRequest che HttpServletRequest implementa, a cui abbiamo passato di volta in volta il nome del parametro della richiesta di cui volevamo estrarre il valore (“firstname”, “lastname”, ecc..). Per capire quindi cosa succede nel caso in cui specifichiamo come argomento del metodo getParameter il nome di un parametro che non esiste nella richiesta possiamo guardare come tale metodo è definito e descritto nella documentazione ufficiale di JavaEE:

        String getParameter(String name)

Restituisce il valore del parametro richiesto oppure null se il parametro non esiste.

Come possiamo vedere quindi, qualora al metodo getParameter venga chiesto di recuperare dalla request il valore di un parametro che non esiste esso restituisce il valore null, senza scatenare nessun tipo di eccezione o generare di per se alcun errore.
Vediamo un primo esempio:
Torniamo alla nostra prima versione dell’applicazione, quella in cui non avevamo ancora introdotto il salvataggio su database delle informazioni relative al nuovo utente creato. Questa versione si limitava a visualizzare a video le informazioni sull’utente inviate tramite il form utilizzando la pagina jsp “useradd”. Per farlo, andiamo nel metodo doPost della nostra servlet e commentiamo la parte relativa alla creazione del nuovo oggetto User ed al suo inserimento nel database tramite le classi di Hibernate.

web application servlet

Proviamo ora a modificare il file “useradd.jsp” cambiando il nome del parametro di cui vogliamo recuperare il valore tramite il metodo getParameter da “firstname” a “first”. Quest’ultimo ovviamente non esiste perchè nel form tramite cui sottomettiamo i valori il nome resta “firstname”.
HttpServletRequest parametro inesistente
A questo punto eseguiamo nuovamente la nostra applicazione, inseriamo i dati nel form di input e lo sottomettiamo. Quello che ci aspettiamo, come avevamo già visto, è che ci vengano mostrati dalla pagina JSP i dati inseriti.
Web Application input form
Come possiamo vedere dall’immagine seguente, in corrispondenza del campo “First Name” viene mostrato il valore null al posto del valore che avevamo inserito in input nel form. Questo perchè il metodo getParameter, non trovando nessun parametro chiamato “first”, restituisce appunto null.
Web Application null parameter value
Vediamo ora un secondo esempio, in cui ripristiniamo la nostra applicazione alla versione corrente che gestisce le richieste inserendo i nuovi utenti nel database e modifichiamo nuovamente il nome di un parametro che richiediamo alla HttpServletRequest tramite il metodo getParameter, fornendogliene uno che non esiste. In questo caso sostituiamo il nome del parametro “country” con “coun” all’interno del metodo doPost della nostra servlet, nel punto in cui utilizziamo le informazioni inviate con la richiesta per istanziare il nuovo oggetto della classe User.
Lasciamo invece inalterate le getParameter presenti nella pagina JSP “useradd”, che quindi recupereranno correttamente i valori di tutti e tre i parametri.
Web Application request parameter inesistente

Dopo aver fatto le modifiche indicate eseguiamo nuovamente la nostra applicazione,compiliamo come al solito il form con i dati relativi all’utente da creare ed inviamo la richiesta.
Web Application input form

Il risultato che otteniamo è quello illustrato nella figura successiva in cui:

  • L’operazione richiesta va a buon fine e non otteniamo alcun errore o eccezione
  • Nel database viene inserito il record relativo al nuovo utente che presenta però il campo “country” a null invece che valorizzato con la stringa “Argentina” che avevamo inserito in input. Questo perchè il metodo getParameter, essendo stato invocato fornendogli come argomento il nome di un parametro non esistente (“coun”) restituisce null e tale valore viene passato al costruttore della classe User per istanziare il nuovo oggetto. La variabile di istanza “country” del nuovo oggetto viene quindi valorizzata a null e questo valore viene riportato nel database da Hibernate quando effettua la insert. In questo caso non è un problema, in quanto avevamo definito la colonna “country” del database come nullable, indicando che ammettevamo quindi record (e quindi oggetti) in cui essa non fosse valorizzata.
  • Nella pagina JSP invece possiamo vedere come il valore “Argentina” del parametro “country” venga mostrato correttamente. Questo perchè la pagina JSP “useradd” effettua a sua volta la retrieve dei parametri della richiesta tramite il metodo getParameter indicando per tutti i parametri, compreso “country” il nome corretto. Vedremo pi˘ avanti come evitare che la pagina JSP legga nuovamente i valori dei parametri inviati tramite il form, già acquisiti dalla servlet ed inseriti nell’oggetto User creato. Faremo in modo che la servlet passi direttamente l’oggetto User alla JSP tramite il metodo setAttribute della richiesta.
  • Web Application database null value

    Infine vediamo un terzo esempio, analogo a quello appena visto, dove però il parametro per il quale forniamo il nome sbagliato al metodo getParameter, e per cui quindi otteniamo un null, è un campo che nel database è definito not nullable. Nella nostra servlet “AddUser” ripristiniamo quindi la chiamata getParameter(“country”) e modifichiamo invece la chiamata getParameter(“firstname”) in getParameter(“first”) in modo che cerchi di recuperare il valore di un parametro inesistente. Il codice della classe per questo test diventa quindi quello dell’immagine seguente.
    Web Application request parameter inesistente

    Al solito, compiliamo il form con le informazioni di un nuovo utente che vogliamo inserire…
    Web Application input form

    Quello che otteniamo in questo caso è un errore di violazione di un constraint del database, in quanto stiamo cercando di fare una insert di una riga, e quindi di un oggetto, che presenta un valore null in uno dei campi (firstname) che avevamo definito come not nullable in fase di creazione della tabella del database.
    Come possiamo vedere dall’immagine seguente, Hibernate in questo caso scatena una PropertyValueException e ci fornisce il dettaglio relativo alla tipologia di errore e l’indicazione di quale campo di quale classe ha generato il problema.
    Nell’esempio specifico otteniamo infatti

    Grave: Servlet.service() for servlet [com.dede.app1st.controller.AddUser] in context with path [/WebTest] threw exception
    org.hibernate.PropertyValueException: not-null property references a null or transient value : com.dede.app1st.model.User.firstname
    

    che ci segnala che la variabile d’istanza “firstname” della classe “User” è a null e che stiamo cercando di inserirla in una colonna di una tabella del database che i valori null non li ammette.
    Web Application insert database constraint  violato

    Vai all’articolo successivo: Creare una semplice web application con JAVA, Eclipse, Tomcat, Hibernate e PostgreSQL – Parte #5

This entry was posted in $1$s. Bookmark the permalink.

11 thoughts on “Creare una semplice web application con JAVA, Eclipse, Tomcat, Hibernate e PostgreSQL – Parte #4

  1. Pingback: Creare una semplice web application con JAVA, Eclipse, Tomcat, Hibernate e PostgreSQL – Parte #5 | Dede Blog

  2. Scusami, capisco che l’articolo è datato, ma sto prendendo familiarità con hibernate. Quindi seguendo passo passo i tuoi esempi a me da il seguente

    • Ciao,
      l’errore di autenticazione dell’utente sul database è piuttosto parlante.
      Per quanto riguarda invece l’errore Unknown Entity, hai inserito nel file di configurazione di hibernate l’indicazione che User è da inserire sotto la sua gestione tramite il tag “mapping”? In pratica, hai questa riga nel file di configurazione di Hibernate? (ho tolto i tag altrimenti li interpreta e la riga non esce nel commento)
      mapping class=”com.dede.app1st.model.User”

Leave a Reply

Your email address will not be published. Required fields are marked *