Bug 51713 - Bad Connector protocol causes NullPointerException when using Executor
Bad Connector protocol causes NullPointerException when using Executor
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Catalina
7.0.20
PC All
: P2 minor (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2011-08-23 21:44 UTC by Christopher Schultz
Modified: 2011-08-25 15:01 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christopher Schultz 2011-08-23 21:44:53 UTC
Under the following configuration, an NPE is thrown because _setExecutor() calls con.getProtocolHandler().getClass() when the protocol handler is null.

It would be nice to report a bad configuration instead of suffering an NPE.

server.xml:

    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>

    <Connector port="12345"
               redirectPort="443" protocol="HTTP"
               secure="true" scheme="https" proxyPort="80"
               URIEncoding="UTF-8" executor="tomcatThreadPool" />

catalina.out:

Aug 23, 2011 5:18:30 PM org.apache.catalina.connector.Connector <init>
SEVERE: Protocol handler instantiation failed
Aug 23, 2011 5:18:30 PM org.apache.tomcat.util.digester.Digester startElement
SEVERE: Begin event threw exception
java.lang.NullPointerException
        at org.apache.catalina.startup.ConnectorCreateRule._setExecutor(ConnectorCreateRule.java:69)
        at org.apache.catalina.startup.ConnectorCreateRule.begin(ConnectorCreateRule.java:63)
        at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1276)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
        at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2755)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1537)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:555)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:596)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449)


Aug 23, 2011 5:18:30 PM org.apache.catalina.startup.Catalina load
WARNING: Catalina.start using conf/server.xml: Error at (104, 66) : null
Aug 23, 2011 5:18:30 PM org.apache.catalina.connector.Connector <init>
SEVERE: Protocol handler instantiation failed
Aug 23, 2011 5:18:30 PM org.apache.tomcat.util.digester.Digester startElement
SEVERE: Begin event threw exception
java.lang.NullPointerException
        at org.apache.catalina.startup.ConnectorCreateRule._setExecutor(ConnectorCreateRule.java:69)
        at org.apache.catalina.startup.ConnectorCreateRule.begin(ConnectorCreateRule.java:63)
        at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1276)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
        at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2755)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1537)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:555)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:609)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Aug 23, 2011 5:18:31 PM org.apache.catalina.startup.Catalina load
WARNING: Catalina.start using conf/server.xml: Error at (104, 66) : null
Aug 23, 2011 5:18:31 PM org.apache.catalina.startup.Catalina start
SEVERE: Cannot start server. Server instance is not configured.
Comment 1 Christopher Schultz 2011-08-24 15:59:04 UTC
Looking at the code, it seems that the o.a.c.connector.Connector constructor attempts to create the protocol handler and catches any exceptions that occur and merely logs them.

Later, when o.a.c.startup.ConnectorCreateRule calls _setExecutor, there is an assumption that the protocol handler has been correctly set which is not true.

Is there any reason why the Connector's constructor catches that exception instead of allowing it to propagate? That would seem to solve this particular problem.
Comment 2 Christopher Schultz 2011-08-24 16:00:21 UTC
It also appears that there is an incorrect parens situation going-in in Connector(String):

    public Connector(String protocol) {
        setProtocol(protocol);
        // Instantiate protocol handler
        try {
            Class<?> clazz = Class.forName(protocolHandlerClassName);
            this.protocolHandler = (ProtocolHandler) clazz.newInstance();
        } catch (Exception e) {
            log.error
                (sm.getString
                 ("coyoteConnector.protocolHandlerInstantiationFailed", e));
        }
    }

I believe the intent was to log the error message and the exception, not to use the exception as a parameter to sm.getString(). This is masking quite a bit of the underlying error.
Comment 3 Konstantin Kolinko 2011-08-25 00:33:53 UTC
Fixed the message in Connector constructor in trunk in r1161322.
Backported to 7.0.x and will be in 7.0.21.


Regarding whether or not rethrow the exception from inside of Connector constructor:

On one hand, such an error is nearly fatal. If I do not configure an Executor, there are a lot of failures that follow. None of webapps is able to start because of NPE in connector.getAttribute() call in ApplicationContext.populateSessionTrackingModes() - stacktrace is below.

On other hand, Tomcat as a whole does start up and is manageable. There is *.EXIT_ON_INIT_FAILURE system property that one can use to turn this into a fatal failure.

If the ClassNotFoundException from Connector constructor were rethrown, the startup sequence aborts immediately. It might be not what everyone wants.


I think this issue is sufficiently addressed. I do not intend to backport this to 6.0.


-----
NPE in ApplicationContext.populateSessionTrackingModes():

SEVERE: ContainerBase.addChild: start: 
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/docs]]
  (...)
Caused by: java.lang.NullPointerException
  at org.apache.tomcat.util.IntrospectionUtils.getProperty(IntrospectionUtils.java:402)
  at org.apache.catalina.connector.Connector.getProperty(Connector.java:272)
  at org.apache.catalina.connector.Connector.getAttribute(Connector.java:291)
  at org.apache.catalina.core.ApplicationContext.populateSessionTrackingModes(ApplicationContext.java:1195)
  at org.apache.catalina.core.ApplicationContext.<init>(ApplicationContext.java:127)
Comment 4 Christopher Schultz 2011-08-25 15:01:38 UTC
Okay, I'm happy with that explanation.

Certainly logging the exception stack trace will improve things as the "real" problem will be properly logged (InstantiationException or CNFE with a message) instead of the terse "Protocol handler instantiation failed" which tends to get lost among the following exception stack traces.