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();


Reply via email to