You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Shawn Heisey <ap...@elyograg.org> on 2018/03/28 02:26:51 UTC

Getting all JDBC configs from the context

This is what the code in our application looks like that gets a
datasource object from the context:

  Context initContext = new InitialContext();
  Context envContext  = (Context)initContext.lookup("java:/comp/env");
  DataSource ds = (DataSource)envContext.lookup("jdbc/REDACTED");

I would like to write a logging thread that can get ALL of the
datasource objects from the context, and for types that it knows, cast
them to the appropriate object to log the active/idle connection counts.

This paste is the idea I've thought of for initializing and creating
this logging thread:

https://paste.apache.org/QcbE

The "log" variable is an slf4j Logger object.

Does that code look like it'll work, if we run it once at system
startup?  It doesn't have any errors in my IDE.  Which is not always an
indication of success!

Thanks,
Shawn


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


Re: Getting all JDBC configs from the context

Posted by Shawn Heisey <ap...@elyograg.org>.
On 3/28/2018 1:18 PM, Christopher Schultz wrote:
> Don't forget to terminate the thread (or ExecutorService) when the
> application is shutting-down, of you'll have a ClassLoader (and a a
> huge memory) leak.

Here's a new paste, that I think addresses the thread leak problem.

https://paste.apache.org/rqaX

I've created a listener class that handles startup and shutdown.

Thanks,
Shawn


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


Re: Getting all JDBC configs from the context

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Shawn,

On 3/29/18 12:00 PM, Christopher Schultz wrote:
> Shawn,
> 
> On 3/28/18 4:42 PM, Shawn Heisey wrote:
>> On 3/28/2018 1:18 PM, Christopher Schultz wrote:
>>>> I would like to write a logging thread that can get ALL of
>>>> the datasource objects from the context, and for types that
>>>> it knows, cast them to the appropriate object to log the 
>>>> active/idle connection counts.
>>> 
>>> It might be easier to do this via JMX.
> 
>> Perhaps.  But then I have to figure out how to get the program 
>> started with the sysprops that enable remote JMX.  The system
>> has no GUI, and we don't have any X-Windows infrastructure, so
>> running JDK tools locally on the Linux server is challenging.
>> Not impossible, just requires me to set up things that I don't
>> already have, to do X forwarding over SSH. With the logging
>> thread idea, we just need to update code, recompile, and
>> redeploy.
> 
> I don't bother with any of that garbage. I use Tomcat's Manager 
> application and the JMXProxyServlet. It's an HTTP-to-JMX bridge,
> so your client just has to speak HTTP.
> 
> I use it along with a Nagios plug-in to fetch things like (wait
> for it) DataSource pool stats :)

Have a look at:
http://people.apache.org/~schultz/ApacheCon%20NA%202016/Monitoring%20Apa
che%20Tomcat%20with%20JMX.pdf

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlq9JZ8ACgkQHPApP6U8
pFjf1A//ctmoJ0Vm8dO+2jyGaUIGIge8teeUd+IeyqH5AQ5mZ1g9mVrLT53Gx0B2
3DKV9XpcaD91sCK/0Xs9su63+IHZNKNvgxQASriQD/iZ4Ebbkv8aLaZcEfR5fBJC
cHU0n7DSKgDtX6vj3gSUb+A4KuNndbsEiXck9nSBxSr57OCJA4TEuTp6QTyXmekO
7Dtv1u0CpljPK4XxrMHJiCTsM7WSdEJQnSRbMQehQTF0fNLNk+wvaLosojBnLdJn
/x4naQh0tHTjyq96+oDIRRhSCFvHqQM1X7/n68eibAEHd2jvSyagleBVVBDyDSzj
bUzGaATkc7P6jkJiTm5nsIE6zrC/AoJcDaSamz5pXj2FTcdOTd9mSQ7Q+roQ70c/
g5VgG+FnZNqQHYG6tToqJiZ3DvPtlxp1o07psCFUOoSc3FRbK2+a0eiUCSbaZbJK
T3kdrN+zZke44EO8JKFtEh45bFF8M9mYeadLfuCgHM2G5T+8ni4HkOX5KPR0PTg7
FqdMk56n+wwEjRV8VDGLo3vASmRKT9DbUYsLpIdGFtAaHuuviPJqVgldd2eukKfm
5LhaB7mfAmk5i5DfBL9lZWqCa+SiGwe/MN5BN1BtVo1zxoRlnG3xdb411V/V69bX
VQFLAcNFV5Y5fMdDHI5eR4cRHF4W/bj72eRZgtLZRmh22fphzs0=
=CRLc
-----END PGP SIGNATURE-----

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


