Newsgroup: it.comp.java
Titolo: pool di connessioni e singleton

in un progetto jsp/servlet se si usa un pool di connessioni al db che
utilit� potrebbe avere usare sempre la stessa con un singleton?
lo chiedo perch� ho visto dei progetti cos� fatti
grazie
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

grazie
Sostanzialmete esistono 3 approcci per le connecction :
1. Una sola connection.
Il jdbc e' progettato in modo che una singola connection puo' aprire N
statement che possono operare sul db in parallelo.
Per tanto si puo' progettare una applicazione che abbia una sola ( o qualche
una ) connection universale. Questo approccio ha
vantaggi : prestazioni, infatti la connction tendenzialmente non si chiude mai
e aprire e chiudere una connction e' pesante
svantaggi : Non hai differenziazione di user, tutti hanno gli stessi privilegi
tutto viene loggato sul db con lo stesso user a livello db
2. Apri una connction ogni accesso a db e poi la chiudi.
Questo approccio e' pesante per le prestazioni ma ha dei vantaggi in termini
di Utenze.
3. Il pool
E' una via di mezzo dei 2. Di fatto le connction restano aperte e vengono
assegnate ai vari thread che eseguono le operazioni su db e poi le rilasciano
al pool che le assegna ai prossimi.
Anche questo approccio usa l'utente unico
Ciao NIcola
-- 

 diana_est ha scritto:
P.S.
Effettivamente l'approccio 3 dovrebbe essere sempre migliore in tutto dell'1
e quindi non e' molto giustificato l'uso di una connessione universale se
c'e' un pool in circolazione
 
Ciao NIcola
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 quindi singleton e pool sono in alternativa giusto?



Boh, prova a postarlo il codice di sto singleton.
Difficile dire per certo.
Magari il singleton serve per gestire il pool in modo "manuale"
ma davvero non si puo' dire molto a priori
N


 N

no beh qua non ce l'ho ma l'ho visto; vabbeh diciamo che ora uso un pool e
basta


 utilit� potrebbe avere usare sempre la stessa con un singleton?
non lo so, dovresti chiederlo a chi lo fa.
sono anni che il jdbc dice di usare il DataSource specialmente (ma non 
solo) in ambito jee. se c'� ancora chi s'inventa la ruota e pure si 
meraviglia perch� gli viene squadrata, non so che farci.

 Anche questo approccio usa l'utente unico
Piu' che altro è l'unica soluzione del non peracottaro.

 
Non e' detto. Se utilizzi una connessione singleton per sessione 
prelevata dal pool, puoi fare in modo che la connessione riconfluisca 
nel pool quando la sessione muore, che forse dal punto di vista 
dell'utilizzo del db e' il modo piu' efficente, mentre dal punto di 
vista delle  prestazioni e' invariante, infatti quando ottieni una 
connessione da un pool, il pool te ne restituisce una gia' esistente, 
mentre quando la chiudi in realta' non fai altro che restituirla al pool.
La gestione degli utenti utilizzando un pool non e' problematica, ma 
spesso c'e' un controllo accessi a monte, per cui in questi casi il 
controllo dell'utente da parte del db non serve.
Naturalmente molto dipende dall'implementazione del DataSource del 
driver, l'interfaccia DataSource ha due metodi:
Connection getConnection();
e:
Connection getConnection(String username, String password);
che risolverebbe il problema dell'utente nella gestione a pool, ma 
questo secondo metodo non sempre e' implementato come ci si aspetterebbe.

 In ambito web questa non funziona.
La implementai nel 1997 per una intranet web di una azienda con 50 dipendenti
quando i pool non esistevano :-)
Il problema e' che dai in giro statement a ogni richiesta, devi controllare
bene che le parti di codice che ricevono gli statement li rilascino
perfettamente o rischi che ti si intasa tutto.
Inoltre un pool di 10-20 connessioni e' piu' efficiente di una sola
connection
ma e' tutto DBMS dependant, le connessioni e gli statement in java sono solo
wrapper vuoti delle
connection e statement(command) reali sul dbms, quindi dipende dal dbms, dal
driver eccetera.
P.S.
ho letto che continui con Seam, mi fa piacere. Anche io ogni progetto che
posso glielo metto dentro, ma spesso non si puo' per un motivo o per l'altro
Sono riuscito da qualche mese finalmente anche a passare al 2.1 e richfaces
:-)
Sai che io sono quasi sempre anche su Liferay e quei f.d.p. di Liferay e di
JBoss non si amano proprio :-/
ciao Nicola
-- 

 vista delle  prestazioni e' invariante
