Bug 53301 - Servlet init method called twice with embedded Tomcat
Summary: Servlet init method called twice with embedded Tomcat
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API (show other bugs)
Version: 7.0.27
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-05-26 21:36 UTC by Jeff MAURY
Modified: 2012-11-21 08:15 UTC (History)
1 user (show)



Attachments
Sample Maven project with a test (7.54 KB, application/zip)
2012-05-28 19:26 UTC, Jeff MAURY
Details
SampleServlet.java (1.38 KB, text/plain)
2012-05-28 21:15 UTC, Konstantin Kolinko
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jeff MAURY 2012-05-26 21:36:56 UTC
When using embedded Tomcat, the servlet init method is called twice by the container. This has been seen with an Apache DirectMemory unit test. I have checked with a normal Tomcat launched by the Tomcat Maven plugin (mvn tomcat7:run) and in this case, the init method is correctly called once.
Comment 1 Mark Thomas 2012-05-26 22:30:36 UTC
This is user error. Use the users mailing list to debug.
Comment 2 Jeff MAURY 2012-05-27 19:17:04 UTC
Don't understand why you claim it is a user error
Comment 3 Konstantin Kolinko 2012-05-28 11:35:23 UTC
> Don't understand why you claim it is a user error

It is your responsibility to provide enough details to prove and reproduce the issue. Your report is lacking and there are several statements in it that appear to be based on false assumptions.

You should ask for help on the users list to better diagnose your problem. Bugzilla is not a support forum.

FYI:
1. tomcat7:run uses embedded Tomcat 
2. init() can be called as many times as many instances of a Servlet are there
Comment 4 Jeff MAURY 2012-05-28 19:25:21 UTC
Sorry, but the intent was not to get support but rather to signal the Tomcat community of the problem.
I agree I should have given more materials about the problem: so you should find now a sample Maven project that demonstrate the problem. Just run 'mvn test' and you should get the error.
This has been tested against 7.0.27, 7.0.26 and 7.0.25 (using the tomcatVersion property)
Comment 5 Jeff MAURY 2012-05-28 19:26:13 UTC
Created attachment 28844 [details]
Sample Maven project with a test
Comment 6 Konstantin Kolinko 2012-05-28 21:13:19 UTC
Ok. Reproducible.

I modified your SampleServlet to print stacktrace when init() is called, like this:
[[[
    @Override
    public void init( ServletConfig config )
        throws ServletException
    {
        log.info( "Init called, config="+config, new Throwable() );
        super.init( config );
...
]]]

I'll attach full source later. There are two calls to init() in a row and stack traces are the following:
[[[
00:58:32.187 [main] INFO  init - Tomcat started on port:4396
00:58:32.609 [http-bio-auto-1-exec-1] INFO  init - Init called, config=org.apache.catalina.core.StandardWrapperFacade@15e2075
java.lang.Throwable: null
 at org.apache.tomcat.tomcat53301.SampleServlet.init(SampleServlet.java:43) [classes/:na]
 at org.apache.catalina.startup.Tomcat$ExistingStandardWrapper.loadServlet(Tomcat.java:854) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:857) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:136) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [na:1.6.0_32]
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [na:1.6.0_32]
 at java.lang.Thread.run(Thread.java:662) [na:1.6.0_32]
00:58:32.625 [http-bio-auto-1-exec-1] INFO  init - Init called, config=org.apache.catalina.core.StandardWrapperFacade@15e2075
java.lang.Throwable: null
 at org.apache.tomcat.tomcat53301.SampleServlet.init(SampleServlet.java:43) [classes/:na]
 at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:877) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:136) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [na:1.6.0_32]
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [na:1.6.0_32]
 at java.lang.Thread.run(Thread.java:662) [na:1.6.0_32]
]]]

Essentially it is the same single call to
org.apache.catalina.core.StandardWrapper.allocate()
and it calls init() twice with the following stack traces
a)
[[[
 at org.apache.tomcat.tomcat53301.SampleServlet.init(SampleServlet.java:43) [classes/:na]
 at org.apache.catalina.startup.Tomcat$ExistingStandardWrapper.loadServlet(Tomcat.java:854) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:857) [tomcat-embed-core-7.0.27.jar:7.0.27]
]]]
b)
[[[
 at org.apache.tomcat.tomcat53301.SampleServlet.init(SampleServlet.java:43) [classes/:na]
 at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266) [tomcat-embed-core-7.0.27.jar:7.0.27]
 at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:877) [tomcat-embed-core-7.0.27.jar:7.0.27]
]]]

The second call happens because StandardWrapper#instanceInitialized flag is still false, but init() has already been called by Tomcat$ExistingStandardWrapper.loadServlet().

So either Tomcat$ExistingStandardWrapper should not call init(), or it should update the flag when doing so.
Comment 7 Konstantin Kolinko 2012-05-28 21:15:20 UTC
Created attachment 28845 [details]
SampleServlet.java

SampleServlet.java update.
Added stackstace printing in init(). Overwrote destroy().
Comment 8 Mark Thomas 2012-06-01 10:19:36 UTC
Thanks for the analysis Konstantin - that made the fix very simple.

Fixed in trunk and 7.0.x and will be included in 7.0.28 onwards. I also included a test case for this.