Re: Getting all JDBC configs from the context

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Shawn,

On 3/30/18 5:30 PM, Shawn Heisey wrote:
> On 3/30/2018 11:38 AM, Christopher Schultz wrote:
>> No. In Java, the "class" is defined by the ClassLoader (which
>> loaded it) plus the fully-qualified class name. It's entirely
>> possible in
> 
> The subtleties of classloader-related problems make my head hurt.
> :)
> 
>> If objects a and b were instantiated using different
>> ClassLoaders (which independently loaded the class). This would
>> only happen if you did this:
>> 
>> 1. Copy tomcat-dbcp.jar into your app's WEB-INF/lib directory 2.
>> Let Tomcat create the DataSource (loaded from its ClassLoader) 3.
>> Instantiated a new DataSource yourself (loaded from your
>> webapp's ClassLoader)
>> 
>> You'd have to take care to build against Tomcat, but deploy
>> without adding Tomcat JARs to your application.
> 
> I don't know how much I can influence the deployment process, but
> if I see any issues, I will discuss it with development.  Issues
> will probably be apparent pretty quickly, though.  I am generally
> aware that it's a bad idea to have the same jar (especially if
> they're different versions) loaded more than once.
> 
> Would I be right in thinking that subtle problems will either
> cause compile errors or throw ClassCastException, with the latter
> being much more likely?

The biggest risk is trying to build WITH Tomcat libraries and trying
to deploy WITHOUT them. Anyone can toss "catalina" in as a dependency
to their project using Maven but not everyone knows how to tell Maven
that the catalina.jar file shouldn't be bundled with the application.
For example, I have no idea how to do that. Then again, I have no idea
how to use Maven at all.

If you compile against Tomcat and also make sure not to bundle
catalina.jar with your application, then you should be okay. I just
think there are better ways to skin this particular cat.

> I thought I had ensured that if the runflag goes false, the thread 
> should only run for a maximum of one second before it exits.

Sorry, I missed the "runFlag.get()". I ignored it because it's not a
simple flag but an AtomicInteger and got lost in the noise of the code
(in my eyes).

> Is that a case of premature optimization? :)

