Bug 57733

Summary: ServletContext.getContext(String) always returns null for the root context ("/")
Product: Tomcat 8 Reporter: Ivan Nikolchov <ivannikolchov>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED DUPLICATE    
Severity: normal CC: ivannikolchov, tomasz.macnar
Priority: P2    
Version: 8.0.30   
Target Milestone: ----   
Hardware: PC   
OS: All   

Description Ivan Nikolchov 2015-03-21 18:03:59 UTC
The cause of the problem is the fix for bug #57190 for version 8.0.16 (https://bz.apache.org/bugzilla/show_bug.cgi?id=57190) 

It is not present in version 8.0.15

I have the following configuration running on Tomcat 8.0.20:

C:\tomcat
   conf
     server.xml
     context.xml
   webapps
     app
   ......
C:\external
     app3
        web
     app4
        web
In context.xml I have <Context crossContext="true"> .... </Context>

And in server.xml:
 ..........
 <Host name="host.com"  appBase="webapps" unpackWARs="true" autoDeploy="true">
    <Context 
      docBase="C:\external\app3\web" 
      path="" 
      crossContext="true"
      reloadable="true" />

    <Context 
      crossContext="true"
      docBase="C:\external\app4\web" 
      path="/app4"
      reloadable="true" />
 </Host>
Obtaining the Context of /app works as espected:

request.getServletContext().getContext("/app") is not null.

However, requesting the Context of the root app (app3) with:

request.getServletContext().getContext("/") ALWAYS returns null.

After some debugging found out that this is a regression caused by the fix for #57190  in org.apache.catalina.core.ApplicationContext#getContext(String)

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.17/org/apache/catalina/core/ApplicationContext.java#286

on line 286 we have
284             // Must be an exact match. It is no good returning the ROOT
285             // context if the caller is looking for "/something-else"
286             if (mappingData.context.getPath().equals(uri)) {
287                 child = mappingData.context;
288             }

Here uri is "/" and mappingData.context.getPath() is "" hence the null result.

Probably it should be:
String contextPath = mappingData.context.getPath();
if (contextPath.equals(uri) || contextPath.isEmpty() && uri.equals("/")) {
....
}
Comment 1 Christopher Schultz 2015-03-21 22:06:06 UTC

*** This bug has been marked as a duplicate of bug 57645 ***
Comment 2 Tomasz 2015-12-29 11:31:49 UTC
Bug is still existing on tomcat 8.0.30 (and probably tomcat 7.x)
I debug source code of tomcat and find, that ROOT context (with empty "path" in configuration server.xml) is added to ContainerBase class (HashMap name children) in key "", but i suppoust it shoud add ROOT context with key "/". Bug is probably in line 2036 in class org.apache.catalina.core.StandardContext, when set path.
 
When i want to get root context (class ApplicationContext.getContext("/")) i can't call it with empty string parameter, because method check param and return null (!uri.startsWith("/")). When I call it with param "/" , I have null. 

Please check it - it is very important for us.
Comment 3 Mark Thomas 2015-12-29 17:25:35 UTC
The following JSP snippet works as expected:

<%
out.print("[" + request.getServletContext().getContext("/").getContextPath() + "]");
%>

If you need assistance debugging why your application doesn't work then please use the users mailing list.

*** This bug has been marked as a duplicate of bug 57645 ***
Comment 4 Tomasz 2015-12-30 09:31:07 UTC
Ok i agree, that this code work OK.
But my case is other. I get ServletContext from servlet. Hire is my example:

public class TestServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {

        ServletContext servletContext = getServletContext();

        System.out.println("Servlet START: " + servletContext.getContextPath());

        String[] contextTab = { "/", "/app1", "/app2" };

        for (String con : contextTab) {
            System.out.println("Context " + con + " : " + servletContext.getContext(con));
        }
    }
}

And in context "/" always I have null. In server.xml i have configuration:
<Context path="" docBase="${catalina.base}/webapps/ROOT" crossContext="true" />
<Context path="/app1" docBase="${catalina.base}/webapps/app1" crossContext="true" />
<Context path="/app2" docBase="${catalina.base}/webapps/app2" crossContext="true" />

And the output is:
Servlet START: /app1
Context / : null
Context /app1 : null
Context /app2 : null

Servlet START: /app2
Context / : null
Context /app1 : org.apache.catalina.core.ApplicationContextFacade@8c6fb37
Context /app2 : null

Servlet is added to app1 and app2.
Comment 5 Mark Thomas 2015-12-30 19:32:14 UTC
Use the users mailing list.

If you continue to ignore advice you are given and re-open this bug with an unrelated question then your Bugzilla account will be disabled.

*** This bug has been marked as a duplicate of bug 57645 ***