4
votes

I have an issue with a standalone Tomcat server (not linked with Apache).

When Tomcat starts up, the init() method of the servlet is getting called twice, i.e., two servlets are starting up. Even more worrying is that these appear to be loaded by different classloaders - there is only one Java process running on the command line so it's not multiple Tomcats.

web.xml snippet (the servlet is only configured once, and only configured in the webapp web.xml):

<servlet>
  <servlet-name>LenderInterfaceServlet</servlet-name>
  <display-name>Lender Interface Servlet</display-name>
  <servlet-class>com.foobar.lender.webservice.server.LenderInterfaceServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

I put some logging in the init method, and created a singleton class called RatesPoller that the init tries to get an instance of. From the logs we can see that the singleton instances are different:

LenderInterfaceServlet - [init] Start: com.foobar.lender.webservice.server.LenderInterfaceServlet@56d90453
LenderInterfaceServlet - [init] Starting up the Rates pollers.
LenderInterfaceServlet - [init] Got com.foobar.lender.framework.rates.RatesPoller@ae0e515
LenderInterfaceServlet - [init] Start: com.foobar.lender.webservice.server.LenderInterfaceServlet@1b0c6cfc
LenderInterfaceServlet - [init] Starting up the Rates pollers.
LenderInterfaceServlet - [init] Got com.foobar.lender.framework.rates.RatesPoller@5759780d

So we have two distince servlets, and two distinct singleton pollers.

I suspect this means that Tomcat is launching two instances of the webapp that is stored in the Tomcat webapps folder. Obviously when you want to launch something that only one will be running, this is a problem, and I need to work out how to ensure that Tomcat doesn't run the webapp twice!

If anyone has any ideas ...

Code:

public class RatesPoller {

  private static RatesPoller instance;

  private RatesPoller() {}

  public static RatesPoller getInstance() {
    if (instance == null) {
        instance = new RatesPoller();
    }
    return instance;
  }

  public RatesPoller clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException("Singleton. Tsk!");
  }
}

and the init() method in LenderInterfaceServlet:

public class LenderInterfaceServlet extends AxisServlet {
  // ...
  @Override
  public void init() throws ServletException {
    logger.info("[init] Start: " + this);
    super.init();
    logger.info("[init] Starting up the Rates pollers.");
    RatesPoller rp = RatesPoller.getInstance();
    logger.info("[init] Got " + rp);
  }
  // ...
}
4
"Singleton. Tsk!" made my day :)ADTC

4 Answers

4
votes

Tomcat is autodeploying anything in webapps, and also deploying according to server.xml. Just remove your webapp from webapps to avoid double loading.

1
votes

There is a bug in your code. Your singleton is not thread-safe. That getInstance() method should be synchronised. Otherwise you are liable to construct multiple instances.

0
votes

I would set a breakpoint in the init() method and then look at the stack to see where the calls are coming from.

-1
votes

If the init() method fails, it may be called again on a subsequent get. Did you check the catalina.out file to make sure that the init() call is not being aborted for some reason?