Bug 51396 - Embedding class cannot launch a webapp with a jsp servlet
Summary: Embedding class cannot launch a webapp with a jsp servlet
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 7.0.16
Hardware: PC All
: P2 major (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-20 17:02 UTC by bmargulies
Modified: 2011-06-20 22:51 UTC (History)
0 users



Attachments
test case in a patch (2.34 KB, patch)
2011-06-20 22:09 UTC, bmargulies
Details | Diff
Patch including fix to the problem. (3.17 KB, patch)
2011-06-20 22:40 UTC, bmargulies
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description bmargulies 2011-06-20 17:02:09 UTC
https://github.com/bimargulies/Tomcat-Solr-Test-Case is a test case. It creates an instance of Tomcat and then adds a webapp from Apache Solr. This webapp has 'jsp' servlets.

The code crashes, because the implicit default web.xml used in this case does not include a servlet named jsp, resulting in the following backtrace.



2011-06-20 12:56:24,598 [Embedded Tomcat] INFO org.apache.catalina.startup.ContextConfig - No global web.xml found
Exception in thread "Embedded Tomcat" java.lang.NullPointerException
	at org.apache.catalina.startup.ContextConfig.convertJsp(ContextConfig.java:1379)
	at org.apache.catalina.startup.ContextConfig.convertJsps(ContextConfig.java:1358)
	at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1349)
	at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:881)
	at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:316)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5103)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:812)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:787)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:607)
	at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:509)
	at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:483)
	at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:171)
	at org.apache.tomcat.tc.solrWebapp.LaunchWithSolr.tryToAddSolr(LaunchWithSolr.java:111)
	at org.apache.tomcat.tc.solrWebapp.LaunchWithSolr.access$1(LaunchWithSolr.java:106)
	at org.apache.tomcat.tc.solrWebapp.LaunchWithSolr$1.run(LaunchWithSolr.java:91)
Comment 1 Mark Thomas 2011-06-20 17:04:32 UTC
Look at the test cases for examples of how to do this.
Comment 2 bmargulies 2011-06-20 17:10:06 UTC
 It stuns me that you would close this without apparently taking 2 minutes to read the one Java class, which I wrote by reading the available doc and examples. Further, I spend several hours debugging into tomcat here, and there were a number of suspicious aspects that led me to think that a bugzilla was appropriate.

Further, this is code that worked with tomcat 6 embedded and only failed when I moved to tomcat 7.

My code was written from the available examples, it works fine for a webapp that jsp pages but not jsp servlets, and the webapp with jsp servlets works fine with unembedded tomcat.
Comment 3 bmargulies 2011-06-20 19:36:14 UTC
Since bz won't let me edit, I will improve on my description down here.

1) I've written a class that uses the embedded API:

  org.apache.catalina.startup.Tomcat

2) My class calls Tomcat.addWebapp.

3) My class works fine on a webapp that contains JSP pages.

4) My class does NOT work for webapps that have <servlet> declarations that name jsp pages.

5) The reason, which I have diagnosed, is the lack of the following servlet declaration from the default web.xml:

 <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

6) Tomcat.addWebapp does extra work to prevent the use of the default web.xml.

7) I can't find any test case in the tomcat hierarchy that looks like this overall model, and in particular which supplies default web.xml content when using the embedded Tomcat class. Though I may of course be missing something.
Comment 4 bmargulies 2011-06-20 19:51:00 UTC
In short, if there is a defect here, it is that:

org.apache.catalina.startup.Tomcat.initWebappDefaults(Context)

does not set up the servlet named 'jsp' which is set up in the default web.xml, and that the modularity of the Tomcat class does not offer a straightforward way to change that, since the function is static and so cannot be trivially @overridden.
Comment 5 bmargulies 2011-06-20 22:09:07 UTC
Created attachment 27182 [details]
test case in a patch

Here is a minimal test case as a patch. Proposed fix to follow.
Comment 6 Mark Thomas 2011-06-20 22:11:25 UTC
Bugs opened shortly after almost identical reports on the users list and containing statements that are clearly wrong (the jsp servlet is defined) do tend to get closed as invalid quickly to keep the noise down.

There is a bug here but a simpler test case would have made tracking it down a lot easier.

org.apache.catalina.startup.Tomcat.initWebappDefaults(Context) is a red herring. That code is fine. The problem is around where the NPE occurs. Because the JSP has been set up programmatically, the definition of the init parameters isn't where it would be if read from the default web.xml and that triggers the NPE.

I have a fix and the test case gets to the point where the app starts but I get 500 errors and the message java.lang.RuntimeException: Can't find resource 'solrconfig.xml' in classpath or 'D:\solr_webapp\.\conf/. I don't see a file with that name in testcase.

I'll commit that fix shortly and I'm going to assume that the 500 error is a problem with the webapp rather than another bug.
Comment 7 Mark Thomas 2011-06-20 22:38:25 UTC
Fixed in 7.0.x and will be included in 7.0.17 onwards.
Comment 8 bmargulies 2011-06-20 22:40:22 UTC
Created attachment 27183 [details]
Patch including fix to the problem.

Here we have the missing if statement to fix the problem, too.
Comment 9 bmargulies 2011-06-20 22:42:30 UTC
Well, now we've completed the whole story in parallel. 

Debugging the functions in ContextConfig, I think it is semi-fair to say that the jsp servlet is not, in fact, defined -- in web.xml-space, where the code is looking for it.

Perhaps my JUnit test would find a home.
Comment 10 Mark Thomas 2011-06-20 22:45:16 UTC
Comment on attachment 27183 [details]
Patch including fix to the problem.

The patch fixes the symptom, not the cause.
Comment 11 bmargulies 2011-06-20 22:51:14 UTC
Just for the record, it's not that I didn't see the importance of fishing the init params out of where they were, it's that I couldn't work out for myself where to find them. That doesn't make it the right patch, of course.