> On 2025 Aug 15, at 23:00, Daniel Schwartz <d...@danielgschwartz.com> wrote:
> 
> Chuck,
> 
> Okay, here is the text of the attachment.


Thanks.

<snip/>


> Regarding your statement "What is more likely is that the GlassFish 
> connection pool simply initializes the configured minimum number of 
> connections on the first attempt to acquire a connection.", I have no idea 
> hat this means.


To quote from the GlassFish doc for the asadmin utility:

--steadypoolsize
The minimum and initial number of connections maintained in the pool. The 
default value is 8.

--maxpoolsize
The maximum number of connections that can be created. The default value is 32.

When the pool is first accessed by your web service code to acquire a 
connection, the pool creates steady-pool-size instances, not just the one your 
code is asking for.  The pool will maintain at least steady-pool-size 
connections (idle plus active) in the pool. Connections can be removed from the 
pool if they fail, but the pool will be replenished as needed to keep 
steady-pool-size around.

Also, there’s no evidence in the doc that 8 is the minimum value that can be 
set. If you’re lowering the maximum (max-pool-size), it must be set at least as 
large as steady-pool-size; setting both to one should find any connection leaks 
pretty quickly. (Looks like Robert Turner demonstrated that while I was writing 
this.)

  - Chuck


> Dan
> 
> From: Chuck Caldarale <n82...@gmail.com>
> Sent: Friday, August 15, 2025 11:39 PM
> To: Tomcat Users List <users@tomcat.apache.org>
> Subject: Re: [EXTERNAL EMAIL] How to access a REST service
> 
>> On 2025 Aug 15, at 22:03, Daniel Schwartz 
>> <d...@danielgschwartz.com<mailto:d...@danielgschwartz.com>> wrote: > > I 
>> think I found the answer. > > A few days ago, someone suggested that I try 
>> setting the Glassfish maximum pool size to 1 and see what happens.
> NkdkJdXPPEBannerStart
> Be Careful With This Message
> From (Chuck Caldarale 
> <n82...@gmail.com>)<https://godaddy1.cloud-protect.net/email-details/?k=k1&payload=53616c7465645f5f4a8adbed4b5cf7a587f5f4df537a8eaec1a2b42d4d58936018b1ed681a23d9919bf8332d2b6b61429feb03a72599510c1c3ab28d5aaddc506ec4d56aaa261fcb98bd9aad462cad1cc8e2c0a7c87426fd5ac7bd5b6e2701e483c6c0dabfa7863325d5e1cce43460a01fdb3123cef7a62998f33320b7ee6a504f58e005390e8ee17f0cc8754779156e61decfa830f679ecb7c1779d40b153b44dd3c8946f5c5040afad656b12d548292c93d680a4c9c588dd499f91f4d3fe02cd457cde8bab1d939f1dcbfe104966e4bccd617fa2cf6cf872584c675598f814ea3508244febcc34102818eff6415cdd>
> Learn 
> More<https://godaddy1.cloud-protect.net/email-details/?k=k1&payload=53616c7465645f5f4a8adbed4b5cf7a587f5f4df537a8eaec1a2b42d4d58936018b1ed681a23d9919bf8332d2b6b61429feb03a72599510c1c3ab28d5aaddc506ec4d56aaa261fcb98bd9aad462cad1cc8e2c0a7c87426fd5ac7bd5b6e2701e483c6c0dabfa7863325d5e1cce43460a01fdb3123cef7a62998f33320b7ee6a504f58e005390e8ee17f0cc8754779156e61decfa830f679ecb7c1779d40b153b44dd3c8946f5c5040afad656b12d548292c93d680a4c9c588dd499f91f4d3fe02cd457cde8bab1d939f1dcbfe104966e4bccd617fa2cf6cf872584c675598f814ea3508244febcc34102818eff6415cdd>
> Potential Impersonation
> The sender's identity could not be verified and someone may be impersonating 
> the sender. Take caution when interacting with this message.
> 
> NkdkJdXPPEBannerEnd
> 
> 
> 
>> On 2025 Aug 15, at 22:03, Daniel Schwartz 
>> <d...@danielgschwartz.com<mailto:d...@danielgschwartz.com>> wrote:
> 
>> 
> 
>> I think I found the answer.
> 
>> 
> 
>> A few days ago, someone suggested that I try setting the Glassfish maximum 
>> pool size to 1 and see what happens.  I reported back that in Glassfish the 
>> minimum pool size is 8, to which someone responded that this seems strange.  
>> I really didn't know.  But now I do.
> 
>> 
> 
>> Today I decided to run a test where I cleared out Glassfish so I could start 
>> from scratch.  I executed one REST request using the URL I posted recently, 
>> which returns a list of countries.  Then I looked at the Glassfish JDBC pool 
>> monitor.  A PDF of this is attached.
> 
> 
> 
> 
> 
> The list strips nearly all attachments, for safely reasons. You need to post 
> the text.
> 
> 
> 
> 
> 
>> You will see that it says the following:
> 
>> 
> 
>> 1. NumConnAcquired, 1 count, Number of logical connection
> 
>> 
> 
>> 2. NumConnReleased, 1 count, Number of logical connections released to the 
>> pool.
> 
>> 
> 
>> 3. NumConnCreated, 8 count, The number of physical connections that were 
>> created since the last reset.
> 
>> 
> 
>> 4. NumConnFree, 8count, The total number of free connections in the pool as 
>> of the last sampling.
> 
>> 
> 
>> I believe that this is why the minimum pool size is 8; each logical 
>> connection requires 8 physical connections.
> 
>> 
> 
>> This leads me to believe that this is why the number of connections in my 
>> connection pool is much larger than what one would expect.  Assuming that 
>> Tomcat only requires one connection object per query, this implies that 
>> Glassfish requires 8 times that amount.
> 
> 
> 
> 
> 
> I think that is extremely unlikely. What is more likely is that the GlassFish 
> connection pool simply initializes the configured minimum number of 
> connections on the first attempt to acquire a connection.
> 
> 
> 
> You can test this by making concurrent requests and seeing what happens to 
> the pool counters. Try inserting a delay in your code between opening a 
> connection and closing it; something like Thread.currentThread().sleep(10000) 
> would likely suffice. Then initiate independent requests from several browser 
> tabs in parallel; the 10-second delay should allow time for each request to 
> grab its own connection from the pool while the other requests are still 
> active.
> 
> 
> 
> 
> 
>> So, while a normal pool size for Tomcat might be 20 connections, in 
>> Glassfish this same activity would require 160 connections.
> 
>> 
> 
>> In any case, I'm now 100% sure that my program doesn't, and never did, have 
>> a memory leak.  I have modified my code according to Chris's 
>> recommendations, as this surely is good advice, but it hasn't changed the 
>> performance, since no exceptions were ever being thrown.
> 
> 
> 
> 
> 
> Did you apply the try-catch-finally pattern to all DB-related objects, such 
> as statements, prepared statements, and result sets?
> 
> 
> 
>  - Chuck
> 
> 
> 
> 
> 
>> It appears to me that Glassfish is performing normally according to its 
>> internal design, and there really is no problem as long as I keep the 
>> maximum pool size large enough.
> 
>> 
> 
>> What do you think?
> 
>> 
> 
>> Dan
> 
>> 
> 
>> -----Original Message-----
> 
>> From: Christopher Schultz 
>> <ch...@christopherschultz.net<mailto:ch...@christopherschultz.net>>
> 
>> Sent: Friday, August 15, 2025 1:07 PM
> 
>> To: users@tomcat.apache.org<mailto:users@tomcat.apache.org>
> 
>> Subject: Re: [EXTERNAL EMAIL] How to access a REST service
> 
>> 
> 
>> Dan,
> 
>> 
> 
>> The only reason we are all looking for resource leaks (technically not 
>> memory leaks, but leaks nonetheless) is because it's the best explanation 
>> for why your connection pool seems to be running dry.
> 
>> 
> 
>> I don't think that switching to Tomcat (or TomEE) is going to make any 
>> difference.
> 
>> 
> 
>> -chris
> 
>> 
> 
>> On 8/15/25 12:33 PM, Daniel Schwartz wrote:
> 
>>> 
> 
>>> 
> 
>>> -----Original Message-----
> 
>>> From: Christopher Schultz 
>>> <ch...@christopherschultz.net<mailto:ch...@christopherschultz.net>>
> 
>>> Sent: Friday, August 15, 2025 12:18 PM
> 
>>> To: users@tomcat.apache.org<mailto:users@tomcat.apache.org>
> 
>>> Subject: Re: [EXTERNAL EMAIL] How to access a REST service
> 
>>> 
> 
>>> Daniel,
> 
>>> 
> 
>>> On 8/15/25 12:49 AM, Daniel Schwartz wrote:
> 
>>>> Robert (and all),
> 
>>>> 
> 
>>>> I will work on answers your various questions.  However, I decided to 
>>>> first explore the comment (by someone) that a servlet can "swallow" an 
>>>> exception, which I take to mean that it can throw an exception without 
>>>> reporting the exception or terminating the program.
> 
>>>> 
> 
>>>> I have this system running on a PC identified as localhost. The test URL 
>>>> is:
> 
>>>> 
> 
>>>> https://urldefense.proofpoint.com/v2/url?u=http-3A__localhost-3A8080_
> 
>>>> H
> 
>>>> olidaysRESTJSON-2D1.0-2DSNAPSHOT_webresources_holidaysandevents_count
> 
>>>> r
> 
>>>> ies&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=AbCalLxz
> 
>>>> o
> 
>>>> pgQUG9LLcXdB80OM-GtDfItX76RMxNYqz4&m=NKm1FUayvDzFHyhbqCI0JR32OpW1rfTe
> 
>>>> d
> 
>>>> HFkAoC_xT6Cjqt4-wsVFtYKPtR38vFY&s=4BYNb88ZN6WvyMyyZcR1FyT6Jg-qa4JSDa9
> 
>>>> P
> 
>>>> xsSFgB4&e=
> 
>>>> 
> 
>>>> I ran two tests.  First, I wrote in code to throw an SQL exception, which 
>>>> did get caught in my catch clause, which printed out some messages and a 
>>>> stack trace.  The web browser showed the retrieved list of countries, but 
>>>> nothing else.
> 
>>>> 
> 
>>>> Second, I replaced the line that throws the SQL exception by one that 
>>>> tries to do a division by zero.  This of course was not caught, but it did 
>>>> print out a stack trace and reported a 505 error in the browser, and the 
>>>> program did terminate.
> 
>>>> 
> 
>>>> I take this to mean that exceptions are not being "swallowed" by my 
>>>> program.  When/if an exception occurs, there is definitely some indication 
>>>> of this, either in the server.log or the browser.  Because I have never 
>>>> seen either of these actions, I'm fairly sure that my program is not 
>>>> throwing exceptions and all database connections are being closed 
>>>> immediately after they are used, i.e., no memory leaks in this respect.
> 
>>>> 
> 
>>>> The actual code fragments and outputs are copied below.
> 
>>>> 
> 
>>>> ----------------------------------------------------------------
> 
>>>> The code that throws the SQL exception
> 
>>>> ----------------------------------------------------------------
> 
>>>>     @GET
> 
>>>>     @Path("/countries")
> 
>>>>     @Produces(MediaType.APPLICATION_JSON)
> 
>>>>     public String getJsonCountries() {
> 
>>>>         if (TempDataStorage.countryList == null) {
> 
>>>>             Connection connection = null;
> 
>>>>             try {
> 
>>>>                 connection = dataSource.getConnection();
> 
>>>>                 System.out.println("countries connection has been opened");
> 
>>>>                 TempDataStorage.countryList = 
>>>> GetCountryList.doIt(connection);
> 
>>>>                 throw new SQLException("testing sql exception");
> 
>>>> //                connection.close();
> 
>>>> //                System.out.println("countries connection has been 
>>>> closed");
> 
>>>>             } catch (SQLException e) {
> 
>>>>                 System.out.println(e);
> 
>>>>                 System.out.println("catching sql exception");
> 
>>>>                 if (connection != null) {
> 
>>>>                     try {
> 
>>>>                         connection.close();
> 
>>>>                     } catch (SQLException ex) {
> 
>>>>                         System.out.println(ex);
> 
>>>>                     }
> 
>>>>                 }
> 
>>>>             }
> 
>>>>         }
> 
>>> 
> 
>>> 100% connection leak every time, guaranteed.
> 
>>> 
> 
>>> You are never closing the connection, because it's been commented out.
> 
>>> Perhaps this was just for testing, because I see you are throwing an 
>>> exception.
> 
>>> 
> 
>>> DGS: When I put in the throw statement, I had to comment out those two 
>>> lines because the Java compiler complains that they are unreachable.  This 
>>> was just to test for what would happen if an SQL exception was thrown, in 
>>> which case, yes, there will be a memory.  The point is that my program 
>>> never throws SQL exceptions, because if it did, I would know about it.
> 
>>> 
> 
>>> The conn.close() *MUST* be in a finally {} block. Do not put it in the try 
>>> block. Do not put it in the catch block. Always put it in the finally block.
> 
>>> 
> 
>>> DGS: Sounds like good advice.  I'll do this and see if it makes a 
>>> difference.
> 
>>> 
> 
>>>> ------------------------------------------------------------------
> 
>>>> The output in the server.log file
> 
>>>> ------------------------------------------------------------------
> 
>>>> [2025-08-14T23:34:42.019-0400] [glassfish 4.1] [INFO] [] [] [tid: 
>>>> _ThreadID=40 _ThreadName=Thread-8] [timeMillis: 1755228882019] 
>>>> [levelValue: 800] [[
> 
>>>>   countries connection has been opened]]
> 
>>>> 
> 
>>>> [2025-08-14T23:34:42.022-0400] [glassfish 4.1] [INFO] [] [] [tid: 
>>>> _ThreadID=40 _ThreadName=Thread-8] [timeMillis: 1755228882022] 
>>>> [levelValue: 800] [[
> 
>>>>   java.sql.SQLException: testing sql exception
> 
>>>>  at
> 
>>>> com.worldholidaysandevents.restjsonwebservice.HolidaysRESTJSONResourc
> 
>>>> e
> 
>>>> .getJsonCountries(HolidaysRESTJSONResource.java:54)
> 
>>>> 
> 
>>>>         ... stack trace ...
> 
>>>> 
> 
>>>> [2025-08-14T23:34:42.022-0400] [glassfish 4.1] [INFO] [] [] [tid: 
>>>> _ThreadID=40 _ThreadName=Thread-8] [timeMillis: 1755228882022] 
>>>> [levelValue: 800] [[
> 
>>>>   catching sql exception]]
> 
>>> 
> 
>>> ... and the server does not crash. You can make any request without 
>>> restarting Glassfish, right?
> 
>>> 
> 
>>>> ----------------------------------------------------------------
> 
>>>> The code that divides by zero
> 
>>>> ----------------------------------------------------------------
> 
>>>>     @GET
> 
>>>>     @Path("/countries")
> 
>>>>     @Produces(MediaType.APPLICATION_JSON)
> 
>>>>     public String getJsonCountries() {
> 
>>>>         if (TempDataStorage.countryList == null) {
> 
>>>>             Connection connection = null;
> 
>>>>             try {
> 
>>>>                 connection = dataSource.getConnection();
> 
>>>>                 System.out.println("countries connection has been opened");
> 
>>>>                 TempDataStorage.countryList = 
>>>> GetCountryList.doIt(connection);
> 
>>>>                 float something = 1/0;
> 
>>>>                 connection.close();
> 
>>>>                 System.out.println("countries connection has been closed");
> 
>>>>             } catch (SQLException e) {
> 
>>>>                 System.out.println(e);
> 
>>>>                 System.out.println("catching sql exception");
> 
>>>>                 if (connection != null) {
> 
>>>>                     try {
> 
>>>>                         connection.close();
> 
>>>>                     } catch (SQLException ex) {
> 
>>>>                         System.out.println(ex);
> 
>>>>                     }
> 
>>>>                 }
> 
>>>>             }
> 
>>>>         }
> 
>>> 
> 
>>> 
> 
>>> 100% connection leak every time, guaranteed.
> 
>>> 
> 
>>> You are never closing the connection, because your code is throwing an 
>>> uncaught exception (divide by zero) Perhaps this was just for testing, 
>>> because I see you are intentionally dividing by zero.
> 
>>> 
> 
>>> DGS: Right.  This was to test for what would happen if a non-SQL exception 
>>> were thrown, i.e., one that is not caught in the catch clause.   This 
>>> created a 505 error and the program quit running.  Here the point is that, 
>>> if something like this were to happen, I would certainly know about it, and 
>>> it has never happened, so no memory leak is being created in this way.
> 
>>> 
> 
>>> The conn.close() *MUST* be in a finally {} block. Do not put it in the try 
>>> block. Do not put it in the catch block. Always put it in the finally block.
> 
>>> 
> 
>>> DGS: Thanks again.  I'll do this and see if it makes any difference in the 
>>> connection pooling.
> 
>>> 
> 
>>> -chris
> 
>>> 
> 
>>> 
> 
>>> ---------------------------------------------------------------------
> 
>>> To unsubscribe, e-mail: 
>>> users-unsubscr...@tomcat.apache.org<mailto:users-unsubscr...@tomcat.apache.org>
> 
>>> For additional commands, e-mail: 
>>> users-h...@tomcat.apache.org<mailto:users-h...@tomcat.apache.org>
> 
>>> 
> 
>>> 
> 
>>> ---------------------------------------------------------------------
> 
>>> To unsubscribe, e-mail: 
>>> users-unsubscr...@tomcat.apache.org<mailto:users-unsubscr...@tomcat.apache.org>
> 
>>> For additional commands, e-mail: 
>>> users-h...@tomcat.apache.org<mailto:users-h...@tomcat.apache.org>
> 
>>> 
> 
>> 
> 
>> 
> 
>> ---------------------------------------------------------------------
> 
>> To unsubscribe, e-mail: 
>> users-unsubscr...@tomcat.apache.org<mailto:users-unsubscr...@tomcat.apache.org>
> 
>> For additional commands, e-mail: 
>> users-h...@tomcat.apache.org<mailto:users-h...@tomcat.apache.org>
> 
>> 
> 
>> 
> 
>> ---------------------------------------------------------------------
> 
>> To unsubscribe, e-mail: 
>> users-unsubscr...@tomcat.apache.org<mailto:users-unsubscr...@tomcat.apache.org>
> 
>> For additional commands, e-mail: 
>> users-h...@tomcat.apache.org<mailto:users-h...@tomcat.apache.org>
> 
> 
> 
> 
> 
> ---------------------------------------------------------------------
> 
> To unsubscribe, e-mail: 
> users-unsubscr...@tomcat.apache.org<mailto:users-unsubscr...@tomcat.apache.org>
> 
> For additional commands, e-mail: 
> users-h...@tomcat.apache.org<mailto:users-h...@tomcat.apache.org>
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to