I'm not sure. In my case, I use a crontab-scheduled line of curl that
logs directly to my monitoring system. No Java code required, no extra
threads, etc. Yes, you have to deploy the Manager application. But
now, I can instrument anything available via JMX just by adding more
lines to my crontab. If you want to check your heap health, or
session-count, or anything like that, you might be tempted to
duplicate your existing code and replace the "logging" with logging
something else. That requires a re-build and redeploy. With JMX, you
just ask for a different address and get different data.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlrCLzQACgkQHPApP6U8
pFj4XBAAlXRgBZAfELarYHhqRmNOitV+fdHdVdPF8xPcYl2/TkOsi7CiN3aQwAFo
tBlxFyleNApjW7wAm7nr9+u13VKxVlWwRbAKak0exW8xfzkNGRZGDq2aSAxooeMZ
Ckl5HSQ3srpzhkTSBhd44pxbvae5JwlKAvtUqAcFWUbl1byAwe4SsMVcdQEPv6bd
ge5k/wB9TYgcAFgQTVIeGAR2K7HXhM9HFV1QFG/qJL3eul2YvdafMtHU4ly+0AHW
QpBHNv0TQl/MZM1KFoKn5Y1uMKrY1qCZRccQBt5KTto55zHXXZXOiNGXacZ9pEbn
/5KvmAVhKZHjzFSBpS8RtDu04HIFVL0fYA/eySWTdYem2wAtSN23ZfZ9NFRwKYMW
TE0MAOO4naWtE6mGUrgZuGIx4j3HSVHg2lh9k/sZjMM0vpsP43YMXL2aHetUp+Vc
fw7L1t0O0m7Mz0s7ow9EmF5obZf5euaXa2gXJOd4Yy6dd8OTaFqQFK6jVw+R0aq5
OVjAXI/t5uJLu1XRQlNGDxQ9xw+L00j57lpqA8+xjxgVaOtWy5KxyDcfDIwEoNAj
LxZ+fktW6HUBonTYwrIfjBBMO0zaNq/gX821KJS2Z40Ls9j4FLuoezXkVUGkvpqv
2Rr+KXD5aVaY0+fNeVotDgSOIUHcucEYJosnqR60e/3vSKL6Q7Q=
=QRoQ
-----END PGP SIGNATURE-----

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


Re: Getting all JDBC configs from the context

Posted by Shawn Heisey <ap...@elyograg.org>.
On 3/30/2018 11:38 AM, Christopher Schultz wrote:
> No. In Java, the "class" is defined by the ClassLoader (which loaded
> it) plus the fully-qualified class name. It's entirely possible in

The subtleties of classloader-related problems make my head hurt. :)

> If objects a and b were instantiated using different ClassLoaders
> (which independently loaded the class). This would only happen if you
> did this:
>
> 1. Copy tomcat-dbcp.jar into your app's WEB-INF/lib directory
> 2. Let Tomcat create the DataSource (loaded from its ClassLoader)
> 3. Instantiated a new DataSource yourself (loaded from your webapp's
> ClassLoader)
>
> You'd have to take care to build against Tomcat, but deploy without
> adding Tomcat JARs to your application.

I don't know how much I can influence the deployment process, but if I
see any issues, I will discuss it with development.  Issues will
probably be apparent pretty quickly, though.  I am generally aware that
it's a bad idea to have the same jar (especially if they're different
versions) loaded more than once.

Would I be right in thinking that subtle problems will either cause
compile errors or throw ClassCastException, with the latter being much
more likely?

> I would just search Google for "how to use java executor services" or
> something similar.

Thanks for the tip.

> It's more fleshed-out, but I still think it's more code than
> necessary. You also have the problem that if you want to shut-down
> your application, Tomcat will claim you have a memory leak because
> that thread will continue to run during the 5-minute delay.

I thought I had ensured that if the runflag goes false, the thread
should only run for a maximum of one second before it exits.

So I looked over the code again.  The runflag is checked on every loop
of the 'wait' code, which only sleeps one second.  The time required for
program flow (if, while, try/catch, calculations, etc) should be too
small to worry about.  The runflag is also checked on the outer loop.

Because I placed the wait at the beginning of the outer loop, the thread
will output logs just before it quits.  That's easy enough to fix.

> The point is, yes: you can do all of this and it will work. But if you
> use existing code, you can rely on code that is probably
> better-written and maintained (no offense intended) and focus your OWN
> code on what you NEED to get done, instead of mixing it all up with
> the plumbing of waiting, launching threads, checking for the "done"
> flag, etc.

If I were doing a complex multi-thread highly concurrent task, I would
probably be a lot more concerned about the plumbing I'm using, and
looking to let other libraries handle almost everything.  This idea's
simple.  One thread that spits a few log lines every five minutes.

