|Summary:||Allow Context without real docbase in embedded Tomcat|
|Product:||Tomcat 8||Reporter:||Konstantin Kolinko <knst.kolinko>|
|Component:||Catalina||Assignee:||Tomcat Developers Mailing List <dev>|
Description Konstantin Kolinko 2014-10-28 00:44:09 UTC
Many of Tomcat test cases do the following to create and configure a web application programmatically: // Must have a real docBase - just use temp Context ctx = tomcat.addContext("", System.getProperty("java.io.tmpdir")); Essentially, it makes Tomcat to serve the contents of the system temporary directory. Sometimes it results in failures on CI servers (bug 57154 is an example). There shall be a way to configure a context that does not need a real docbase. I do not see a use case for that when running a standalone Tomcat, because docbase is needed to provide executable code for the application, but I do see the use case when running embedded Tomcat. In embedded Tomcat the entire web application can be configured programmatically. If I use a non-existent docbase, e.g. Context ctx = tomcat.addContext("", "ROOT"); Tomcat startup fails with [[[ Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) ... 6 more Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.webresources.StandardRoot@123f26] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4875) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5004) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 6 more Caused by: java.lang.IllegalArgumentException: The main resource set specified [(censored)\test-tmp\webapps\ROOT] is not valid at org.apache.catalina.webresources.StandardRoot.startInternal(StandardRoot.java:665) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 9 more ]]] If I do the following: Context ctx = tomcat.addContext("", ""); the test passes successfully. Apparently it is using docBase = appBase. An odd configuration, but it works if there are no other web applications in appBase.
Comment 1 Konstantin Kolinko 2014-10-28 01:03:32 UTC
I think that docBase that is equal to the empty string can be treated specially as this "No doc base" case. I mean that in this case one needs to configure the resources (org.apache.catalina.webresources.StandardRoot) so that no files are served. I think that now there is a risk that somebody will be unwillingly serving files from appbase if one specifies <Context docBase=""/> . If anybody really wants to serve files from appbase directory, one can use "." or an absolute path. Alternatively, add one-argument method to Tomcat class as public Context addContext(String contextPath) and perform all configuration of StandardRoot programmatically. In this case we can avoid special processing of docBase="".
Comment 2 Mark Thomas 2014-10-29 15:52:00 UTC
I'm leaning towards treating a docBase value of "" as invalid and using null to signal that a docBase on the file system is not required. I need to do some testing of this.
Comment 3 Konstantin Kolinko 2014-10-29 18:30:10 UTC
I envision a caveat with ContextConfig.fixDocBase(). The fixDocBase() method replaces null docBase with one calculated from path, (new ContextName(path, context.getWebappVersion())).getBaseName(). Using null in tomcat.addContext(path, null) is indeed a good API. (Maybe add a single-argument Tomcat.addContext(path) for this use case).
Comment 4 Mark Thomas 2014-10-29 22:21:37 UTC
I don't see a need to change ContextConfig. That is not intended for use in embedding. If it was used it would only be used when there was a docBase on the filesystem. This has been fixed in 8.0.x for 8.0.15 onwards.