A parte il problema delle chiamate concorrenti (probabilità niente
affatto remota con AJAX), questo approccio limita fortemente la
scalabilità dell'applicazione.
L'approccio ottimale consiste nel chiedere una connessione al pool
quando necessario, e chiuderla (aka restituirla al pool) il prima
possibile.  Quindi al più una connessione per richiesta, non certo per
sessione.

 JBoss non si amano proprio :-/
Sono particolarmente interessato a CDI ultimamente, e quindi di
conseguenza a Seam3. Per quanto riguarda le portlet sapevi che Gavin
le ha definite "una soluzione in cerca di problemi"?

 le ha definite "una soluzione in cerca di problemi"?
Non c'era bisogno di GK per capirlo :-)))
Il fatto e' il CMS tira. CMS propietari neanche per scherzo. CMS buoni o
portlet o PHP. Preferisco morire "in cerca di problemi" con le portlet che
"cambiare sponda" :-))
Nicola 
-- 

il 10.06.2010 14.43, Scrive cicap 41406120:

Se avessi anche detto da che punto di vista "l'approccio e' ottimale", 
potremmo anche essere d'accordo.
Il punto e', che se dal punto di vista applicativo avessi bisogno di una 
certa persistenza della connessione, dovrai utilizzare delle tecnologie 
che non facciano a cazzotti tra loro. L'Ajax sara' anche una bella cosa, 
  finche' leggi il tuo modello dati e basta, ma se devi anche fare 
aggiornamenti, sono piu' le grane che i benefici. Se ad esempio per 
iniziare e concludere una transazione hai bisogno di emettere piu' 
pagine, e committare solo alla fine, una connessione che persista nella 
sessione, almeno fino alla fine della transazione, e' una gran comodità.
Ovviamente ci sono alternative, ma ognuna ha i suoi ma e i suoi perche'.

 sessione, almeno fino alla fine della transazione, e' una gran comodità.
Innanzitutto questo è l'unico caso pratico per il quale abbia senso 
parlare di connessione per utente, non un esempio qualsiasi.
Non è però una soluzione decente, altro che ottimale. Quante connessioni 
hai intenzione di avere nel pool? E quanti utenti contemporanei pensi di 
poter servire con questa tecnica?
Siccome sono solito gestire la persistenza con l'accoppiata 
JPA-Hibernate, fortunatamente ho a disposizione tecniche molto migliori, 
giocate sul flushing della sessione.

 3. Il pool [...]
Ciao nn, io sto appunto studiando l'uso di pool MySql in applicazioni 
stand-alone, ma non ho trovato documentazione a riguardo, così sono 
andato ad intuito... secondo te questo approccio va bene?
import java.sql.*;
import javax.sql.*;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
public class DatabaseAccess {
  PooledConnection pooledConnection;
  public DatabaseAccess() throws SQLException {
    MysqlConnectionPoolDataSource customDS =
      new com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource();
    customDS.setUser("myUser");
    customDS.setPassword("myPassword");
    customDS.setDatabaseName("myDatabase");
    pooledConnection = customDS.getPooledConnection();
  }
  public Connection getConnection() throws SQLException {
    Connection conn = pooledConnection.getConnection();
    return conn;
  }
}
-- 
Enos
//          Senza Dio, l'anima. Senza anima, le virtù.
//         Senza virtù, la legge. Con la legge, il caos.

 giocate sul flushing della sessione.
Questo e' un altro discorso. Anch'io uso tecniche analoghe, pero' ad uno 
che ti chiede banalmente e genericamente di un progetto "jsp/servlet" e 
se gestire le connessioni al db in pool o singleton, cosa gli rispondi? 
Che esiste la programmazione per aspetti?
Tenendo poi presente che qualche post fa', la stessa persona, si poneva 
il problema di ottimizzare delle connessioni su mysql, a me non viene in 
mente un'applicazione da 50000 transazioni ora, per cui ci sta anche che 
non si metta ad imbracciare un cannone per debellare le zanzare.

 non si metta ad imbracciare un cannone per debellare le zanzare.
