> 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