I have embedded Jetty into my Eclipse RCP application successfully.
In my RCP application, when user click some button, a browser will be opened and some servlet page shown. The jsp files are in a separated directory, it is a angulajs web application.
I am trying to shutdown embedded Jetty server from Eclipse UI plugin when user closes the RCP.The server is started in a class named Workshop which is part of web project, so I dont have access to Server instance to call, server.stop() from Eclipse UI Plugin.I have tried below code, but in vein.
1>Configure ShutdownHook to Workshop class of web project
server = new Server();
server.setConnectors(new Connector[] { connector });
server.setHandler(handlers);
server.start();
handlers.addHandler(new ShutdownHandler(server, "abc"));
server.setStopAtShutdown(true);
server.setGracefulShutdown(7_000);
ShutdownThread.getInstance().run();
2> In my Eclipse UI Plugin, I have added
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
URL url = new URL("http://localhost:" + resultPortNo + "/shutdown?token=" + shutdownCookie);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.getResponseCode();
logger.info("Shutting down " + url + ": " + connection.getResponseMessage());
} catch (SocketException e) {
// logger.debug("Not running");
// Okay - the server is not running
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
HtppUrlConnection throws 404-NotFound response code.So Jetty server is still running. How do we handle embedded Jetty shutdown from Eclipse UI Plugin.
I did read lot of articles, but cannot find answer to my question.
Any help will be appreciated.Thank you.
Problem : Every time jettyServer.stop was called, Interrupt Exception was thrown and jetty server continued to run.
Solution : (1) Added Executor Service with daemon thread in the Servlet code to stop the Jetty server
JettyShutdownServlet.js
-----------------------
ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
pool.execute(new Runnable() {
#Override
public void run() {
if (null != jettyServer) {
try {
jettyServer.stop();
jettyServer.join();
} catch (Exception e) {
logger.info("Error when stopping Jetty: " + e.getMessage());
}
}
}
});
(2) Adding the servlet inside the Jetty startup code.
servletContextHandler.addServlet(new ServletHolder(new JettyShutdownServlet(server)), "/shutdown");
(3) Adding shutdownhook to Eclipse UI class
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
String shutdownurl = "http://localhost:" + resultPortNo + "/api/shutdown";
URL url = new URL(shutdownurl);
HttpURLConnection connection =(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
try {
connection.getResponseCode();
connection.disconnect();
} catch (SocketException e) {
// logger.debug("Not running");
// Okay - the server is not running
connection.disconnect();
}
} catch (Exception x) {
// exception during shutdown
Activator.error("Unable to shutdown Jetty Server.\n" + x.getMessage());
}
}
});
This solved my problem and hope it will be of some help to others.
Related
I need to start a filewatcher service at the server start. The file watcher service starts in an infinite while loop. So I have started a thread to start the watch service in a loop by overriding the servlet init method. Now when I shutdown tomcat, this thread that is running the loop gets killed abrouptly. There is an error in tomcat logs which says that there is a memory leak issue.Is there a way to stop this thread when the server shutsdown
I have tried to override the destroy method and make while loop condition to false. But I noticed that the destroy method is not getting executed when the server shuts down.
public static void startFileWatcher() throws InterruptedException {
Runnable r = () -> {
try {
while (!exit) {
System.out.println("Exit flag: " + exit);
if (FileWatcherUtil.isFileChanged()) {
System.out.println("file is changed");
Thread.sleep(2000);
InstantiateSystemProperties.destroy();
System.out.println("Initializing new system properties");
SystemPropertiesConfigurer.loadNewXml();
InitializeLogger.resetLogger();
InstantiateSystemProperties.initializeLoggerObject();
NotificationQueue.resetQueue();
InstantiateSystemProperties.startThreadPool();
Thread.sleep(2000);
}
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
logger.error("Exception in custom init(): ", e);
}
};
Thread t = new Thread(r);
t.start();
t.setDaemon(true);
}
public static void stopThread(){
System.out.println("stopping th thread *********************************************************8");
SystemPropertiesConfigurer.exit =true;
}
Servlet destroy:
#Override
public void destroy() {
System.out.println(".........destroy method invoked.......");
InstantiateSystemProperties.destroy();
SystemPropertiesConfigurer.stopThread();
}
I have the following piece of code to start a basic Embedded Grizzly server running with Jersey.
private static void startServer() {
ServerResourceConfiguration configuration = new ServerResourceConfiguration();
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
URI.create(BASE_URI),
configuration,
false,
null,
false);
server.start();
if (System.in.read() > -2) {
server.shutdownNow();
}
}
This does not look like production level way to stop a server.
What is the best practice to gracefully shut it down ?
I guess a terminal command of some sort. Killing the process would work but it is not very graceful.
I am using Gradle on this project and runs the server with the gradle run command.
Could a Gradle task do the job?
Also I have seen this about gracefully terminating a grizzly transport:
http://grizzly-nio.net/2013/08/gracefully-terminating-a-grizzly-transport/
But I am not sure if I would need to use it. I don't understand how to use it.
EDIT: I came across this post:
https://stackoverflow.com/a/15391081/3982755
Is that an acceptable way to terminate an Http server in a production environment?
There is no answer so I will post my own, I implemented it with a Shutdown Hook and it works very well.
The server will wait for all connections to terminate before shutting down.
To avoid getting blocked for ever if a connection never terminates, we set a grace period(60 seconds)
After the grace period the server will force termination of all connections
Here is the code for the hook to be run when the server receives a SIGINT or SIGTERM signal.
public class GrizzlyServerShutdownHookThread extends Thread {
public static final String THREAD_NAME = "Grizzly Server Shutdown Hook";
public static final int GRACE_PERIOD = 60;
public static final TimeUnit GRACE_PERIOD_TIME_UNIT = TimeUnit.SECONDS;
private final HttpServer server;
/**
* #param server The server to shut down
*/
public GrizzlyServerShutdownHookThread(HttpServer server) {
this.server = server;
setName(THREAD_NAME);
}
#Override
public void run() {
LOG.info("Running Grizzly Server Shutdown Hook.");
LOG.info("Shutting down server.");
GrizzlyFuture<HttpServer> future = server.shutdown(GRACE_PERIOD, GRACE_PERIOD_TIME_UNIT);
try {
LOG.info(format("Waiting for server to shut down... Grace period is %s %s", GRACE_PERIOD, GRACE_PERIOD_TIME_UNIT));
future.get();
} catch(InterruptedException | ExecutionException e) {
LOG.error("Error while shutting down server.", e);
}
LOG.info("Server stopped.");
}
}
Then I register the Hook into the RunTime object this way when I setup the server:
Runtime.getRuntime().addShutdownHook(
new GrizzlyServerShutdownHookThread(server)
);
And finally, I start the server this way:
try {
server.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
// wait for a SIGINT (Ctrl+c) signal to shut down
try {
LOG.info("Press CTRL^C to exit..");
Thread.currentThread().join();
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
I'm using Netty 4.0.26.Final along with Tomcat 8 to implement an embedded TCP server inside a web application.
The problem is that when I stop Tomcat I'm getting this message :
The web application [app] appears to have started a thread named
[nioEventLoopGroup-2-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278)
sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:622)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:310)
io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
I've tried using this class to shutdown the threads before closing tomcat but I'm still having the same problem.
#Component
public class MyAppServletContextListener implements ServletContextListener{
#Override
public void contextInitialized(ServletContextEvent arg0) {
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
TrackingDaemon trackingDaemon= (TrackingDaemon) ApplicationContextProvider.getBean("trackingDaemon");
trackingDaemon.bossGroup.shutdownGracefully();
trackingDaemon.workerGroup.shutdownGracefully();
}
}
BossGroup and workerGroup are:
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
Any help will be appreciated..
I have had this problem with netty 4 and tomcat 7 and solved it by capturing the future event from shutdownGracefully() and awaiting its completion.
The method below is called when closing down the application.
private void stopChannel() {
log.trace("Stopping server socket on port '{}'", port);
sendMessageService.deregisterMessageSender(endpointId);
try {
for (Channel channel : channels) {
if (channel != null) {
channel.close();
}
}
serverChannel.close().sync();
log.trace("Server socket on port '{}' stopped.", port);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
Future<?> fc = connectionGroup.shutdownGracefully();
Future<?> fw = workerGroup.shutdownGracefully();
try {
fc.await(); // when shutting down in tomcat waits for the netty threads to die
fw.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.trace("Server workerGroup has shutdown successfully on port '{}'", port);
}
}
I guess you will need to do:
trackingDaemon.bossGroup.shutdownGracefully().syncUninterruptibly();
trackingDaemon.workerGroup.shutdownGracefully().syncUninterruptibly();
What is the impact for using Daemon threads or Normal Threads in my
Play Application. I am having some Akka Scheduler, and Quarts Schedulers. These are being start When Application start. My App is running in Dev mode, and whenever i made changes to my Source Code, it restart's / Auto Reload application that Cause Thread DeadLock. What is the best way to stopping these Threads.
Is it good to use Daemon Threads here ?
Will System.exit(0) will be Useful here ?
Is any Other way to stopping these running/waiting threads that are sleeping for a particular time in scheduling ?
I'm trying to do something like:
#Override
public void onStart(Application app) {
Akka.system().scheduler().schedule(Duration.create(2000, TimeUnit.MILLISECONDS), Duration.create(60000, TimeUnit.MILLISECONDS),
() -> {
String url = Play.application().configuration().getString("localloadbalancer.ip");
url = url + "initCallOut";
Logger.info("Calling initcall from global.java::" + url);
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
try {
HttpResponse response = client.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
Logger.info("Status Code::" + statusCode);
if (statusCode == 200) {
//Do stuff here
} else {
//retry
}
} catch (IOException ex) {
Logger.error("Error in Initcall::" + ex.getMessage());
}
}, Akka.system().dispatcher());
// Quartz scheduler starting here
try {
QuartzScheduler.startScheduler();
}
catch (Exception ex){
System.out.println("Scheduler Exception::"+ex.getMessage());
}
}
I am running an application using tomcat as the container - at start up, several files need to be found and loaded. However, if one of these files doesn't exist or can't be read, I want to log the exception and exit the app, which I am currently doing using System.exit(1)... however, is there a better way of doing this?
Any help is much appreciated!
I dont know if this fits your needs but it actually worked for my app. The listener is
called at application start, if it is declared in your web.xml:
<listener>
<listener-class>your.package.TestServletListener</listener-class>
</listener>
There you can do testing and call the ShutdownThread if one fails. It will connect to Tomcats shutdown port and send the shutdown command as a String:
public class TestServletListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("Starting app, running 5 tests ...");
// do tests ...
for (int i = 0; i < 5; i++) {
System.out.println("testing ... " + i);
waitFor(1000);
}
// If a test failed call:
System.out.println("test failed!");
new ShutdownTask().start();
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.print("Stopping app, cleaning up (takes 3 sec) ... ");
waitFor(3000);
System.out.println("done");
}
private void waitFor(int i) {
try {
Thread.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
class ShutdownTask extends Thread {
#Override
public void run() {
try {
Socket s = new Socket("127.0.0.1", 8015);
PrintStream os = new PrintStream(s.getOutputStream());
os.println("shutdown");
s.close();
System.out.println("Shutting down server ...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You need to make sure that the shutdown port and shutdown command are in sync with your Tomcats server.xml:
...
<Server port="8015" shutdown="shutdown">
...
For example, you could pass them as context parameters in your web.xml. Like System.exit(...) this is not going to work (without further config) if Tomcat is running with a SecurityManager.
You should consider embedding Tomcat, i.e. have your AppStarter class perform those checks and then start Tomcat:
public class AppStarter {
public static void main(String[] args) {
// Check if everything is ready...
if (file1.exists() && file2.exists() && condition3) {
// Start Tomcat here.
}
else {
System.out.println("Invalid configuration.");
}
}
}
You can find how to embed Tomcat tutorials on the Internet.