Ma guarda che la necessità di tenere una transazione attiva tra più 
richieste è una cosa piuttosto rara, e tu quindi hai consigliato una 
tecnica che può servire (malamente) in una situazione assolutamente 
eccezionale. Questo è peggio che consigliare un cannone contro una zanzara.

}
La prima questione fondamentale e' capire se c'e' o meno un appserver di
qualsiasi tipo, infatti tutti gli app server ( credo ) offrono il pooling via
jndi
ti copio direttamente l'esempio della 
dev.mysql.com
public class MyServletJspOrEjb {
    public void doSomething() throws Exception {
        /*
         * Create a JNDI Initial context to be able to
         *  lookup  the DataSource
         *
         * In production-level code, this should be cached as
         * an instance or static variable, as it can
         * be quite expensive to create a JNDI context.
         *
         * Note: This code only works when you are using servlets
         * or EJBs in a J2EE application server. If you are
         * using connection pooling in standalone Java code, you
         * will have to create/configure datasources using whatever
         * mechanisms your particular connection pooling library
         * provides.
         */
        InitialContext ctx = new InitialContext();
         /*
          * Lookup the DataSource, which will be backed by a pool
          * that the application server provides. DataSource instances
          * are also a good candidate for caching as an instance
          * variable, as JNDI lookups can be expensive as well.
          */
 
        DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");
        /*
         * The following code is what would actually be in your
         * Servlet, JSP or EJB 'service' method...where you need
         * to work with a JDBC connection.
         */
        Connection conn = null;
        Statement stmt = null;
        try {
            conn = ds.getConnection();
            /*
             * Now, use normal JDBC programming to work with
             * MySQL, making sure to close each resource when you're
             * finished with it, which allows the connection pool
             * resources to be recovered as quickly as possible
             */
            stmt = conn.createStatement();
            stmt.execute("SOME SQL QUERY");
            stmt.close();
            stmt = null;
            conn.close();
            conn = null;
        } finally {
            /*
             * close any jdbc instances here that weren't
             * explicitly closed during normal code path, so
             * that we don't 'leak' resources...
             */
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (sqlexception sqlex) {
                    // ignore -- as we can't do anything about it here
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (sqlexception sqlex) {
                    // ignore -- as we can't do anything about it here
                }
                conn = null;
            }
        }
    }
}
Se necessiti il pooling vuole dire che alla tua applicazione accedeno molti
utente/thread, il che significa che di fatto stai costruendo un pezzo di
server.
Questa cosa induce a suggerirti di usare un application server ( tipo tomcat o
jboss o glassfish o altro ) che ti gestiscono loro il pooling e in futuro ti
possono offrire altri utili servizi
Come vedi il principio e' semplice, via jndi ottieni un datasource ( con la
lookup )
il quale poi ti da le connection "poolate"
Qualora volessi davvero gestire tu il pool "a mano" per qualche ragione, le
cose si complicano un po'
poiche' non lo ho mai fatto in una applicazione stand alone ti posso solo
suggerire
http://commons.apache.org/dbcp/
e i suoi esempi
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/doc/
che sono un modo di usare il pool stand alone proposto da mamma apache
ciao NIcola
-- 

 eccezionale. Questo è peggio che consigliare un cannone contro una zanzara.
Guarda che hai frainteso, io non ho proprio consigliato un bel niente. 
C'e' chi fa domande, e se posso rispondo, ma a chi non chiede consigli 
ma solo delucidazioni tecniche mi guardo bene dal consigliare. Al 
massimo segnalo i problemi che possono montare adottando una certa 
tecnica, cosa che ho fatto, ma da qui a dare il 'la' per iniziare un 
progetto ce ne passa.

 progetto ce ne passa.
E' quello che ho tentato di fare: avvisarlo che quella scemenza della 
connessione per utente è una pratica sbagliata.

 driver eccetera.
non ho capito che vuoi dire.

non ho capito che vuoi dire.
E' un ragionamento per fare capire a chi si pone domande sul jdbc in generale
che aprire / chiudere una connection o uno statement non e' solo una
operazione java, ma al contrario in java si fa ben poco al di la di una new,
il grosso dell'operazione avviene a livello di dbms, per cui ogni ragionamento
sulle connection va sempre fatto senza prescindere da cosa succede sul dbms,
in pratica non e' solo da pensare cosa e' meglio per il programmatore ma anche
cosa e' meglio per il dbms, ma forse andiamo OT.
ciao NIcola
-- 


Solo un'osservazione: MAI usare direttamente un'implementazione! 
Ovviamente mi riferisco solo all'argomento della discussione, ma a tutti 
i servizi in genere.
Il consiglio è di utilizzare una libreria di terze parti, ad esempio DBCP:
http://commons.apache.org/dbcp/
ma comunque ce n'è diversi, vedi qui per un elenco:
http://java-source.net/open-source/connection-pools
E comunque se l'applicazione è stand-alone (mono-utente immagino) 
sinceramente non vedo l'utilità di un connection-pool... dovrebbe 
bastare aprire una connessione all'inizio e chiuderla quando esci. Come 
ai vecchi tempi ;)
-- 
Dimitri De Franciscis
Phone:  
(+39) 3401570778
Website: 
http://www.megadix.it/

 i servizi in genere. [...]
