Bug 48613 - AprLifecycleListener tries to initialize even if it is not configured in server.xml
Summary: AprLifecycleListener tries to initialize even if it is not configured in serv...
Alias: None
Product: Tomcat 6
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 6.0.24
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: default
Assignee: Tomcat Developers Mailing List
URL: http://www.martincordova.com
Depends on:
Reported: 2010-01-25 15:07 UTC by Martin Cordova
Modified: 2010-02-18 09:53 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
Description Martin Cordova 2010-01-25 15:07:48 UTC
When Tomcat starts, this message is displayed, in spite of this listener not being used in server.xml. There is no way to avoid it.

org.apache.catalina.core.AprLifecycleListener init
INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path
Comment 1 Konstantin Kolinko 2010-01-25 19:37:14 UTC

o.a.c.connector.Connector#setProtocol(String) has a call to static method AprLifecycleListener.isAprAvailable().

o.a.c.core.AprLifecycleListener#isAprAvailable() calls AprLifecycleListener#init() and that tries to initialize APR, and prints the message.
Comment 2 Filip Hanik 2010-01-27 17:31:04 UTC
Fixed in trunk/ backport proposed for 6.0.x branch
Comment 3 Konstantin Kolinko 2010-01-27 19:22:27 UTC
Filip, the proposed patch (rev.903928) is wrong -- see sequence of calls described in the Comment 1 in this issue.

Connector#setProtocol(String) is called by Digester when creating instance of the Connector,  and that happens long before the Lifecycle event is fired and reaches the listener.

Thus, with the patch, AprLifecycleListener will report that the native library is found, but Connector#setProtocol(String) will create a non-Apr connector. (an exact opposite of Bug 48311).

It can be seen in the logs, running the trunk as of rev.903928:

28.01.2010 6:12:55 org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.19.
28.01.2010 6:12:55 org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], ra
ndom [true].
28.01.2010 6:12:56 org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
28.01.2010 6:12:56 org.apache.coyote.ajp.AjpProtocol init
INFO: Initializing Coyote AJP/1.3 on ajp-8009

Note that "Http11Protocol" and "AjpProtocol" were printed, instead of 
"Http11AprProtocol" and "AjpAprProtocol" that were expected. 

I see two ways of fixing the current issue:
a) quick but somewhat dirty:

Use the fact that AprLifecycleListener instance is created by digester before the instance of a connector.

That is, in AprLifecycleListener class constructor set some volatile static field as a flag stating that "an instance of the Listener was created" and test that flag in the init() method.

I wonder, whether we will need to wait for Lifecycle.INIT_EVENT to happen, or all initialization (including initializeSSL() call) can be done at the same time.

b) more elaborate,

Change implementation of o.a.c.connector.Connector, to defer the AprLifecycleListener.isAprAvailable() call until Connector#start() is called.

This means:
 #  in Connector#setProtocol(String) method: do not initialize protocolHandlerClassName field there
 #  in Connector(String) constructor: do not initialize protocolHandler field
 #  in Connector#setProperty(String, String) method: allow it to work when protocolHandler is not yet initialized, e.g. by caching the values in a map

But with such a change Connector#setProperty() won't be able to report about unknown properties at call time, thus "Warn if the user tries to set an invalid property" feature will need to be reimplemented here.

Thus it looks to me that it would be better to go with a).

If we refuse to go with b), then Connector#setProtocol() and Connector#setProtocolHandlerClassName methods can be made private (or at least protected), because as of now they work only when called from Connector(String) constructor.

Comment 4 Mark Thomas 2010-01-28 04:11:19 UTC
I was looking at this and came up with your option a) as a solution. It is a bit of a hack but as long as we document why that should be fine.

I also don't see any reason not to move the whole of the init method in the constructor.
Comment 5 Filip Hanik 2010-01-28 11:23:40 UTC
Your right Konstantin,
We've tried to fix this in the past

Let's push your change through.
Comment 6 Filip Hanik 2010-01-28 11:28:55 UTC
>I wonder, whether we will need to wait for Lifecycle.INIT_EVENT to happen,

I don't see why we wouldn't wait. while we could call it during isAprAvailable() and the init method, at least we know that all properties have been set during INIT_EVENT.
Comment 7 Mark Thomas 2010-01-31 16:30:25 UTC
This has been fixed in trunk and proposed for 6.0.x by Filip
Comment 8 Mark Thomas 2010-02-18 09:53:33 UTC
That patch had been applied to trunk and will be included in 6.0.25 onwards.