Laboratorio di sistemi Approccio DAO JSP [NetBeans] Liberamente adattato da “Java dai fondamenti alla programmazione avanzata JS2E versione 1.5” di Karsten Samaschke, Apogeo editrice Vogliamo realizzare un'applicazione di tipo CRUD (Create, Read, Update, Delete). Queste sono infatti le funzioni più frequentemente richieste quando si lavora con tabelle di dati. Prepariamo quindi un database di prova, guestbook_db, e una tabella di prova, chiamiamola guestbook, la cui struttura è la seguente: Seguono alcuni dati di esempio: Ecco come si presenta l'interfaccia web per la gestione dei record della tabella guestbook. GuestbookDAO.pdf Pag. 1/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Se vogliamo aggiungere un record usiamo il link Nuovo; inseriamo dei dati (solo due campi per semplicità, non c'è inoltre nessun tipo di controllo di validità dei dati) e premiamo sul pulsante Inserisci: Se tutto è andato a buon fine, appare un messaggio di conferma: GuestbookDAO.pdf Pag. 2/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Clicchiamo su uno dei link Modifica in corrispondenza della voce che vogliamo modificare: Se tutto è Ok, appare un messaggio di conferma: GuestbookDAO.pdf Pag. 3/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] In maniera analoga, possiamo cancellare un record, cliccando sul link Cancella; per semplicità abbiamo omesso qualsiasi richiesta di conferma (ma che possiamo inserire mediante del codice javascript); questo significa che la cancellazione è permanente: Nello scrivere il codice di accesso al database, usiamo il cosiddetto “approccio DAO”, un design pattern che si rivela molto utile nella pratica corrente. Esso consiste nella: ● definizione delle classi che devono rappresentare i dati ● messa a disposizione di un'interfaccia che offre metodi per accedere ai dati ● implementazione dell'interfaccia nelle classi concrete ● messa a disposizione di una classe Factory (Factory è il nome di un altro design pattern di cui parleremo in un prossimo articolo), mediante la quale creare un'istanza della classe concreta per la selezione dei dati Questo approccio offre diversi vantaggi: ● nell'applicazione lavorate soltanto con l'interfaccia DAO: l'implementazione concreta rimane nascosta. Ciò significa una manutenzione più facile poiché la classe di accesso ai dati concreti può essere modificata senza che il codice applicativo debba essere rivisto ● gli eventuali accessi al database sono mediati da una classe centrale. Se il modello dei dati cambia (database, file di testo, file XML ecc), l'adattamento riguarderà soltanto questa classe; le chiamate ai metodi non richiederanno modifiche Il codice proposto fa uso di 4 classi di supporto e di 7 pagine jsp. Le classi di supporto sono: 1. GuestbookEntry, che rappresenta una voce nella tabella guestbook di esempio 2. GuestbookDAO, l' interfaccia che definisce i metodi per l'accesso al database 3. MySQLGuestbookDAO, una implementazione concreta di GuestbookDAO 4. GuestbookDAOFactory, la classe Factory per la creazione di istanze di GuestbookDAO Tutto ciò che occorre per connettersi al database è concentrato in una sola istruzione: GuestbookDAO gb = GuestbookDAOFactory.getInstance(); mentre i metodi per la manipolazione dei dati sono forniti dai metodi add, update, delete e GuestbookDAO.pdf Pag. 4/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] retrieve come evidenziato nel frammento di codice seguente: // inserimento; supponiamo l'id del record sia 192 GuestbookDAO gb = GuestbookDAOFactory.getInstance(); GuestbookEntry entry = new GuestbookEntry(); entry.setMessage("Ciao ciao"); entry.setSender("Maurizio"); gb.add(entry); out.println("Record aggiunto "); //modifica gb = GuestbookDAOFactory.getInstance(); entry.setId(195); entry.setMessage("Ancora tu"); entry.setSender("Ancora tu"); gb.update(entry); out.println("Record modificato "); //cancellazione gb = GuestbookDAOFactory.getInstance(); entry.setId(195); gb.delete(entry); out.println("Record cancellato "); Nell'applicativo di cui presentiamo di seguito i codici sorgenti, facciamo in modo, nel momento in cui l'utente richiede una pagina, di stabilire una connessione col database, di effettuare le elaborazioni e di chiudere la connessione. Purtroppo questo approccio può andar bene fino a un certo punto perchè le operazioni di apertura e di mantenimento della connessione sono, da un punto di vista computazionale, particolarmente gravose e richiedono un certo tempo che, per siti con traffico molto sostenuto come possono essere i siti di e-commerce, può essere molto prezioso. Si potrebbe pensare di ricorrere a variabili di sessione per il mantenimento della connessione; tuttavia anche questo approccio non è quello giusto in quanto l'utente poi si ritrova a consultare magari per lungo tempo i dati forniti dal server per cui le risorse allocate per il mantenimento della sessione in questo caso sono inutili. Una soluzione di compromesso consiste nell'usare un pool di connessioni che come dice il termine consiste nel raggruppare e trattare come una singola unità un insieme di connessioni le quali vengono allocate e poi rilasciate via via come descritto meglio in seguito. La cosa interessante è che occorre fare solo qualche leggera modifica all'applicativo perchè tutto continui a funzionare egregiamente. L'unico vincolo è che l'application server supporti JNDI, un servizio ormai ampiamente diffuso in tutti i moderni application server e servlet container, come Tomcat o Application Server 9 della Sun. Ecco il codice (parzialmente commentato) delle classi: GuestbookEntry.java package myPackage; import java.util.Date; GuestbookDAO.pdf Pag. 5/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] /** * Rappresenta una voce nel guestbook */ public class GuestbookEntry { private private private private int id = 0; String message = ""; String sender; Date created = new Date(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getSender() { return sender; } public void setSender(String sender) { this.sender = sender; } public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } } // fine classe GuestbookEntry GuestbookDAO.java package myPackage; import java.sql.SQLException; /** * Definisce i metodi per l'accesso * al database guestbook */ public interface GuestbookDAO { /** * Recupera un array di record */ GuestbookDAO.pdf Pag. 6/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] public GuestbookEntry[] retrieve() throws SQLException; /** * Aggiunge un record al guestbook */ public int add(GuestbookEntry entry) throws SQLException; /** * Aggiorna un record al guestbook */ public int update(GuestbookEntry entry) throws SQLException; /** * Cancella un record dal guestbook */ public int delete(GuestbookEntry entry) throws SQLException; /** * Recupera un record con l'id specificato */ public GuestbookEntry getEntry(int id) throws SQLException; } // fine interfaccia GuestbookDAO MySQLGuestbookDAO.java package myPackage; import java.sql.*; import java.util.ArrayList; import java.util.Properties; import java.io.FileInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import javax.naming.NamingException; /** * Implementazione reale di GuestbookDAO */ public class MySQLGuestbookDAO implements GuestbookDAO { private Connection conn; public MySQLGuestbookDAO() throws ClassNotFoundException, SQLException, NamingException { try { String className = "com.mysql.jdbc.Driver"; String connStr = "jdbc:mysql://localhost:3306/guestbook_db?user=root&password="; Class.forName(className); conn = DriverManager.getConnection(connStr); } catch (ClassNotFoundException e) { throw new ClassNotFoundException("Driver non trovati"); } catch (SQLException e) { throw new SQLException("Errore! Impossibile stabilire una connessione col db"); } } // fine costruttore GuestbookDAO.pdf Pag. 7/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] /** * Recupera un elenco di record dal guestbook */ public GuestbookEntry[] retrieve() throws SQLException { ArrayList<GuestbookEntry> list = new ArrayList<GuestbookEntry>(); if(conn != null) { try { PreparedStatement stmt = conn.prepareStatement( "SELECT id, message, sender, messageDate FROM guestbook ORDER BY id"); ResultSet rs = stmt.executeQuery(); while(rs.next()) { int id = rs.getInt(1); String message = rs.getString(2); String sender = rs.getString(3); java.util.Date d = (java.util.Date)rs.getObject(4); /* if(sender == null || sender.length() == 0) { sender = "mittente ignoto"; } */ GuestbookEntry entry = new GuestbookEntry(); entry.setCreated(d); entry.setId(id); entry.setMessage(message); entry.setSender(sender); } } list.add(entry); conn.close(); } catch (SQLException e) { throw new SQLException("Errore: "+e.getMessage()); } return list.toArray(new GuestbookEntry[0]); } // fine metodo retrieve /** * Aggiunge un record al guestbook */ public int add(GuestbookEntry entry) throws SQLException { int result = 0; if(conn != null) { try { PreparedStatement stmt = conn.prepareStatement( "INSERT INTO guestbook (message, sender, messageDate) " + "VALUES (?, ?, ?)"); GuestbookDAO.pdf Pag. 8/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] stmt.setString(1, entry.getMessage()); stmt.setString(2, entry.getSender()); stmt.setObject(3, entry.getCreated()); result = stmt.executeUpdate(); conn.close(); } catch (SQLException e) { throw new SQLException("Errore: "+e.getMessage()); } } return result; } //fine metodo add /** * Aggiorna un record del guestbook */ public int update(GuestbookEntry entry) throws SQLException { int result = 0; if(conn != null) { try { PreparedStatement stmt = conn.prepareStatement( "UPDATE guestbook SET message = ?, sender = ?, messageDate = ? " + "WHERE id = ?"); stmt.setString(1, entry.getMessage()); stmt.setString(2, entry.getSender()); stmt.setObject(3, entry.getCreated()); stmt.setInt(4, entry.getId()); result = stmt.executeUpdate(); conn.close(); } catch (SQLException e) { throw new SQLException("Errore: "+e.getMessage()); } } return result; } // fine metodo update /** * Cancella un record dal guestbook */ public int delete(GuestbookEntry entry) throws SQLException { int result = 0; if(conn != null) { try { PreparedStatement stmt = conn.prepareStatement( "DELETE FROM guestbook WHERE id = ?"); stmt.setInt(1, entry.getId()); GuestbookDAO.pdf Pag. 9/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] result = stmt.executeUpdate(); conn.close(); } catch (SQLException e) { throw new SQLException("Errore: "+e.getMessage()); } } return result; } // fine metodo delete /** * Ottiene un record dal guestbook con l'id specificato */ public GuestbookEntry getEntry(int id) throws SQLException { GuestbookEntry entry = null; if(conn != null) { try { PreparedStatement stmt = conn.prepareStatement( "SELECT * FROM guestbook WHERE id=?"); stmt.setInt(1, id); ResultSet rs = stmt.executeQuery(); if (rs.next()) { entry = new GuestbookEntry(); int i = rs.getInt(1); String message = rs.getString(2); String sender = rs.getString(3); java.util.Date d = (java.util.Date)rs.getObject(4); entry.setCreated(d); entry.setId(i); entry.setMessage(message); entry.setSender(sender); // non chiudiamo subito la connessione // potrebbe tornarci utile return entry; } } catch (SQLException e) { throw new SQLException("Errore: "+e.getMessage()); } } // fine if return entry; } / fine metodo getEntry } // fine classe MySQLGuestbookDAO GuestbookDAOFactory.java package myPackage; import java.sql.SQLException; GuestbookDAO.pdf Pag. 10/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] import javax.naming.NamingException; /** * Factory per la creazione di istanze di GuestbookDAO */ public class GuestbookDAOFactory { public static GuestbookDAO getInstance() throws ClassNotFoundException, SQLException, NamingException { return new MySQLGuestbookDAO(); } } Segue il codice delle pagine web: guestbookAdd.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page import="myPackage.*" %> <%@page errorPage="errore.jsp" %> <!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>JSP Page</title> <link href="css.css" rel="stylesheet" type="text/css" /> </head> <body> <h3>Aggiungi</h3> <form name="frmInserisci" method="POST" action="<%=request.getRequestURI()%>"> Sender: <input type="text" name="txtSender" value="" /><br/> Message: <textarea name="txtMessage" cols="35" rows="5"></textarea><br/> <input type="submit" value="Inserisci" name="btnInserisci" /> </form> <% if (request.getParameter("btnInserisci")!=null) { int result = 0; String message=request.getParameter("txtMessage"); String sender=request.getParameter("txtSender"); GuestbookDAO gb = GuestbookDAOFactory.getInstance(); // se uso una variabile di sessione potrei recuperare la connessione al database // direttamente dalla sessione //GuestbookDAO gb = (GuestbookDAO) session.getAttribute("gb"); if (gb!=null) { GuestbookEntry entry = new GuestbookEntry(); entry.setMessage(message); GuestbookDAO.pdf Pag. 11/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] entry.setSender(sender); result = gb.add(entry); if (result != 0) response.sendRedirect("guestbookRetrieve.jsp?message=Record registrato correttamente"); else response.sendRedirect("guestbookRetrieve.jsp?message=Impossibile registrare il record"); } } %> </body> </html> guestbookDelete.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page import="myPackage.*" %> <%@page errorPage="errore.jsp" %> <!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>JSP Page</title> <link href="css.css" rel="stylesheet" type="text/css" /> </head> <body> <h3>Modifica</h3> <% if (request.getParameter("id")!=null) { int result = 0; int id = Integer.parseInt(request.getParameter("id")); GuestbookDAO gb = GuestbookDAOFactory.getInstance(); //GuestbookDAO gb = (GuestbookDAO) session.getAttribute("gb"); if (gb!=null) { GuestbookEntry entry = gb.getEntry(id); if (entry != null) { out.println("Cancellazione record id="+entry.getId()+"<br/>"); result = gb.delete(entry); if (result != 0) GuestbookDAO.pdf Pag. 12/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] response.sendRedirect("guestbookRetrieve.jsp?message=Record cancellato correttamente"); else response.sendRedirect("guestbookRetrieve.jsp?message=Impossibile cancellare il record"); } } else response.sendRedirect("guestbookRetrieve.jsp?message=Record non trovato"); } else response.sendRedirect("guestbookRetrieve.jsp"); %> </body> </html> guestbookRetrieve.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page import="myPackage.*" %> <%@page errorPage="errore.jsp" %> <!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>JSP Page</title> <link rel="stylesheet" type="text/css" href="css.css"> </head> <body> <h3>Approccio DAO</h3> <% /* * codice valido nel caso di una sessione if (session.getAttribute("gb")==null) { gb = GuestbookDAOFactory.getInstance(); session.setAttribute("gb",gb); session.setMaxInactiveInterval(-1); } else { gb = (GuestbookDAO) session.getAttribute("gb"); } */ GuestbookDAO gb = GuestbookDAOFactory.getInstance(); GuestbookEntry[] entries = gb.retrieve(); if (request.getParameter("message")!=null) { String message=request.getParameter("message"); out.println("<span class='red'>"+message+"</span>"); } GuestbookDAO.pdf Pag. 13/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] out.println("<table>"); out.println("<tr>"); out.println("<td>"); out.println("ID"); out.println("</td>"); out.println("<td>"); out.println("Sender"); out.println("</td>"); out.println("<td>"); out.println("Message"); out.println("</td>"); out.println("<td>"); out.println("Date"); out.println("</td>"); out.println("<td>"); out.println("Modifica"); out.println("</td>"); out.println("<td>"); out.println("Cancella"); out.println("</td>"); out.println("</tr>"); for(GuestbookEntry entry : entries) { out.println("<tr>"); out.println("<td>"); int id=entry.getId(); //out.println(id); out.println(entry.getId()); out.println("</td>"); out.println("<td>"); out.println(entry.getSender()); out.println("</td>"); out.println("<td>"); out.println(entry.getMessage()); out.println("</td>"); out.println("<td>"); out.println(entry.getCreated()); out.println("</td>"); out.println("<td>"); out.println("<a href=guestbookEntry.jsp?id="+id+">Modifica</a>"); out.println("</td>"); out.println("<td>"); out.println("<a href=guestbookDelete.jsp?id="+id+">Cancella</a>"); GuestbookDAO.pdf Pag. 14/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] out.println("</td>"); out.println("</tr>"); } out.println("</table><br/>"); out.println("<a href=guestbookAdd.jsp>Nuovo</a>"); %> </body> </html> guestbookUpdate.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page import="myPackage.*" %> <%@page errorPage="errore.jsp" %> <!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>JSP Page</title> <link href="css.css" rel="stylesheet" type="text/css" /> </head> <body> <h3>Aggiornamento</h3> <% if (request.getParameter("btnAggiorna")!=null) { int result = 0; String message = request.getParameter("txtMessage"); String sender = request.getParameter("txtSender"); int id = Integer.parseInt(request.getParameter("id")); GuestbookDAO gb = GuestbookDAOFactory.getInstance(); //GuestbookDAO gb = (GuestbookDAO) session.getAttribute("gb"); if (gb!=null) { GuestbookEntry entry = new GuestbookEntry(); entry.setId(id); entry.setMessage(message); entry.setSender(sender); result = gb.update(entry); GuestbookDAO.pdf Pag. 15/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] if (result != 0) response.sendRedirect("guestbookRetrieve.jsp?message=Record aggiornato correttamente"); else response.sendRedirect("guestbookRetrieve.jsp?message=Impossibile aggiornare il record"); } } else response.sendRedirect("guestbookRetrieve.jsp"); %> </body> </html> guestbookEntry.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page import="myPackage.*" %> <%@page errorPage="errore.jsp" %> <!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>JSP Page</title> <link href="css.css" rel="stylesheet" type="text/css" /> </head> <body> <h3>Modifica</h3> <% if (request.getParameter("id")!=null) { int id=Integer.parseInt(request.getParameter("id")); GuestbookDAO gb = GuestbookDAOFactory.getInstance(); //GuestbookDAO gb = (GuestbookDAO) session.getAttribute("gb"); if (gb!=null) { GuestbookEntry entry = gb.getEntry(id); if (entry != null) { out.println("Modifica record id="+entry.getId()+"<br/>"); %> /><br/> <form name="frmAggiorna" method="POST" action="guestbookUpdate.jsp"> Sender: <input type="text" name="txtSender" value="<%=entry.getSender() %>" Message: <textarea name="txtMessage" cols="35" rows="5"><%=entry.getMessage() %></textarea><br/> <input type="hidden" name="id" value="<%=entry.getId() %>" /> <input type="submit" value="Aggiorna" name="btnAggiorna" /> GuestbookDAO.pdf Pag. 16/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] </form> <% } else response.sendRedirect("guestbookRetrieve.jsp?message=Record non esistente"); } } else response.sendRedirect("guestbookRetrieve.jsp"); %> </body> </html> errore.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@page isErrorPage="true" %> <%@page import="java.io.PrintWriter" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% PrintWriter writer=new PrintWriter(out); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Pagina di errore</title> <style type="text/css"> <!-body,td,th { font-family: Trebuchet MS; font-size: 10pt; } --> </style> </head> <body> <h2>Gestione degli errori</h2> <p>Si è verificato il seguente errore: <%=exception.getMessage()%></p> </body> </html> Pool di connessioni Con un pool di connessioni, vengono ottimizzate le operazioni di apertura e mantenimento delle connessioni perchè, ad esempio, una connessione chiusa non viene definitivamente eliminata dalla memoria del sistema ma restituita al pool e nel momento in cui è necessaria una nuova connessione, essa viene recuperata direttamente dal pool senza doverne allocare una nuova. Per poter usare i pool di connessioni, è necessario innanzitutto utilizzare JNDI. Per prima cosa, logghiamoci nella console amministrativa del nostro application server (per noi Sun Application Server 9). GuestbookDAO.pdf Pag. 17/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Username di default admin e password adminadmin GuestbookDAO.pdf Pag. 18/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Cerchiamo Resources nell'albero di navigazione di sinistra, quindi scegliamo JDBC > Connection Pools e costruiamo il pool di connessioni MySQLGuestBookPool con i seguenti dati GuestbookDAO.pdf Pag. 19/26 Cozzetto © Laboratorio di sistemi GuestbookDAO.pdf Approccio DAO Pag. 20/26 JSP [NetBeans] Cozzetto © Laboratorio di sistemi GuestbookDAO.pdf Approccio DAO Pag. 21/26 JSP [NetBeans] Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Stabiliamo i parametri fondamnetali di accesso al database e lasciamo tutti gli altri impostati per default (come il numero massimo di connessioni, il tempo di attesa massimo ecc). Facciamo il ping per assicurarci che il pool funzioni correttamente. GuestbookDAO.pdf Pag. 22/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Successivamente, costruiamo un data source JDBC, assegnandogli un nome (JNDI name: nel nostro caso jdbc/guestbook) e associandolo al pool di connessioni MSQLGuestBookPool. GuestbookDAO.pdf Pag. 23/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Occorre poi modificare il deployment descriptor (il file web.xml) in modo tale che contenga un riferimento alla nostra risorsa appena creata (in Netbeans conviene farlo tramite interfaccia grafica). GuestbookDAO.pdf Pag. 24/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] Il contenuto del file web.xml è quindi il seguente: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/webapp_2_4.xsd"> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> <resource-ref> <res-ref-name>jdbc/guestbook</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> </web-app> GuestbookDAO.pdf Pag. 25/26 Cozzetto © Laboratorio di sistemi Approccio DAO JSP [NetBeans] L'ultimo passo è modificare il codice relativo alla creazione della connessione (riportiamo solo il frammento utile), senza modificare in alcun modo il codice già scritto [costruttore MySQLGuestbookDAO()]: try { javax.naming.InitialContext ctx = new javax.naming.InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("java:comp/env/jdbc/guestbook"); conn = ds.getConnection(); } catch (NamingException e) { throw new NamingException(e.getMessage()); } catch(SQLException e) { throw new SQLException("Errore! Impossibile stabilire una connessione col db"); } // fine try-catch al posto di: try { String className = "com.mysql.jdbc.Driver"; String connStr = "jdbc:mysql://localhost:3306/guestbook_db?user=root&password="; Class.forName(className); conn = DriverManager.getConnection(connStr); } catch (ClassNotFoundException e) { throw new ClassNotFoundException("Driver non trovati"); } catch (SQLException e) { throw new SQLException("Errore! Impossibile stabilire una connessione col db"); } // fine try-catch GuestbookDAO.pdf Pag. 26/26 Cozzetto ©