Scusa, ma non rischio che mi cambino sotto il naso la libreria, così come 
l'implementazione (che includo come libreria esterna)? Almeno se uso 
l'implementazione ottengo qualcosa di più snello ed ho maggiore controllo.
Naturalmente la mia è una provocazione, sono praticamente certo che 
riuscirai a convincermi del contrario.
Saluti


 [...] dbcp [...]
Questo lo discuto con Dimitri perché mentre tu me lo hai consigliato, lui 
me lo ha *imposto* :-)
Grazie molte, sei stato gentilissimo.
Ciao


 connessione venga chiusa immediatamente?
Dipende dal driver, ma in generale la regola d'oro è chiudere sempre,
e chiudere in blocchi finally.


Bah, lasciando stare questioni filosofiche, correttezza formale, ecc ecc 
ecc ma rimanendo sul piano pratico:
- il tempo da investire all'inizio dello sviluppo per inserire la 
libreria di connection pool è poca cosa;
- più avanti, se l'applicazione ha una qualche utilità, andrà aggiornata 
per poter sfruttare: a) un nuovo database b) una nuova versione del 
vecchio database c) una nuova versione del driver
Però modificare l'applicazione in corsa perché ci sono dipendenze 
dirette verso un vendor e/o una versione specifica è cosa molto 
fastidiosa e soprattutto si tratta di codice "boilerplate", burocrazia 
insomma, che come si sa in tempi di emergenza è solo un intralcio...


 Grazie molte, sei stato gentilissimo.
Prego
Nicola


 fastidiosa [...]
Non stiamo di nuovo cadendo nel tranello della "ottimizzazione 
preventiva"?
Sto partendo con una piccola applicazione. Se meriterà di essere espansa, 
vorrà dire che potrò permettermi di dedicarle il tempo che merita, 
espandendola in modo opportuno.
Non mi pare di essere limitato, dal momento che le raccomandazioni JDBC 
suggeriscono che i driver JDBC stessi sappiano fornire oggetti 
javax.sql.ConnectionPoolDataSource
in grado di creare i pool. Si tratta solo di creare una mini-classe che 
fornisce i suddetti oggetti, invece di caricare una libreria intera, 
vulnerabile a bug, che inevitabilmente penalizzerà le prestazioni.
Magari in questo caso specifico i benefici sono marginali, ma quante 
applicazioni Java enterprise hanno bisogno di girare su hardware 
mostruoso per mantenere applicazioni adeguate, solo perché si sono usate 
nmila librerie stratificate una sull'altra?


 mostruoso per mantenere _applicazioni_ adeguate [...]
Errata corrige: leggasi "per mantenere prestazioni adeguate"
-- 
Enos

 vulnerabile a bug, che inevitabilmente penalizzerà le prestazioni.
Non c'è dubbio. Proverò a condensare la mia opinione in una frase: "Se 
pensi che prima o poi dovrai adattare l'applicazione ad un altro 
db/driver/ecc. allora implementa subito i servizi di connettività in 
modo astratto (JNDI, pool, altro), perché dopo avrai cose più importanti 
da fare"
Comunque rivendendola sotto questa luce la tua una-classe-una che fa il 
"lavoro sporco" di tirar su le connessioni è un modo perfettamente 
lecito di isolare l'applicazione dai dettagli implementativi. Occhio 
comunque a fare discorsi del tipo "Una libreria può avere bug, me lo 
faccio io" perché:
a) *tutti* i programmi hanno bug, a maggior ragione i tuoi perché ci 
lavori da solo (o almeno è quello che ho capito). Quanti programmatori 
*bravi* hanno lavorato a DBCP? Pensi di avere un'esperienza come la 
loro? Appunto ;)
b) la maaggior parte dei connection pool che ti ho segnalato sono 
open-source, quindi non c'è molto mistero intorno al loro funzionamento, 
ti pare?
Per finire aggiungo che tutto 'sto discorso per una applicazione 
mono-utente è il classico cannone per sparare ad una mosca... discorso 
diverso per le applicazioni multi-utente, dove sicuramente il metodo 
migliore è astrarre del tutto lo strato di connettività affidandosi a 
JNDI (app server o non app server) oppure a qualche IoC container tipo 
Spring, Pico, Guice e compagnia bella.
Mizzega che messaggio prolisso che ho scritto... basta devo avervi annoiati!
Saluti persistenti,


 falliti pure noi :-)))))) )
Shhhh, non spargere troppo in giro la voce che ho usato gli ejb 1.0 
altrimenti divento lo zimbello di tutti :)
Come disse Jack Beauregarde:
"– Proprio come ai bei tempi!
– I bei tempi non ci sono mai stati. "
                 (Il mio nome è Nessuno)


 Mizzega che messaggio prolisso che ho scritto... basta devo avervi annoiati!
Me, no di sicuro!
Grazie!
Ciao
--
Enos