Re: How to stop Java HTTP server
 
On Wed, 13 Oct 2010, Shiladitya wrote:
I need a way to call httpServerExe.stop() from this thread.
So the main thread can be like this:
      httpServerExe.start();
      while(!terminated) {
         Thread.sleep(4000);
        }
        httpServerExe.stop();
That's the wrong way to do it. Rather than sleeping in a loop, this thread 
should wait on a monitor, and threads which want to stop the server should 
notify that monitor.
The main code would look like:
server.start();
synchronized (terminationLock) {
 	while (!terminated) terminationLock.wait();
}
server.stop();
Code which wants to stop it can go:
terminated = true;
synchronized (terminationLock) {
 	terminationLock.notify();
}
I have set up a handler for a URL (/terminateCommand). So if anyone send 
a request to this URL, the terminated flag should be set and main thread 
should stop the http server.
But I can't figure out how to set the flag from one of the handlers so 
that main thread gets interrupted.
The handler has to have a reference to the place the flag lives. If the 
flag is a static variable on a class, then it can go directly to the class 
by name:
MainClass.terminated = true;
synchronized (terminationLock) {
 	MainClass.terminationLock.notify();
}
Although of course it would be better to wrap that in a method:
MainClass.terminate();
class MainClass {
 	private static boolean terminated;
 	private static Object terminationLock;
 	public static void terminate() {
 		terminated = true;
 		synchronized (terminationLock) {
 			terminationLock.notify();
 		}
 	}
}
If it's on an object, then you will need to pass a reference to that 
object to the handler somehow, perhaps when you construct it.
void main(String... args) {
 	HttpServer server = HttpServer.create();
 	ServerController controller = new ServerController(server);
 	HttpHandler terminationHandler = new TerminationHandler(controller);
 	server.createContext("/terminate", terminationHandler);
 	new Thread(controller).start;
}
class ServerController implements Runnable {
 	private HttpServer server;
 	private boolean terminated;
 	private Object terminationLock = new Object();
 	public ServerController(HttpServer server) {
 		this.server = server;
 	}
 	public void run() {
 		server.start();
 		synchronized (terminationLock) {
 			try {
 				while (!terminated) terminationLock.wait();
 			}
 			catch (InterruptedException e) {}
 		}
 		server.stop();
 	}
 	public void terminate() {
 		terminated = true;
 		synchronized (terminationLock) {
 			terminationLock.notify();
 		}
 	}
}
You could dispense with the terminationLock by using the ServerController 
itself to wait and notify on, but i tend to steer way from that, and use 
private objects as locks, so that the wait/notify activity of the methods 
can't 'leak' across the interface.
An even better way to do this, actually, would be with a 
java.util.concurrent.CountDownLatch with a count of one:
class ServerController implements Runnable {
 	private HttpServer server;
 	private CountDownLatch latch = new CountDownLatch(1);
 	public ServerController(HttpServer server) {
 		this.server = server;
 	}
 	public void run() {
 		server.start();
 		try {
 			latch.await();
 		}
 		catch (InterruptedException e) {}
 		server.stop();
 	}
 	public void terminate() {
 		latch.countDown();
 	}
}
tom
-- 
you can't feel your stomack with glory -- Czako