You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Johannes Brodwall <jo...@brodwall.com> on 2001/09/21 10:04:55 UTC

EmbededTomcat embeded, addContext

I am continuing with my struggle getting tomcat 3.3 to work embedded, and it
seems like I am finally starting to see the light.

I saw that my patch for addEndpoint was added, which is good.  However,
addAjpEdpoint contains the same bug.  That InetAddress.toString is a
insidious little monster.

More importantly, there is a problem with EmbededTomcat.addContext.  Since
the first thing this method does is to call initContextManager, the new
context is added after contextManager.init has been called.  This means that
Context.init is never called, and the context is still in STATE_ADDED when
it is supposed to handle requests.  This is very hard to debug, as there is
no error message to that effect, only a generic 503.

Here is my suggested patch:

EmbebedTomcat.addContext

347:     contextM.addContext( ctx );
+        ctx.init();
348:     return ctx;

This will happen after contextM.init is called; I am not sure if that will
cause adverse side-effects.

Secondly, in order to more easily spot this kind of problem, I suggest the
following change in ContextManager.

ContextManager.java:949-958
- if( req.getContext() == null ||
-     req.getContext().getState() != Context.STATE_READY ) {
-     // the context is not fully initialized.
-     req.setAttribute("javax.servlet.error.message",
-        "Application not available");
-     // return error code - the caller will handle it
-     // handleStatus( req, req.getResponse(), 503 );
-     // service unavailable
-     return 503;
- }


+ if( req.getContext() == null ) {
+     req.setAttribute("javax.servlet.error.message",
+        "Context not set in request!");
+    return 503;
+ }
+ if( req.getContext().getState() != Context.STATE_READY ) {
+     req.setAttribute("javax.servlet.error.message",
+        "Context " + req.getContext() + " is not initialized");
+     return 503;
+ }


Lastly, I would like to warn people that when using
EmbededContext.addContext, the name of the ROOT context is "", not "ROOT".
The diagnostics for a missing root context are quite confusing
(java.lang.RuntimeException: Assertion failed: container==null at
org.apache.tomcat.modules.mappers.SimpleMapper1.contextMap(SimpleMapper1.jav
a:298))

I hope this can be of use.

Sincerely,
Johannes Brodwall
--

PS. Here is the code I am using - I am executing it using the Beanshell
interpreter (www.beanshell.org) using classpath
lib\tomcat.jar;lib\common\connector_util.jar;
lib\common\core_util.jar;lib\common\etomcat.jar;
lib\common\jasper-runtime.jar;lib\common\servlet.jar;lib\common\tomcat_core.
jar:


tomcatHome = "C:\\java\\external\\jakarta-tomcat\\dist\\tomcat";
import org.apache.tomcat.util.IntrospectionUtils;
parentL = IntrospectionUtils.class.getClassLoader();

commonCP = IntrospectionUtils.getClassPath(tomcatHome + "\\lib\\common",
null, "org.apache.tomcat.common.loader", false);
commonCL = URLClassLoader.newInstance(commonCP, parentL);

containerCP = IntrospectionUtils.getClassPath(tomcatHome +
"\\lib\\container", null, "org.apache.tomcat.common.loader", false);
containerCL = URLClassLoader.newInstance(containerCP, parentL);

appsCP = IntrospectionUtils.getClassPath(tomcatHome + "\\lib\\apps", null,
"org.apache.tomcat.common.loader", false);
appsCL = URLClassLoader.newInstance(appsCP, parentL);


tomcat = new org.apache.tomcat.startup.EmbededTomcat();

tomcat.setInstall(tomcatHome);
tomcat.setParentClassLoader(parentL);
tomcat.setContainerClassLoader(containerCL);
tomcat.setCommonClassPath(commonCP);
tomcat.setCommonClassLoader(commonCL);

tomcat.setEstart(true);

rootContextUrl = new URL("file:c:\\java\\projects\\hellotomcat\\");
tomcat.addContext("", rootContextUrl, null);
// using the Accessibility API to set tomcat.initialized = false, and
// then calling tomcat.initContextManager() here will produce the
/  desired behaviour

tomcat.start();



Re: EmbededTomcat embeded, addContext

Posted by cm...@yahoo.com.
Hi Johannes,

Many thanks for your work ! I'll incorporate your fixes - AFAIK Larry
is planning to build RC1 this weekend, I'll make sure everything gets in.

Feel free to propose any additional improvements to
EmbededTomcat. In case you have problems, remember you can at any time
call getContextManager and use it directly.

