The connection pool is created when the webapp is deployed. At that time, a number of Connections are pre-created, with that number being the pool's minimum size.
When the app requests a Connection, the pool pulls a Connection off of its list of Connections and wraps it in an object that serves as a façade Connection. It differs from the underlying Connection only in that its
close() method simply returns the Connection back to the Connection pool instead of disconnecting from the database. Thus, that Connection can be re-used.
Note that it is ABSOLUTELY ESSENTIAL that you close a Connection as soon as you possibly can. Holding it keeps other apps from being able to use it. And NEVER, EVER store it in a Session or Application object for continued use between requests!!!
If all of the Connections in a pool have been opened by requesting webapps, then the pool will create one or more new Connection objects to expand the pool. It will do that until the configured maximum pool sizee is reached, at which time, further Connection requests will fail (see paragraph above!)
The Connection pool lives for the lifetime of the webapp. It may shrink itself down to its nominal size over time, depending on how it is configured, but it will never drop below the minimum pool size.
One "gotcha" is that when the underlying Connections don't get used often enough, they may time out and be disconnected by the database server. In which case you may need to configure the Connection Pool to
test and refresh stale Connections so that the webapps can use them safely. The mechanism that sets that up may vary depending on the particular pool implementation and/or the database server.
And, no, I don't obfuscate my code. It's pointless. Back in olden days I used to disassemble software all the time and the lack of meaningful names made no difference to me. Back then it was legal, incidentally. And a lot easier than persuading Microsoft to make a 1-line change to one of their major program products.