Solr
  1. Solr
  2. SOLR-3244

New Admin UI doesn't work on tomcat

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.0-ALPHA
    • Fix Version/s: 4.0-ALPHA
    • Component/s: web gui
    • Labels:
      None

      Description

      I am currently unable to open admin interface when using war deployment under tomcat server.
      The stack trace:

      SEVERE: Servlet.service() for servlet [LoadAdminUI] in context with path [/solr] threw exception
      java.lang.NullPointerException
      at java.io.File.<init>(File.java:251)
      at org.apache.solr.servlet.LoadAdminUiServlet.doGet(LoadAdminUiServlet.java:50)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:292)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
      at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1815)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
      at java.lang.Thread.run(Thread.java:722)

      Tomcat version: Apache Tomcat/7.0.23
      Java version: jdk1.7.0_02

      I did some debugging and found that the problem related that
      it delegates the resolving of resource path to the org.apache.naming.resources.WARDirContext which simply returns null for any input parameters:

      /**

      • Return the real path for a given virtual path, if possible; otherwise
      • return <code>null</code>.
        *
      • @param path The path to the desired resource
        */
        @Override
        protected String doGetRealPath(String path) { return null; }

      Need to check specification, because it may be actually the tomcat bug. We may try use the getResourceAsStream(java.lang.String path) method which should work even for war.

      1. SOLR-3244.patch
        2 kB
        Uwe Schindler

        Issue Links

          Activity

          Hide
          Uwe Schindler added a comment - - edited

          It seems that the file is missing in the WAR file?

          File f = new File(getServletContext().getRealPath("admin.html"));
          if(f.exists()) {
            // This attribute is set by the SolrDispatchFilter
            CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
          
            String html = IOUtils.toString(new FileInputStream(f), "UTF-8");
          

          In general I am a little bit sceptical about the whole code. In my opinion using File and getRealPath is not the best idea. The simpliest and filesystem-unspecific to get the file is (there may be a servlet container that does not extract WAR files at all and simply returns the resource from inside the war file):

          InputStream in = getServletContext().getResourceAsStream("/admin.html");
          if(in != null) try {
            // This attribute is set by the SolrDispatchFilter
            CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
          
            String html = IOUtils.toString(in, "UTF-8");
            ...
          } finally {
            IOUtils.closeSafely(in);
          }
          

          Please note the "/" in the path, accoring to JavaDocs of getResource:

          The path must begin with a / and is interpreted as relative to the current context root, or relative to the /META-INF/resources directory of a JAR file inside the web application's /WEB-INF/lib directory. This method will first search the document root of the web application for the requested resource, before searching any of the JAR files inside /WEB-INF/lib. The order in which the JAR files inside /WEB-INF/lib are searched is undefined.

          This also applies to getRealPath, so I think Tomcat is more picky about that than jetty.

          Show
          Uwe Schindler added a comment - - edited It seems that the file is missing in the WAR file? File f = new File(getServletContext().getRealPath( "admin.html" )); if (f.exists()) { // This attribute is set by the SolrDispatchFilter CoreContainer cores = (CoreContainer) request.getAttribute( "org.apache.solr.CoreContainer" ); String html = IOUtils.toString( new FileInputStream(f), "UTF-8" ); In general I am a little bit sceptical about the whole code. In my opinion using File and getRealPath is not the best idea. The simpliest and filesystem-unspecific to get the file is (there may be a servlet container that does not extract WAR files at all and simply returns the resource from inside the war file): InputStream in = getServletContext().getResourceAsStream( "/admin.html" ); if (in != null ) try { // This attribute is set by the SolrDispatchFilter CoreContainer cores = (CoreContainer) request.getAttribute( "org.apache.solr.CoreContainer" ); String html = IOUtils.toString(in, "UTF-8" ); ... } finally { IOUtils.closeSafely(in); } Please note the "/" in the path, accoring to JavaDocs of getResource: The path must begin with a / and is interpreted as relative to the current context root, or relative to the /META-INF/resources directory of a JAR file inside the web application's /WEB-INF/lib directory. This method will first search the document root of the web application for the requested resource, before searching any of the JAR files inside /WEB-INF/lib. The order in which the JAR files inside /WEB-INF/lib are searched is undefined. This also applies to getRealPath, so I think Tomcat is more picky about that than jetty.
          Hide
          Uwe Schindler added a comment -

          Hi,

          can you apply the attached patch and rebuild the WAR. This fixes this bug and also another security issue:

          • The inlined pathes are not correctly escaped according to JavaScript rules, this can lead to security problems if you deploy to a path with strange characters in it...
          Show
          Uwe Schindler added a comment - Hi, can you apply the attached patch and rebuild the WAR. This fixes this bug and also another security issue: The inlined pathes are not correctly escaped according to JavaScript rules, this can lead to security problems if you deploy to a path with strange characters in it...
          Hide
          Uwe Schindler added a comment -

          It would be nice if you could test this, I have no Tomcat available...

          Show
          Uwe Schindler added a comment - It would be nice if you could test this, I have no Tomcat available...
          Hide
          Aliaksandr Zhuhrou added a comment -

          Sure, I will test it at evening. Thank you very much.

          Show
          Aliaksandr Zhuhrou added a comment - Sure, I will test it at evening. Thank you very much.
          Hide
          Aliaksandr Zhuhrou added a comment -

          I checked your patch and it works on Tomcat.

          Show
          Aliaksandr Zhuhrou added a comment - I checked your patch and it works on Tomcat.
          Hide
          Uwe Schindler added a comment -

          Fine, I will commit this now!

          Show
          Uwe Schindler added a comment - Fine, I will commit this now!
          Hide
          Uwe Schindler added a comment -

          Committed trunk revision: 1300710

          Thanks Aliaksandr!

          Show
          Uwe Schindler added a comment - Committed trunk revision: 1300710 Thanks Aliaksandr!
          Hide
          Ryan McKinley added a comment -

          Thanks Uwe – I did not realize you could get the stream directly from ServletContext

          Show
          Ryan McKinley added a comment - Thanks Uwe – I did not realize you could get the stream directly from ServletContext

            People

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

              Dates

              • Created:
                Updated:
                Resolved:

                Development