public static void main(String[] args) { loadEnvironment(args); final CountDownLatch latch = new CountDownLatch(1); final Container container = new Container(); container.addStatusChangeListener( new Container.StatusChangeListener() { @Override public void onChange(Container.StatusChangeEvent changeEvent) { // if an event occurs that causes the container to shut itself // down, also shut down the application. An event could be a // failure of some sort, or it could be that the job completed. if (Container.Status.STOPPED == changeEvent.getStatus()) { doStop(latch, container); } } }); Thread shutdownThread = new Thread() { @Override public void run() { // if a control-c occurs, properly halt the container. doStop(latch, container); } }; // add a control-c hook that stops the container cleanly... Runtime.getRuntime().addShutdownHook(shutdownThread); try { container.start(); // the latch should be waited upon in only two cases: // control-c was triggered, or the container itself // shutdown, b/c perhaps the test completed. try { latch.await(); } catch (InterruptedException e) { // ignore } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception | Error e) { panic(Exceptions.toStringAllCauses(e), e); } finally { try { Runtime.getRuntime().removeShutdownHook(shutdownThread); } catch (IllegalStateException e) { // ignore shutdown in progress message } } }