I'm occasionally guilty of premature optimization when I come up with a
code design... spending hours or days thinking about how to best write
some bit of code that makes the whole idea tick.  But I *TRY* not to
engage in that activity.  Sometimes a paper plane can do the job
wonderfully, and the super spy jet that's invisible to radar and breaks
the sound barrier will take too much time and effort.  If you're an
aerospace engineer, you might have a different opinion. :)

I almost used a ten millisecond value for the Thread.sleep call in the
thread's inner loop.  But then I thought about the fact that it would
run that loop one hundred times more frequently, and decided that a
longer sleep value was probably a lot more efficient.  Nobody's going to
care if they have to wait a few hundred more milliseconds before they
get another series of logs.  Is that a case of premature optimization? :)

I do tend to agree that letting somebody else bash their head against
the difficult problems and come up with optimized solutions is a great
idea.  No reason to re-invent every wheel you need -- third-party
dependencies and well-written features built into the language or the
core libraries are a lifesaver.

Thanks,
Shawn


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


Re: Getting all JDBC configs from the context

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Shawn,

On 3/29/18 3:29 PM, Shawn Heisey wrote:
> On 3/29/2018 10:00 AM, Christopher Schultz wrote:
>> I don't bother with any of that garbage. I use Tomcat's Manager 
>> application and the JMXProxyServlet. It's an HTTP-to-JMX bridge,
>> so your client just has to speak HTTP.
> 
> I'm not sure that the manager application is active on our
> install.

No sane production install should have it available unless (a) it's
necessary and (b) it's been enabled "with care" (e.g. locked-down).

We operate ours in a localhost-only configuration.

>> You may also run into ClassLoader problems where BasicDataSource
>> (as loaded by your ClassLoader) != BasicDataSource (as
>> instantiated by Tomcat).
> 
> Are these problems mitigated by my usage of the fully qualified
> class name in the object declaration and the cast?

No. In Java, the "class" is defined by the ClassLoader (which loaded
it) plus the fully-qualified class name. It's entirely possible in
Java to have this:

     Object a = [something];
     Object b = [something];

     System.out.println(a.getClass().getName());
     System.out.println(b.getClass().getName());
     System.out.println(a.getClass().isAssignableFrom(b.getClass()));

print this:
org.apache.tomcat.dbcp.dbcp.BasicDataSource
org.apache.tomcat.dbcp.dbcp.BasicDataSource
false

If objects a and b were instantiated using different ClassLoaders
(which independently loaded the class). This would only happen if you
did this:

1. Copy tomcat-dbcp.jar into your app's WEB-INF/lib directory
2. Let Tomcat create the DataSource (loaded from its ClassLoader)
3. Instantiated a new DataSource yourself (loaded from your webapp's
ClassLoader)

You'd have to take care to build against Tomcat, but deploy without
adding Tomcat JARs to your application.

> That part of the code actually came from one of our developers ...
> I probably would have imported the class and used the bare class
> name.
The compiled code would be identical in either case. "Imports" are
just a shorthand way to tell the compiler what the FQCN is for the
classes you actually reference in your code.

> Maybe I should use getCanonicalName instead of getName on the 
> DataSource object.  When I can finally run the code for the first 
> time, I'll have a better idea of whether I need to make any
> changes.
Using the class's canonical name won't change anything.

>> Have a look. It will probably be (slightly) more efficient than
>> the code you wrote, and hey, you'll have less code to babysit. It
>> also gives you trivial "shutdown" semantics...
> 
> I will do my own searching later, but do you happen to know of some
> good documentation that covers the basics of implementing
> ExecutorService?

I would just search Google for "how to use java executor services" or
something similar.

>> ServletContextListener is the way to go. In fact, you should 
>> probably be using a ServletContextListener to *launch* this
>> thread in the first place. So, in your init() method,
>> create+launch the thread (or ExecutorService), and in the
>> destroy() method, shut it all down.
> 
> You may have noticed the new reply where I included a paste for
> new code, using ServletContextListener.  It's now *complete* code,
> instead of a fragment.

