Bonjour,

Je développe une application Web Java dans le serveur Tomcat avec une base de données MySQL 5.1, des pages JSP, Spring et Struts 1.3.

J'ai une difficulté avec la connexion DB. J'ai créé une classe DBConnection implémentant le design pattern Singleton pour récupérer la connexion DB. J'utilise un pool de connexion et je garde l'objet de connexion comme membre statique privé de la classe DBConnection. J'utilise cette classe, et l'objet Connection qui est fourni par le Connection Pool Tomcat dans des classes de la couche DB. J'utilise ces classes dans les JSP (qui incluent éventuellement d'autres JSP), et dans les controleurs Struts.

Le problème est que la classe DBConnection, l'objet Connection Pool, et la Connexion JDBC sont instanciés plusieurs fois (comme je le vois dans le log de chaque requête aux pages JSP).

Je me demande si c'est normal. Pour moi, l'objet DBConnection ne devrait être instancié qu'une fois dans la JVM, ainsi que le connection pool, comme j'ai utilisé le design pattern Singleton mais vu que c'est la première fois que j'utilise un connection pool, je ne suis pas très sûr.


Voici le code de la classe DBConnection:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
 
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
 
public class DBConnection {
	public static DataSource ds; // la source de données
	public static DBConnection dbconnection;
	protected static Connection conn;
 
	String connectionString;
 
	static String user;
	static String password;
	static String host;
	static String dbname;
	static String port;
 
	private DBConnection() {
	}
 
	public static DBConnection getInstance() throws Exception {
		if (DBConnection.dbconnection == null) {
			DBConnection.dbconnection = new DBConnection();
			log(Level.INFO, "DBConnection.dbconnection = new DBConnection();");
		}
		return DBConnection.dbconnection;
	}
 
	public Connection getConnection() throws Exception {
 
		if (DBConnection.dbconnection == null)
			throw new Exception("Singleton non initialisé");
		if (DBConnection.conn != null)
			return DBConnection.conn;
		else
			log(Level.INFO, "Connection == null");
		try {
			DBConnection.conn = getConnection2();
			// DBConnection.conn = getConnection3();
		} catch (Exception ex) {
			log(Level.SEVERE, "Erreur lors du chargement du dataSource");
			ex.printStackTrace();
			throw new Exception("Erreur lors du chargement du dataSource");
		}
		return conn;
 
		/*	
*/
 
	}
 
	private static Connection getConnection3() throws Exception {
		if (DBConnection.conn != null)
			return DBConnection.conn;
		Properties props = new Properties();
		try {
			String path = "\\WEB-INF\\dbconnection.properties";
			props.load(new FileInputStream(path));
 
			user = props.getProperty("user");
			password = props.getProperty("password");
			host = props.getProperty("host");
			port = props.getProperty("port");
			dbname = props.getProperty("dbname");
		}
 
		// catch exception in case properties file does not exist
 
		catch (IOException e) {
			log(Level.SEVERE,
					"Erreur : cannot retrieve properties file for db connection parameters");
			e.printStackTrace();
			log(Level.SEVERE,
					"Erreur : cannot retrieve properties file for db connection parameters");
		}
 
		try {
			String url = "jdbc:mysql://" + host + "/" + dbname;
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			DBConnection.conn = DriverManager.getConnection(url, user, password);
			log(Level.INFO, "Connection DB réussie");
		} catch (Exception e) {
			log(Level.INFO, "Echec de la connection DB");
		} finally {
		}
		return DBConnection.conn;
	}
 
	private static Connection getConnection2() throws Exception {
		if (DBConnection.ds == null)
			init();
		if (DBConnection.ds != null)
			return DBConnection.conn;
		return null;
	}
 
	public static void close() throws Exception {
		if (DBConnection.conn != null)
			try {
				DBConnection.conn.close();
				log(Level.INFO, "Déconnection DB réussie");
			} catch (Exception e) {
				log(Level.SEVERE, "Echec de la déconnection DB");
				e.printStackTrace();
				throw new Exception("Echec lors de la déconection");
			}
	}
 
	private static void init() throws Exception {
		try {
			// récupération de la source de donnée
			Context initCtx = new InitialContext();
			DBConnection.ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/dataSource");
			DBConnection.conn = DBConnection.ds.getConnection();
			log(Level.INFO, "DBConnection.ds.getConnection(); OK");
			} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("Erreur lors du chargement du dataSource");
		}
	}
 
	protected static void log(Level level, String message) {
		ConsoleHandler handler = new ConsoleHandler();
		Formatter formatter = new SimpleFormatter();
		handler.setFormatter(formatter);
		Logger logger = Logger.getLogger("DBConnection");
		logger.addHandler(handler);
		if (logger.isLoggable(level)) {
			logger.log(level, message);
		}
 
	}
}
Dans le log j'ai enregistré ceci :
Login submit
22-août-2009 0:24:42 steemploi.persistance.DBConnection log
INFO: DBConnection.dbconnection = new DBConnection();
22-août-2009 0:24:42 steemploi.persistance.DBConnection log
INFO: DBConnection.dbconnection = new DBConnection();
22-août-2009 0:24:42 steemploi.persistance.DBConnection log
INFO: Connection == null
22-août-2009 0:24:42 steemploi.persistance.DBConnection log
INFO: Connection == null
22-août-2009 0:24:42 steemploi.persistance.DBConnection log
INFO: Connection == null
22-août-2009 0:24:43 steemploi.persistance.DBConnection log
INFO: DBConnection.ds.getConnection(); OK
22-août-2009 0:24:43 steemploi.persistance.DBConnection log
INFO: DBConnection.ds.getConnection(); OK
22-août-2009 0:24:43 steemploi.persistance.DBConnection log
INFO: DBConnection.ds.getConnection(); OK
22-août-2009 0:24:43 steemploi.persistance.DBConnection log
INFO: DBConnection.ds.getConnection(); OK
22-août-2009 0:24:43 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:24:43 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:24:43 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:24:43 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:24:43 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
2 instanciation de DBConnection
4 instanciations (récupération?) de Connection


Lors du deuxième appel j'ai ceci:
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
22-août-2009 0:41:49 steemploi.persistance.Table log
INFO: steemploi.persistance.TableEtudiants : findById()
Est-ce que ça veut dire que Tomcat garde un objet pour les futures requêtes clients? Enfin ça a l'air de bien fonctionner finalement.

Finalement ça fonctionne.

J'avais un autre problème, avec cette classe DBConnection et les requêtes JSP. Faut-il fermer le connectionPool Tomcat après utilisation? A mon avis, non dans mon cas car le Connection Pool est apparemment gardé pour plusieurs requêtes HTTP et est sans doute libéré après un certain temps d'inutilisation.

Voilà, je n'avais pas trouvé de documentation à ce sujet et j'ai quand même réussi à le faire