Web applications

The RequestExecutor contains a number of internal threads used for sending and receiving requests to RoboServers, as well as pinging each known RoboServer at regular intervals. These threads are all marked as daemon, which means that they don't prevent the JVM from stopping when the main thread exists, check Thread JavaDoc for details on daemon threads.

If you use the RequestExecutor inside a web application, the JVM has a longer lifespan than your web application, and you can deploy and un-deploy your web application while the web container is running. This means that a web application is responsible for stopping any threads that it has created, if it does not a memory leak will be created when you un-deploy the web application. The memory leak occurs because any objects referenced by running threads can't be garbage collected until the threads stop, so if these threads are not stopped when the application is un-deployed, they will never be garbage collected.

If you use the RequestExecutor inside a web application your code is responsible for shutting down these internal threads, this is done by calling Request.shutdown() or RequestExecutor.shutdown() if your code created the RequestExecutor explicitly.

This example show you how to use a ServletContextListener to shutdown the API correctly when a web application is un-deployed. You must define the context listener in your applications web.xml.


import com.kapowtech.robosuite.api.java.repository.construct.*;
import com.kapowtech.robosuite.api.java.rql.*;
import com.kapowtech.robosuite.api.java.rql.construct.*;

import javax.servlet.*;

public class APIShutdownListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        RoboServer server = new RoboServer("localhost", 50000);
        Cluster cluster = new Cluster("MyCluster", new RoboServer[]{ server}, false);
        try {
            Request.registerCluster(cluster);
        }
        catch (ClusterAlreadyDefinedException e) {
            throw new RuntimeException(e);
        }
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        Request.shutdown();
    }
}
                                  

proper shutdown in web application


contextDestroyed is called when the web container un-deploys the application. Here we call Request.shutdown() to ensure that all internal threads in the hidden RequestExecutor are stopped correctly.

Since contextInitialized can't throw any unchecked exceptions we have to wrap the ClusterAlreadyDefinedException in a RunTimeException. Developers may be tempted to ignore the ClusterAlreadyDefinedException at this location, because they claim that it can't be thrown, as our application has not defined any other clusters. However due to the class loader hierarchy in java web containers it is actually possible to get this exception if the application is deployed twice. It will however only occur if the API jar file was loaded by a common class loader and not by the individual application's class loader.