✅ Short answer:
The connection pool (like HikariDataSource
, Tomcat DataSource
, etc.) should be destroyed when the web application is shutting down.
That means:
- When Tomcat (or another servlet container) undeploys your app,
- Or stops,
- Or reloads the application.
Otherwise:
- Database connections stay open → resource leak on database side.
- Eventually database runs out of connections → errors like “Too many connections”.
✅ How to destroy it properly?
You must close the connection pool inside a ServletContextListener
in the contextDestroyed()
method.
Here’s the right lifecycle:
Event | What to do |
---|---|
App startup (contextInitialized ) | Create connection pool and store it in ServletContext |
App shutdown (contextDestroyed ) | Close the connection pool safely |
✅ Example again (proper destruction):
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;
import com.zaxxer.hikari.HikariDataSource;
@WebListener
public class AppContextListener implements ServletContextListener {
private HikariDataSource dataSource;
@Override
public void contextInitialized(ServletContextEvent sce) {
dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("user");
dataSource.setPassword("pass");
// Save it in the ServletContext so servlets can use it
sce.getServletContext().setAttribute("DataSource", dataSource);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// Properly close the pool when the application shuts down
HikariDataSource ds = (HikariDataSource) sce.getServletContext().getAttribute("DataSource");
if (ds != null) {
ds.close(); // 🔥 Important: release all DB connections
}
}
}
✅ What happens when you call ds.close()
?
- All idle connections are closed.
- Active connections are closed after use.
- No new connections are accepted.
- The pool is safely shutdown.
In short: the application cleans up after itself like a good citizen.
✅ If you forget to close:
- Memory leak inside Tomcat or your server.
- Database keeps connections busy unnecessarily.
- Can cause deployment errors if you redeploy the app many times.
✅ Real-world checklist:
Thing | Should happen |
---|---|
During contextInitialized | Create + configure DataSource |
Save it to | ServletContext attributes |
During contextDestroyed | Fetch DataSource and call .close() |
After closing | No memory leaks, no DB leaks |
🌟 Visual Lifecycle:
App Startup
↓
ServletContextListener.contextInitialized()
↓
Create Connection Pool (DataSource)
↓
Servlets use connections from pool
↓
App Shutdown
↓
ServletContextListener.contextDestroyed()
↓
Close Connection Pool properly
✨ Final Reminder:
Connection
objects are borrowed and returned automatically (withtry-with-resources
).- But the pool itself must be manually closed once when the app ends.