It's more fleshed-out, but I still think it's more code than
necessary. You also have the problem that if you want to shut-down
your application, Tomcat will claim you have a memory leak because
that thread will continue to run during the 5-minute delay.

If you used an ExecutorService (which just runs Runnables), you could
instantiate the service and schedule a series of jobs beginning in 5
minutes and executing every 5 minutes after that.

On app shutdown, you shut-down the ExecutorService and cancel all
fuure jobs immediately, so there is no waiting-around for the thread
to stop or anything.

(You could also simulate this yourself by adding a check to your
5-minute-loop that also checks to see if "runFlag" has been tripped.)

The point is, yes: you can do all of this and it will work. But if you
use existing code, you can rely on code that is probably
better-written and maintained (no offense intended) and focus your OWN
code on what you NEED to get done, instead of mixing it all up with
the plumbing of waiting, launching threads, checking for the "done"
flag, etc.

Hope that helps,
- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlq+dgsACgkQHPApP6U8
pFiP8g/7BArFaIXH0tnIOv2b6PVNrWbWw9vaF0YlHe4/DUE6NsPRtkyRY1I/9TuL
QULtVRFAPOAzVLQkEIruelNscGnSvXOokEvpkRF1ClekBLB8pr67iCt1SFUTY0ce
ANhfSKD0BSRa80P4obrmWTKFVktx3L7Uf1v8Hj1aFa+mLdSNV5B4smwRt+W7k9WK
UQb6wt68nhpHQjePksJvh2/w3rc4SKVKyWFVWaWImZ9yJgTXTtTFD5TEcVOGZA6I
1RsO9tvdu3O86tSIwhb1pOvqbMYt8uVjIsDEG24vHXw7dr63TVPW2ByHRBAP8xn6
aggOYLwitx2J+k3Dj03cgMEfajWmuIqiDHcRkk1G2Dc5Zr8CwXqXGZfhzCzY64AI
+Uu2zgOAx8QNNcw0RnGKRdLGsuJLPoA1Vd0oc/NRv3qr1W7DJOODbkOFG/XUZwqT
UKji+xBORjjbL0uW7lDQ/Bz1YQdSaNZqWZBjyURlK/51aQJBmFAuI+m+W6WoI81A
lNVO3L+vvkZD93SCKpHeCn/j+oaap2Faxhhg75g0ZeQ6lnuVKbnn/WDw9h8G/1+c
MXqzvgqy2uOvxxxxf7efXYayWtjcMoklUCds+ihrrwq3d3ZQd7GF9BhMwpP3OlzH
m2pNObVM4o0SvwU+oSVNN670aUX2dwJTijAfmsM5kDb/2Tot+rg=
=6zuk
-----END PGP SIGNATURE-----

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


Re: Getting all JDBC configs from the context

Posted by Shawn Heisey <ap...@elyograg.org>.
On 3/29/2018 10:00 AM, Christopher Schultz wrote:
> I don't bother with any of that garbage. I use Tomcat's Manager
> application and the JMXProxyServlet. It's an HTTP-to-JMX bridge, so
> your client just has to speak HTTP.

I'm not sure that the manager application is active on our install.  The
load balancer doesn't mention it, and I haven't seen it in the
Apache/AJP config either.  I think that in order for it to be enabled
and NOT be a potential security risk, access to it would need to be
strictly controlled.  I tried accessing /manager paths in various ways
(even direct to tomcat, bypassing haproxy and apache) and none of those
requests worked.  I didn't find any immediate evidence that it's enabled
under another context path either.  But I am the first to admit that I
am not very familiar with configuring Tomcat!

> You may also run into ClassLoader problems where BasicDataSource (as
> loaded by your ClassLoader) != BasicDataSource (as instantiated by
> Tomcat).