It is also possible to just ignore EmbededTomcat and create your own
startup program - either something specialized for your needs or a better
version of EmbededTomcat. The current code was 'driven' by the current
common use-cases for tomcat.

The general idea is that everything is ( or should be ) replaceable :-)

Costin


On Fri, 21 Sep 2001, Johannes Brodwall wrote:

> I am continuing with my struggle getting tomcat 3.3 to work embedded, and it
> seems like I am finally starting to see the light.
>
> I saw that my patch for addEndpoint was added, which is good.  However,
> addAjpEdpoint contains the same bug.  That InetAddress.toString is a
> insidious little monster.
>
> More importantly, there is a problem with EmbededTomcat.addContext.  Since
> the first thing this method does is to call initContextManager, the new
> context is added after contextManager.init has been called.  This means that
> Context.init is never called, and the context is still in STATE_ADDED when
> it is supposed to handle requests.  This is very hard to debug, as there is
> no error message to that effect, only a generic 503.
>
> Here is my suggested patch:
>
> EmbebedTomcat.addContext
>
> 347:     contextM.addContext( ctx );
> +        ctx.init();
> 348:     return ctx;
>
> This will happen after contextM.init is called; I am not sure if that will
> cause adverse side-effects.
>
> Secondly, in order to more easily spot this kind of problem, I suggest the
> following change in ContextManager.
>
> ContextManager.java:949-958
> - if( req.getContext() == null ||
> -     req.getContext().getState() != Context.STATE_READY ) {
> -     // the context is not fully initialized.
> -     req.setAttribute("javax.servlet.error.message",
> -        "Application not available");
> -     // return error code - the caller will handle it
> -     // handleStatus( req, req.getResponse(), 503 );
> -     // service unavailable
> -     return 503;
> - }
>
>
> + if( req.getContext() == null ) {
> +     req.setAttribute("javax.servlet.error.message",
> +        "Context not set in request!");
> +    return 503;
> + }
> + if( req.getContext().getState() != Context.STATE_READY ) {
> +     req.setAttribute("javax.servlet.error.message",
> +        "Context " + req.getContext() + " is not initialized");
> +     return 503;
> + }
>
>
> Lastly, I would like to warn people that when using
> EmbededContext.addContext, the name of the ROOT context is "", not "ROOT".
> The diagnostics for a missing root context are quite confusing
> (java.lang.RuntimeException: Assertion failed: container==null at
> org.apache.tomcat.modules.mappers.SimpleMapper1.contextMap(SimpleMapper1.jav
> a:298))
>
> I hope this can be of use.
>
> Sincerely,
> Johannes Brodwall
> --
>
> PS. Here is the code I am using - I am executing it using the Beanshell
> interpreter (www.beanshell.org) using classpath
> lib\tomcat.jar;lib\common\connector_util.jar;
> lib\common\core_util.jar;lib\common\etomcat.jar;
> lib\common\jasper-runtime.jar;lib\common\servlet.jar;lib\common\tomcat_core.
> jar:
>
>
> tomcatHome = "C:\\java\\external\\jakarta-tomcat\\dist\\tomcat";
> import org.apache.tomcat.util.IntrospectionUtils;
> parentL = IntrospectionUtils.class.getClassLoader();
>
> commonCP = IntrospectionUtils.getClassPath(tomcatHome + "\\lib\\common",
> null, "org.apache.tomcat.common.loader", false);
> commonCL = URLClassLoader.newInstance(commonCP, parentL);
>
> containerCP = IntrospectionUtils.getClassPath(tomcatHome +
> "\\lib\\container", null, "org.apache.tomcat.common.loader", false);
> containerCL = URLClassLoader.newInstance(containerCP, parentL);
>
> appsCP = IntrospectionUtils.getClassPath(tomcatHome + "\\lib\\apps", null,
> "org.apache.tomcat.common.loader", false);
> appsCL = URLClassLoader.newInstance(appsCP, parentL);
>
>
> tomcat = new org.apache.tomcat.startup.EmbededTomcat();
>
> tomcat.setInstall(tomcatHome);
> tomcat.setParentClassLoader(parentL);
> tomcat.setContainerClassLoader(containerCL);
> tomcat.setCommonClassPath(commonCP);
> tomcat.setCommonClassLoader(commonCL);
>
> tomcat.setEstart(true);
>
> rootContextUrl = new URL("file:c:\\java\\projects\\hellotomcat\\");
> tomcat.addContext("", rootContextUrl, null);
> // using the Accessibility API to set tomcat.initialized = false, and
> // then calling tomcat.initContextManager() here will produce the
> /  desired behaviour
>
> tomcat.start();
>