I have created an undertow server with a servlet deployment following the methods in the documentation here:
http://undertow.io/documentation/servlet/deployment.html
I am now trying to stop the server and the application in the servlet.
Calling server.stop()
makes the server unavailable on the specified port, but when I call server.start()
again, the application is immediately available (if it had been stopped, it would have taken some time to start up again). I can also see that the memory of the server is not freed when calling server.stop
. I have tried various combinations including calling deploymentManager.undeploy()
all with the same effect.
I have searched the documentation for any clues and come up empty. I wonder if anyone else has any clues? Below is the source code in its current state (please note that I am not a Java developer so there will be plenty of garishness):
package org.locee;
import io.undertow.Undertow;
import io.undertow.Undertow.Builder;
import io.undertow.Handlers;
import io.undertow.util.Headers;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.HttpHandler;
import static io.undertow.servlet.Servlets.defaultContainer;
import javax.servlet.ServletException;
public class LoceeUndertowServer {
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
private int port;
private String host;
public LoceeUndertowServer( DeploymentInfo servletInfo, int port, String host ) {
this.servletInfo = servletInfo;
this.port = port;
this.host = host;
}
public void start() throws ServletException {
deploymentManager = defaultContainer().addDeployment( servletInfo );
deploymentManager.deploy();
HttpHandler httpHandler = deploymentManager.start();
PathHandler pathHandler = Handlers.path( Handlers.redirect( "/" ) ).addPrefixPath( "/", httpHandler );
Builder builder = Undertow.builder();
builder.addHttpListener( port, host );
builder.setHandler( pathHandler );
undertowServer = builder.build();
undertowServer.start();
}
public void shutdown() throws ServletException {
deploymentManager.undeploy();
defaultContainer().removeDeployment( servletInfo );
undertowServer.stop();
}
public void restart() throws ServletException {
shutdown();
start();
}
}
You are retaining what is known as a strong reference to the Undertow components and anything they also directly reference. The references are stored within the following fields:
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
This is less of an issue with Undertow and more how the JVM functions. The garbage collector begins at set of roots (think of these as the threads on the JVM) and traverses all references to other objects. Once it has completed it's traversal then all inaccessible objects are reclaimed. This is the logical view of the whole process. Collection timings are up to the JVM, as well as generations. The following code will remove the references to the components if you place them in the #shutdown() method:
deploymentManager = null;
undertowServer = null;
servletInfo = null;
Note: once you do this you will not be able to restart.