Are these problems mitigated by my usage of the fully qualified class
name in the object declaration and the cast?  That part of the code
actually came from one of our developers ... I probably would have
imported the class and used the bare class name.  Maybe I should use
getCanonicalName instead of getName on the DataSource object.  When I
can finally run the code for the first time, I'll have a better idea of
whether I need to make any changes.

> Have a look. It will probably be (slightly) more efficient than the
> code you wrote, and hey, you'll have less code to babysit. It also
> gives you trivial "shutdown" semantics...

I will do my own searching later, but do you happen to know of some good
documentation that covers the basics of implementing ExecutorService?

> ServletContextListener is the way to go. In fact, you should
> probably be using a ServletContextListener to *launch* this thread in
> the first place. So, in your init() method, create+launch the thread
> (or ExecutorService), and in the destroy() method, shut it all down.

You may have noticed the new reply where I included a paste for new
code, using ServletContextListener.  It's now *complete* code, instead
of a fragment.

Thanks,
Shawn


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


Re: Getting all JDBC configs from the context

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Shawn,

On 3/28/18 4:42 PM, Shawn Heisey wrote:
> On 3/28/2018 1:18 PM, Christopher Schultz wrote:
>>> I would like to write a logging thread that can get ALL of the 
>>> datasource objects from the context, and for types that it
>>> knows, cast them to the appropriate object to log the
>>> active/idle connection counts.
>> 
>> It might be easier to do this via JMX.
> 
> Perhaps.  But then I have to figure out how to get the program
> started with the sysprops that enable remote JMX.  The system has
> no GUI, and we don't have any X-Windows infrastructure, so running
> JDK tools locally on the Linux server is challenging.  Not
> impossible, just requires me to set up things that I don't already
> have, to do X forwarding over SSH. With the logging thread idea, we
> just need to update code, recompile, and redeploy.

I don't bother with any of that garbage. I use Tomcat's Manager
application and the JMXProxyServlet. It's an HTTP-to-JMX bridge, so
your client just has to speak HTTP.

I use it along with a Nagios plug-in to fetch things like (wait for
it) DataSource pool stats :)

>> Since you already have a compile-time dependency upon Tomcat,
>> there's no need to do class-name matching. Instead, just use
>> "instanceof" as before:
> 
> I did the code that way so that I can handle any type of
> DataSource object, even if we change our pool configurations, just
> by adding stanzas to the switch.  And the default case logs the
> class name if it's not handled explicitly, so I know what to add or
> change.  I went looking for a way to write a switch statement that
> utilizes instanceof, didn't find anything.

You're right, you can't. But string-comparisons are fragile.

You may also run into ClassLoader problems where BasicDataSource (as
loaded by your ClassLoader) != BasicDataSource (as instantiated by
Tomcat).

>> Instead of running a single thread that goes to sleep, maybe
>> consider using a ScheduledExecutorService with a simpler runnable
>> object that just logs the status a single time.
> 
> Sounds like a good idea.  That I have absolutely no idea how to 
> implement.  I used the hammer I know. :)

:)

Have a look. It will probably be (slightly) more efficient than the
code you wrote, and hey, you'll have less code to babysit. It also
gives you trivial "shutdown" semantics...

>> Don't forget to terminate the thread (or ExecutorService) when
>> the application is shutting-down, of you'll have a ClassLoader
>> (and a a huge memory) leak.
> 
> I did think about that, but I wasn't sure how to detect a shutdown.
> Is there something available that handles it easily and reliably
> with only a small code change?  Just now, I found the following
> page when I went looking for how to detect that (independent of the
> JVM shutting down):
> 
> http://www.deadcoderising.com/execute-code-on-webapp-startup-and-shutd
own-using-servletcontextlistener/

A
> 
ServletContextListener is the way to go. In fact, you should
probably be using a ServletContextListener to *launch* this thread in
the first place. So, in your init() method, create+launch the thread
(or ExecutorService), and in the destroy() method, shut it all down.

