Solr
  1. Solr
  2. SOLR-5951

SolrDispatchFilter no longer displays useful error message on statup when logging jars are missing

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.7, 4.7.1
    • Fix Version/s: 4.7.2, 4.8, 6.0
    • Component/s: None
    • Labels:
      None

      Description

      We no longer have logging jars in the webapp since SOLR-3706. Because of this we added a extra check in SolrDispatchFilter's ctor to print a nice exception if the logging jars were failing. This check was unfortunately never tests and recently broke:

      The check delays initialization of the Logger instance to inside a try-catch block inside the explicit ctor. If it fails with ClassNotFound, it throws Exception.

      Recently we upgraded to a newer HttpClient version. Unfortunately SolrDispatchFliter also has an implicit constructor a few lines before the main constructor:

        protected final HttpClient httpClient = HttpClientUtil.createClient(new ModifiableSolrParams()); // <-- this breaks the detection
        
        private static final Charset UTF8 = StandardCharsets.UTF_8;
      
        public SolrDispatchFilter() {
          try {
            log = LoggerFactory.getLogger(SolrDispatchFilter.class);
          } catch (NoClassDefFoundError e) {
            throw new SolrException(
                ErrorCode.SERVER_ERROR,
                "Could not find necessary SLF4j logging jars. If using Jetty, the SLF4j logging jars need to go in "
                +"the jetty lib/ext directory. For other containers, the corresponding directory should be used. "
                +"For more information, see: http://wiki.apache.org/solr/SolrLogging",
                e);
          }
        }
      

      The first line above HttpClientUtil.createClient(new ModifiableSolrParams()); breaks the whole thing, because it is executed before the declared constructor. The user just sees a ClassNotFoundEx at this line of code, the nice error message is hidden.

      Because this is so easy to break, we should make the whole thing more safe (any maybe test it). 2 options:

      1. Into the webapp add a fake Servlet (not bound to anything, just loaded first) that does not use any Solr classes at all, nothing only plain java
      2. Alternatively add a Superclass between ServletFilter and SolrDispatchFilter (pkg-private). When the servlet container loads SolrDispatchFilter, it has in any case to first load the superclass. And this superclass does the check and throws ServletException or whatever (no Solr Exception) with the message from the current code.

      I tend to the second approach, because it does not need to modify web-inf. It will also work with other Solr servlets, they must just extend this hidden class. I will provide a patch for that.

      1. SOLR-5951.patch
        11 kB
        Uwe Schindler

        Issue Links

          Activity

          Hide
          Uwe Schindler added a comment -

          Patch that implements the second approach. The good thing: All user-visible servlets and filters extend those hidden abstract base classes. Because of this the checking code is executed in any case, although maybe some other servlet or filter is loaded before SolrDispatchFilter (e.g., user modified web.xml file).

          When starting the example with the Jetty ext folder emptied, the following is displayed:

          2014-04-02 23:21:10.009:WARN:oejuc.AbstractLifeCycle:FAILED SolrRequestFilter: java.lang.NoClassDefFoundError: Failed to initialize
          Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, the SLF4j logging jars need to go in the jetty lib/ext dir
          ectory. For other containers, the corresponding directory should be used. For more information, see: http://wiki.apache.org/solr/Sol
          rLogging
          java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, the S
          LF4j logging jars need to go in the jetty lib/ext directory. For other containers, the corresponding directory should be used. For m
          ore information, see: http://wiki.apache.org/solr/SolrLogging
                  at org.apache.solr.servlet.CheckLoggingConfiguration.check(CheckLoggingConfiguration.java:28)
                  at org.apache.solr.servlet.BaseSolrFilter.<clinit>(BaseSolrFilter.java:25)
                  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
                  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
                  at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
                  at java.lang.Class.newInstance(Class.java:374)
                  at org.eclipse.jetty.servlet.ServletContextHandler$Context.createFilter(ServletContextHandler.java:1053)
                  at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:105)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:719)
                  at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265)
                  at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1252)
                  at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:710)
                  at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:39)
                  at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:186)
                  at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:494)
                  at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:141)
                  at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:145)
                  at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:56)
                  at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:609)
                  at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:540)
                  at org.eclipse.jetty.util.Scanner.scan(Scanner.java:403)
                  at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:337)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:121)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:555)
                  at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:230)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.util.component.AggregateLifeCycle.doStart(AggregateLifeCycle.java:81)
                  at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:58)
                  at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:96)
                  at org.eclipse.jetty.server.Server.doStart(Server.java:280)
                  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
                  at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1259)
                  at java.security.AccessController.doPrivileged(Native Method)
                  at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1182)
                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
                  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                  at java.lang.reflect.Method.invoke(Method.java:606)
                  at org.eclipse.jetty.start.Main.invokeMain(Main.java:473)
                  at org.eclipse.jetty.start.Main.start(Main.java:615)
                  at org.eclipse.jetty.start.Main.main(Main.java:96)
          2014-04-02 23:21:10.013:WARN:oejuc.AbstractLifeCycle:FAILED o.e.j.w.WebAppContext{/solr,file:/C:/Users/Uwe%20Schindler/Projects/luce
          ne/trunk-lusolr2/solr/example/solr-webapp/webapp/},C:\Users\Uwe Schindler\Projects\lucene\trunk-lusolr2\solr\example/webapps/solr.wa
          r: java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, th
          e SLF4j logging jars need to go in the jetty lib/ext directory. For other containers, the corresponding directory should be used. Fo
          r more information, see: http://wiki.apache.org/solr/SolrLogging
          

          I will also backport this to Solr 4.7 branch, if we release another bugfix release.

          Show
          Uwe Schindler added a comment - Patch that implements the second approach. The good thing: All user-visible servlets and filters extend those hidden abstract base classes. Because of this the checking code is executed in any case, although maybe some other servlet or filter is loaded before SolrDispatchFilter (e.g., user modified web.xml file). When starting the example with the Jetty ext folder emptied, the following is displayed: 2014-04-02 23:21:10.009:WARN:oejuc.AbstractLifeCycle:FAILED SolrRequestFilter: java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, the SLF4j logging jars need to go in the jetty lib/ext dir ectory. For other containers, the corresponding directory should be used. For more information, see: http://wiki.apache.org/solr/Sol rLogging java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, the S LF4j logging jars need to go in the jetty lib/ext directory. For other containers, the corresponding directory should be used. For m ore information, see: http://wiki.apache.org/solr/SolrLogging at org.apache.solr.servlet.CheckLoggingConfiguration.check(CheckLoggingConfiguration.java:28) at org.apache.solr.servlet.BaseSolrFilter.<clinit>(BaseSolrFilter.java:25) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at java.lang.Class.newInstance(Class.java:374) at org.eclipse.jetty.servlet.ServletContextHandler$Context.createFilter(ServletContextHandler.java:1053) at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:105) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:719) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1252) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:710) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:39) at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:186) at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:494) at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:141) at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:145) at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:56) at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:609) at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:540) at org.eclipse.jetty.util.Scanner.scan(Scanner.java:403) at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:337) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:121) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:555) at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:230) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.util.component.AggregateLifeCycle.doStart(AggregateLifeCycle.java:81) at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:58) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:96) at org.eclipse.jetty.server.Server.doStart(Server.java:280) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1259) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1182) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.eclipse.jetty.start.Main.invokeMain(Main.java:473) at org.eclipse.jetty.start.Main.start(Main.java:615) at org.eclipse.jetty.start.Main.main(Main.java:96) 2014-04-02 23:21:10.013:WARN:oejuc.AbstractLifeCycle:FAILED o.e.j.w.WebAppContext{/solr,file:/C:/Users/Uwe%20Schindler/Projects/luce ne/trunk-lusolr2/solr/example/solr-webapp/webapp/},C:\Users\Uwe Schindler\Projects\lucene\trunk-lusolr2\solr\example/webapps/solr.wa r: java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. If using Jetty, th e SLF4j logging jars need to go in the jetty lib/ext directory. For other containers, the corresponding directory should be used. Fo r more information, see: http://wiki.apache.org/solr/SolrLogging I will also backport this to Solr 4.7 branch, if we release another bugfix release.
          Hide
          ASF subversion and git services added a comment -

          Commit 1584213 from Uwe Schindler in branch 'dev/trunk'
          [ https://svn.apache.org/r1584213 ]

          SOLR-5951: Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing

          Show
          ASF subversion and git services added a comment - Commit 1584213 from Uwe Schindler in branch 'dev/trunk' [ https://svn.apache.org/r1584213 ] SOLR-5951 : Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing
          Hide
          ASF subversion and git services added a comment -

          Commit 1584214 from Uwe Schindler in branch 'dev/branches/branch_4x'
          [ https://svn.apache.org/r1584214 ]

          Merged revision(s) 1584213 from lucene/dev/trunk:
          SOLR-5951: Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing

          Show
          ASF subversion and git services added a comment - Commit 1584214 from Uwe Schindler in branch 'dev/branches/branch_4x' [ https://svn.apache.org/r1584214 ] Merged revision(s) 1584213 from lucene/dev/trunk: SOLR-5951 : Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing
          Hide
          ASF subversion and git services added a comment -

          Commit 1584215 from Uwe Schindler in branch 'dev/branches/lucene_solr_4_7'
          [ https://svn.apache.org/r1584215 ]

          Merged revision(s) 1584214 from lucene/dev/branches/branch_4x:
          Merged revision(s) 1584213 from lucene/dev/trunk:
          SOLR-5951: Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing

          Show
          ASF subversion and git services added a comment - Commit 1584215 from Uwe Schindler in branch 'dev/branches/lucene_solr_4_7' [ https://svn.apache.org/r1584215 ] Merged revision(s) 1584214 from lucene/dev/branches/branch_4x: Merged revision(s) 1584213 from lucene/dev/trunk: SOLR-5951 : Fixed SolrDispatchFilter to throw useful exception on startup if SLF4j logging jars are missing
          Hide
          Uwe Schindler added a comment -

          Thanks Chris Hostetter (Unused) and Shawn Heisey for help on IRC!

          Show
          Uwe Schindler added a comment - Thanks Chris Hostetter (Unused) and Shawn Heisey for help on IRC!
          Hide
          Uwe Schindler added a comment -

          Close issue after release of 4.8.0

          Show
          Uwe Schindler added a comment - Close issue after release of 4.8.0

            People

            • Assignee:
              Uwe Schindler
              Reporter:
              Uwe Schindler
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development