tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dan Martens" <dlmar...@hotmail.com>
Subject Bug found when calling init methods of defined web apps
Date Thu, 27 Jul 2000 17:23:58 GMT
Hello all.
This is my first message to this group so please let me know if you have 
heard of this behaviour before.  There is a bug in 
org.apache.tomcat.core.ContextManager which allows for the loading of every 
defined servlet in the web.xml file four times at startup.  Not only is each 
servlets init() method called four times, but four different objects are 
created. Since the code base is fairly thick and requires a lot of debugging 
(speaking from experience) this code segment in the init() method of 
ContextManager seems to be producing the error indirectly.
<-- begin code
while(enum.hasMoreElements()) {
	    context = getContext((String)enum.nextElement());
	    try {
		initContext( context );
end code--->
Each object of this enumeration is a different Context, the problem is 
during the creation of each context, the conf/web.xml file is scanned and 
it's information stored in each seperate object.  Then upon the 
initialization of each context, the servlets which it references are 
initialized. This includes such servlets as the DefaultErrorPage, invoker 
and the jsp servlet. The reason for this behaviour occuring exactly four 
times seems to be because in a clean drop of the 3.1 release, there are four 
subdirectories in the WebApps directory, each of which is loaded as a 
seperate context.
I have created a simple fix to this situation which prevents the servlets 
from being loaded repeatedly, but since this other things may be loaded 
repeatedly as well, it is worth further investigation into the actual root 
of the problem.  The fix is in  
org.apache.tomcat.context.LoadOnStartupInterceptor.contextInit(Context) 
method. Currently as it stands the method looks like this
<------begin code
public void contextInit(Context ctx) {
	Hashtable loadableServlets = new Hashtable();
	init(ctx,loadableServlets);

	Vector orderedKeys = new Vector();
	Enumeration e=  loadableServlets.keys();

	// order keys
	while (e.hasMoreElements()) {
	    Integer key = (Integer)e.nextElement();
	    int slot = -1;
	    for (int i = 0; i < orderedKeys.size(); i++) {
	        if (key.intValue() <
		    ((Integer)(orderedKeys.elementAt(i))).intValue()) {
		    slot = i;
		    break;
		}
	    }
	    if (slot > -1) {
	        orderedKeys.insertElementAt(key, slot);
	    } else {
	        orderedKeys.addElement(key);
	    }
	}

	// loaded ordered servlets

	// Priorities IMO, should start with 0.
	// Only System Servlets should be at 0 and rest of the
	// servlets should be +ve integers.
	// WARNING: Please do not change this without talking to:
	// harishp@eng.sun.com (J2EE impact)

	for (int i = 0; i < orderedKeys.size(); i ++) {
	    Integer key = (Integer)orderedKeys.elementAt(i);
	    Enumeration sOnLevel =  ((Vector)loadableServlets.get( key 
)).elements();
	    while (sOnLevel.hasMoreElements()) {
		String servletName = (String)sOnLevel.nextElement();
		ServletWrapper  result = ctx.getServletByName(servletName);

		if( ctx.getDebug() > 0 ) ctx.log("Loading " + key + " "  + servletName );
		if(result==null)
		    System.out.println("Warning: we try to load an undefined servlet " + 
servletName);
		else {
		    try {
			if( result.getPath() != null )
			    loadJsp( ctx, result );
			else
			    result.loadServlet();
		    } catch (Exception ee) {
			String msg = sm.getString("context.loadServlet.e",
						  servletName);
			System.out.println(msg);
		    }
		}
	    }
	}
}
----end code>
If you make the Hashtable loadableServlets a class variable and add a simple 
if statement encompassing the entire method, it will skip the repeat loading 
of servlets.  Therefore the method fix is:
<-----begin code
public void contextInit(Context ctx) {
if(loadableServlets == null){
	loadableServlets = new Hashtable();
	init(ctx,loadableServlets);

	Vector orderedKeys = new Vector();
	Enumeration e=  loadableServlets.keys();

	// order keys
	while (e.hasMoreElements()) {
	    Integer key = (Integer)e.nextElement();
	    int slot = -1;
	    for (int i = 0; i < orderedKeys.size(); i++) {
	        if (key.intValue() <
		    ((Integer)(orderedKeys.elementAt(i))).intValue()) {
		    slot = i;
		    break;
		}
	    }
	    if (slot > -1) {
	        orderedKeys.insertElementAt(key, slot);
	    } else {
	        orderedKeys.addElement(key);
	    }
	}

	// loaded ordered servlets

	// Priorities IMO, should start with 0.
	// Only System Servlets should be at 0 and rest of the
	// servlets should be +ve integers.
	// WARNING: Please do not change this without talking to:
	// harishp@eng.sun.com (J2EE impact)

	for (int i = 0; i < orderedKeys.size(); i ++) {
	    Integer key = (Integer)orderedKeys.elementAt(i);
	    Enumeration sOnLevel =  ((Vector)loadableServlets.get( key 
)).elements();
	    while (sOnLevel.hasMoreElements()) {
		String servletName = (String)sOnLevel.nextElement();
		ServletWrapper  result = ctx.getServletByName(servletName);

		if( ctx.getDebug() > 0 ) ctx.log("Loading " + key + " "  + servletName );
		if(result==null)
		    System.out.println("Warning: we try to load an undefined servlet " + 
servletName);
		else {
		    try {
			if( result.getPath() != null )
			    loadJsp( ctx, result );
			else
			    result.loadServlet();
		    } catch (Exception ee) {
			String msg = sm.getString("context.loadServlet.e",
						  servletName);
			System.out.println(msg);
		    }
		}
	    }
	}
	}
}
-----end code>
This code fix ensures that if the Hashtable was not set up by a previous 
call to this method, then it will commence loading servlets.  Otherwise, if 
loadableServlets is non-null, then this method has been called before so 
skip the initialization process.
I hope I have helped here, please let me know.  You can reach me either at 
this address or dmartens@ca.ibm.com .  Thankyou for your time.
________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com


Mime
View raw message