> I think I could use this to create the thread on application
> startup as well as making sure it shuts down cleanly.  It would
> mean that I can just create a new class for one of our applications
> and edit a config file, instead of monkeying with other people's
> code.

That's the idea.

> It's very encouraging to me that you picked up on the lack of
> shutdown handling.  It means I've got more than a sliver of your
> attention!

:)

- -chris

-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlq9DawACgkQHPApP6U8
pFgLQRAAu5cfpWcgkL7Di/HHuot5r+Hi7XL6PAPbi28GYiVbszLfh3QRaZVhcFx4
AANpVYs4n0y5W1sJZzG8lXdvokm3dY00zWkLTOzU9MW7kuh0b8eV3RXwlyA7dBcz
U+ndeU5o6iqvK7w6Z3kDHvSYbl28YEKz1Ff8SmdQ+GlEUOCSC9OcJlNoQ+dgpSAS
LGW20RHvhk1+j7au4ebMBZpvyh6rsUSdbTt0s6xbqE7raoYPUgQZS2ZmB9iHgGP5
o20Rgaf7F2MQ+LzDBg2uJPMvH0x5QUb3FrDJGgQCRfVJwqeSPruF4lUmS8cktVpK
CHOO/x6MXOGidbrFCBqcq7HN66UnJGVjK0bf/F/wU9RYjnAa9oT12Tn1mxGbP5Qr
8FiSmfA249j+DiMa57vQwD9SUS15V4Npm+sW2+2eamyG5tFbFfv7W/ZKjwzOwQBW
1tkyseCd4BBYPr1yksfvA2+eAE0s0Feamxt4+tF6x/0BZ0l/FA+aN8ZTSfcvM0Dh
5AyRPCJSIY8OpM+86Lk+LBo/hjJVuSiX99cQwb+mPMh9OZLKex8svHUqrJEr4si3
AB+eXA9LtfWWw5UqirXSdx4/oBCZCnegbOp2bw3DYnx8dZyGHTCsUoLkmFzVp4fP
QPbS8WSZVKjqSHIuWvsuhosHH47AsjUpoTE1zX9PJy6lbnZ9RGk=
=OtLy
-----END PGP SIGNATURE-----

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


Re: Getting all JDBC configs from the context

Posted by Shawn Heisey <ap...@elyograg.org>.
On 3/28/2018 1:18 PM, Christopher Schultz wrote:
> > I would like to write a logging thread that can get ALL of the
> > datasource objects from the context, and for types that it knows,
> > cast them to the appropriate object to log the active/idle
> > connection counts.
>
> It might be easier to do this via JMX.

Perhaps.  But then I have to figure out how to get the program started
with the sysprops that enable remote JMX.  The system has no GUI, and we
don't have any X-Windows infrastructure, so running JDK tools locally on
the Linux server is challenging.  Not impossible, just requires me to
set up things that I don't already have, to do X forwarding over SSH. 
With the logging thread idea, we just need to update code, recompile,
and redeploy.

> Since you already have a compile-time dependency upon Tomcat, there's
> no need to do class-name matching. Instead, just use "instanceof" as
> before:

I did the code that way so that I can handle any type of DataSource
object, even if we change our pool configurations, just by adding
stanzas to the switch.  And the default case logs the class name if it's
not handled explicitly, so I know what to add or change.  I went looking
for a way to write a switch statement that utilizes instanceof, didn't
find anything.

> Instead of running a single thread that goes to sleep, maybe consider
> using a ScheduledExecutorService with a simpler runnable object that
> just logs the status a single time.

Sounds like a good idea.  That I have absolutely no idea how to
implement.  I used the hammer I know. :)

> Don't forget to terminate the thread (or ExecutorService) when the
> application is shutting-down, of you'll have a ClassLoader (and a a
> huge memory) leak.

