1

I have a Servlet which is annotated like this:

@WebServlet(value="/MyServiceServlet", loadOnStartup=1)

This results in the Servlet being instantiated on application start and its init() method being called. Perfect! (In the init() method, a Thread is started to perform some db maintenance which runs each hour)

Now, on certain end user actions, I reach the Servlet by using getServletContext().getRequestDispatcher("/MyServiceServlet").include(request, response) to trigger some other db stuff, but the first time I try this, my Servlet gets instantiated one more time and the init() method is called (of course), which results in two similar Threads running. Not perfect!

It seems as if the loadOnStartup=1 does not put the Servlet in the Servlet Context, hence when I try to reach it by the Request Dispatcher it needs to be instantiated.

How can this be? How to fix so I just get one instance of my Servlet? I need it to be started along the application, as the Service started in the init() should run immediately.

The application is deployed on Tomcat 7.0.57.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Janus Engstrøm
  • 103
  • 1
  • 12
  • Sounds like a bug in Tomcat. What if you get the RequestDispatcher via HttpServletRequest itself the usual way? Getting it via ServletContext is only necessary when it's in a different ServletContext (i.e another webapp deployed on same server; you then usually get the ServletContext of interest via ServletContext#getContext()). – BalusC Aug 05 '15 at 12:07
  • @BalusC I have tried to both use the request object to get the RequestDispatcher and use pre 3.x methodology to map the Servlet through web.xml to no avail. After a bit more debugging, it seems to be the call to .include(request, response) that creates yet another instance of my Servlet. – Janus Engstrøm Aug 06 '15 at 00:01

1 Answers1

0

(In the init() method, a Thread is started to perform some db maintenance which runs each hour)

O good lord, wonderful, do you even believe in memory leak? running a thread in servlet?! you need to do it by context-listener(javax.servlet.ServletContextListener), not directly, it's not safe.

public class run_thread implements ServletContextListener{
    @Override
        public void contextInitialized(ServletContextEvent sce) {System.out.println("Init: daemon stuffs");/*run teh trhead*/}
        @Override public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("Hult: daemon stuffs");/*hult teh trhead*/
        }
    }

and don't forge to register it bi web.xml

<listener>
    <listener-class>pack.run_thread</listener-class>
</listener>

More better solution let another external application do db maintain, or at least invoke the servlet path to do so intervally.

Now, on certain end user actions, I reach the Servlet by using

What is the user action? how? using another servlet? what about requets.getRequestDispatcher() instead of getServletContext()

You may share the servlet code, would be appreciated.