Bug 45774 - jspDestroy called after deployment, the second jspInit follows
Summary: jspDestroy called after deployment, the second jspInit follows
Status: RESOLVED DUPLICATE of bug 41606
Alias: None
Product: Tomcat 5
Classification: Unclassified
Component: Unknown (show other bugs)
Version: 5.5.27
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-09-10 07:58 UTC by Brian Burch
Modified: 2009-03-27 02:43 UTC (History)
2 users (show)



Attachments
demo jsp and servlet with index.html. Install into $CATALINA_HOME/webapps (13.02 KB, application/octet-stream)
2008-09-10 07:58 UTC, Brian Burch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Brian Burch 2008-09-10 07:58:26 UTC
Created attachment 22549 [details]
demo jsp and servlet with index.html. Install into $CATALINA_HOME/webapps

I am not sure if this is a duplicate of https://issues.apache.org/bugzilla/show_bug.cgi?id=41606, but it sounds a bit different and applies to 5.5.26.

The jsp is deployed without explicit web.xml definition, so it is loaded when the first client request arrives. The call sequence is usually (but not always) as follows:

jspInit
_jspService
jspDestroy
jspInit
_jspService
_jspService
etc..

This is hard to program around when using jspInit to set up a complex set of background processes. They get torn down unnecessarily, only to be loaded up immediately afterward. However, there is enough variability to make it dangerous to assume the first jspDestroy will always be followed by jspInit - it might be a REAL jspDestroy and the cleanup is really necessary.

I have attached a war that demonstrates the problem. There is an index.html that will run either a demo servlet (which works properly with init/destroy) or a demo jsp (which usually fails). The apps display the call sequence graphically, but entries are also written to the catalina log file.
Comment 1 Mark Thomas 2008-09-15 12:43:37 UTC
Thanks for the test case. A good test case makes it so much easier to investigate an issue.

Unfortunately in this case I can't reproduce this on the latest 5.5.x code with your test case. I also tested trunk with the same result.

I would point out that Servlet containers are free to create and destroy servlet instances as they see fit. See SRV.2.3.4 for the exact wording.

I would guess that for your use case a ServletContextListener would be a better choice.
Comment 2 Brian Burch 2008-10-07 06:56:31 UTC
I made a clean install of the new 5.5.27 release on a different machine. I added my demo war and started tomcat. The servlet still works as designed and the jsp still flags the antisocial behaviour.... the jsp was destroyed after the first service and then was immediately re-initialised.

I then stopped tomcat and restarted it using the already deployed webapp. This time (to my surprise) the jsp was not destroyed.

I used the tomcat manager to stop and start the webapp. It worked fine.

I undeployed it and re-copied the war to automatically deploy. 2 services and then an unnecessary destroy/init.

I reloaded the webapp, and it worked fine.

I copied the war to get it redeployed - 2 services and then an unnecessary destroy/init.

I have no problem with the specification allowing Servlet containers to create and destroy servlet (and jsp) instances when necessary, but this behaviour is just perverse and wasteful of resources. The whole point of init/destroy is to be able to setup a shared pool of "expensive" resources that need to be conserved over a long period of time.

I can do more work on this if you would like. At the moment, the evidence points to some kind of timing issue related to deployment of a new war and subsequent compilation of the jsp.

My earlier tests with 5.5.26 (and older releases) on other machines showed the perverse behaviour could occur after a simple tomcat stop/start cycle (i.e. no jsp compilation), but I have no evidence of this happening on a clean install of the latest version of tomcat.

Regards,

Brian
Comment 3 Mark Thomas 2008-10-07 07:47:51 UTC
Thanks for the additional testing - it explains why I couldn't reproduce it. I'll take another look at what is going on.

If you need to create long-lived resources I really do encourage you to look at ServletContextListener.
Comment 4 Gerhard Kreutzer 2008-11-25 10:14:57 UTC
(In reply to comment #3)
> Thanks for the additional testing - it explains why I couldn't reproduce it.
> I'll take another look at what is going on.

I can confirm the behavior posted by Brian for Tomcat 5.5.20 and 5.5.27. After changing a JSP, the generated Servlet will be instantiated twice, so the described sequence init-destroy-init will appear.

I tested with the following JSP:
<%--
	Bug 45774 - jspDestroy called after deployment, the second jspInit follows
	Bug 41606 - The jspInit method is called twice. 
--%>
<jsp:declaration>
	int counter = 0;
	private static long st = System.currentTimeMillis();
	private long it = System.currentTimeMillis();
	private long time = it - st;
	private static Object firstInstance;
	private Object secondInstance;
	
	public void init() throws ServletException {
		long ltime = System.currentTimeMillis() - st;
		System.out.println("init: " + this + ", time=" + time);
		if (time == 0) firstInstance = this;
		if (firstInstance != this) secondInstance = this;
	}
</jsp:declaration>

<html>
  <head>
    <title>InitTwice.jsp</title>
  </head>
  <body>
     <h1>InitTwice.jsp</h1>
    counter=<jsp:expression>++counter</jsp:expression>
    <br>
    current page=<jsp:expression>page</jsp:expression>
    <hr>
    first=<%= firstInstance %>
    <br>
    second=<%= secondInstance %>
    <br>
    time=<%= time %>
  </body>
</html>

Gerhard
 

Comment 5 Mark Thomas 2009-03-27 02:43:34 UTC
The original report contains a patch. The dup contains a test case.

*** This bug has been marked as a duplicate of bug 41606 ***