I did think about that, but I wasn't sure how to detect a shutdown.  Is
there something available that handles it easily and reliably with only
a small code change?  Just now, I found the following page when I went
looking for how to detect that (independent of the JVM shutting down):

http://www.deadcoderising.com/execute-code-on-webapp-startup-and-shutdown-using-servletcontextlistener/

I think I could use this to create the thread on application startup as
well as making sure it shuts down cleanly.  It would mean that I can
just create a new class for one of our applications and edit a config
file, instead of monkeying with other people's code.

It's very encouraging to me that you picked up on the lack of shutdown
handling.  It means I've got more than a sliver of your attention!

Thanks,
Shawn


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


Re: Getting all JDBC configs from the context

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Shawn,

On 3/27/18 10:26 PM, Shawn Heisey wrote:
> This is what the code in our application looks like that gets a 
> datasource object from the context:
> 
> Context initContext = new InitialContext(); Context envContext  =
> (Context)initContext.lookup("java:/comp/env"); DataSource ds =
> (DataSource)envContext.lookup("jdbc/REDACTED");
> 
> I would like to write a logging thread that can get ALL of the 
> datasource objects from the context, and for types that it knows,
> cast them to the appropriate object to log the active/idle
> connection counts.

It might be easier to do this via JMX.

> This paste is the idea I've thought of for initializing and
> creating this logging thread:
> 
> https://paste.apache.org/QcbE
> 
> The "log" variable is an slf4j Logger object.
> 
> Does that code look like it'll work, if we run it once at system 
> startup?  It doesn't have any errors in my IDE.  Which is not
> always an indication of success!

Since you already have a compile-time dependency upon Tomcat, there's
no need to do class-name matching. Instead, just use "instanceof" as
before:

DataSource ds = myMap.get(dsName);
if(ds instanceof org.apache.tomcat.dbcp.dbcp.BasicDataSource)
{
  (cast)
  (log)
}

Instead of running a single thread that goes to sleep, maybe consider
using a ScheduledExecutorService with a simpler runnable object that
just logs the status a single time.

Don't forget to terminate the thread (or ExecutorService) when the
application is shutting-down, of you'll have a ClassLoader (and a a
huge memory) leak.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlq76pYACgkQHPApP6U8
pFixAw//Ue6UyyLh+y59CEFalOrW0credrwh+i986CYL52wujdmgqmRts1o86N1s
UcSQ3dF4dp6VwZpaiZYrl2dJoxsk6alSkxGJ8zFQ4BsTps5fCehcWdBBf/iWT+Bz
/vbTqo/5o6g8/Sz8GqZ6AUD0gzU1TxIqqy30v5+7hClYLHVR0jZdTlWlX4bq8o44
OKC5imdV2jSCzJeq864BJNSA6/Ttcxsp4OrWZiHMc4YlW6tz7O8jqeB4t4wO+E8f
SoIla76A1L8dajtw85E1PPGFsD4pyBKrcMW9RIlt/ZqoQyI5UbDwOjN4MFBi6AnI
TSwj5fXcjLuFDoXwiZJo8Pvc6fLEc9m2Dd8LNfmnd4j68u+cPCWsE46GCpPZPdat
SAg2yPD0aZBLF/gdi8TFvVES/wQ4BN7s/TqjakxLPJVfSngzX789hyB0Wo8n2rEM
uil5KNyAw4QqnMZft+f5/t8tQ5A5XzU1Sfbxb/WOYI1tR5LwRvRbXiotRxw6lHAs
H+gdM0xXp16IWpyUJuSnczR1BXZhNplZMVozObhbzzzK0XhbBVqnpJRSdP087SNW
TY55/cAudvU8cMyzkF+1WicNPhdDKwqylcwiVHhiSOUduwlip70bMdjpBlMPmblg
sYBBS8X5nfnr52+hL/Qdgx1LZ/Zws5BoHl7q1drzq+SIPyPe5r0=
=eeI8
-----END PGP SIGNATURE-----

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