@Override public void bind(InetSocketAddress addr, int backlog) throws IOException { // check if there is already a connector listening Collection<NetworkConnector> connectors = _server.getBeans(NetworkConnector.class); if (connectors != null) { for (NetworkConnector connector : connectors) { if (connector.getPort() == addr.getPort()) { if (LOG.isDebugEnabled()) LOG.debug("server already bound to port " + addr.getPort() + ", no need to rebind"); return; } } } if (_serverShared) throw new IOException("jetty server is not bound to port " + addr.getPort()); this._addr = addr; if (LOG.isDebugEnabled()) LOG.debug("binding server to port " + addr.getPort()); ServerConnector connector = new ServerConnector(_server); connector.setPort(addr.getPort()); connector.setHost(addr.getHostName()); _server.addConnector(connector); _connectors.put(addr.getHostName() + addr.getPort(), connector); }
@Test public void testGracefulShutdown() throws Exception { ObjectMapper objectMapper = Jackson.newObjectMapper(); Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); MetricRegistry metricRegistry = new MetricRegistry(); Environment environment = new Environment( "test", objectMapper, validator, metricRegistry, ClassLoader.getSystemClassLoader()); CountDownLatch requestReceived = new CountDownLatch(1); CountDownLatch shutdownInvoked = new CountDownLatch(1); environment.jersey().register(new TestResource(requestReceived, shutdownInvoked)); final ScheduledExecutorService executor = Executors.newScheduledThreadPool(3); final Server server = http.build(environment); ((AbstractNetworkConnector) server.getConnectors()[0]).setPort(0); ScheduledFuture<Void> cleanup = executor.schedule( new Callable<Void>() { @Override public Void call() throws Exception { if (!server.isStopped()) { server.stop(); } executor.shutdownNow(); return null; } }, 5, TimeUnit.SECONDS); server.start(); final int port = ((AbstractNetworkConnector) server.getConnectors()[0]).getLocalPort(); Future<String> futureResult = executor.submit( new Callable<String>() { @Override public String call() throws Exception { URL url = new URL("http://localhost:" + port + "/app/test"); URLConnection connection = url.openConnection(); connection.connect(); return CharStreams.toString(new InputStreamReader(connection.getInputStream())); } }); requestReceived.await(); Future<Void> serverStopped = executor.submit( new Callable<Void>() { @Override public Void call() throws Exception { server.stop(); return null; } }); Connector[] connectors = server.getConnectors(); assertThat(connectors).isNotEmpty(); assertThat(connectors[0]).isInstanceOf(NetworkConnector.class); NetworkConnector connector = (NetworkConnector) connectors[0]; // wait for server to close the connectors while (true) { if (!connector.isOpen()) { shutdownInvoked.countDown(); break; } Thread.sleep(5); } String result = futureResult.get(); assertThat(result).isEqualTo("test"); serverStopped.get(); // cancel the cleanup future since everything succeeded cleanup.cancel(false); executor.shutdownNow(); }