I have a simple Jetty server that runs a webapp from a web.xml. That file has some servlets, and a ServletContextListener. When everything starts up fine, this works perfectly, including graceful shutdown on exit.
But, if starting that webapp fails for some reason, I want the server to still gracefully shut down. That includes calling the contextDestroyed methods of the relevant ServletContextListeners.
WebAppContext context = ...;
Server server = ...;
server.start();
if (!context.isAvailable()) {
// startup failed
server.stop(); // I would expect this to call contextDestroyed
}
How do I get Jetty to properly clean up after itself?
If it matters, when running the same web application as a war in Tomcat, it works fine and actually shuts down correctly on a failed startup.
You don't say what version of Jetty you are running. I've checked against the most recent version of jetty, and the behaviour is as expected: if a servlet fails to initialise correctly, then the webapp is marked as unavailable, and when server.stop() is called, the contextDestroy listener method is called. Can you provide more details, such as jetty version, log output, at what point the webapp startup fails etc.
Related
Having implemented a ContextListener I can now happily deal with contextDestroyed events by closing down my connection pools and flushing my caches etc.
I was surprised recently when contextDestroyed was called at a time when my server was not being shut down - it seemed to be at some arbitrary time which I have not been able to track down.
Is there any defined event or set of circumstances that trigger contextDestroyed?
Should I ensure that everything I do when contextDestroyed is called is reversible? Do I need to make all my pools survive a destroyed/initialized cycle? Was I wrong to assume I would only get a contextDestroyed when Tomcat was being shut down or my war was being replaced?
Through a series of trial and error testing I have found that contextDestroyed() is called when;
The server is .WAR is being updated/removed.
The server is shutdown due to administrator intervention.
The server is shutdown due to a coding error. Something that would
terminate a non-server application termination.
If you are experiencing issue #3, as you are suggesting, I think the best possible course of action is to safely (be sure not to create an infinite loop) call contextInitialized() to ensure pools are recreated properly.
See: http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
contextDestroyed(ServletContextEvent sce): Receives notification that
the ServletContext is about to be shut down.
I.e., it gets called when a web application gets unloaded (e.g., you remove or replace a .war file from the web-apps folder OR unload it using the Tomcat server-manager).
I'm running a servlet in a tomcat container.
All is working correct, tomcat calls the init method of my Servlet and it starts correctly.
When I look at the Tomcat Web Application Manager - List Applications I see the running status is "true".
In the init function I want to check some important settings.
If a check fails, I throw a new ServletException. Now I thought that the running status would change to "false" but it didn't.
So my question is how to stop the servlet from a check in the init function.
Or maybe I just do it the wrong way.
Would like to get some help, thanks in advance
The Manager does not show the status of individual servlets but of the web application. Individual servlets can fail to start but that doesn't stop the web application from starting.
If you have some checks you want to perform that need to stop the web application starting then put those checks in the contextInitialized method of a ServletContextListener and throw a RuntimeException (or a subclass of it) if the checks fail.
I have a question similar to camel-file-consumer-template-threads-remaining-alive. I have a webapp running in a Tomcat container. I am using Camel version 2.10.4. In it I have I use the File component as a polling consumer. It is set up as follows:
from("/myDir"+
"?delete=true"+
"&startingDirectoryMustExist=true"+
"&scheduledExecutorService=#mySpringManagedExecutorService")
This runs fine as expected but when I attempt to stop Tomcat I get the following message:
SEVERE: The web application [/myapp] appears to have started a thread
named [MyExecuteService-0] but has failed to stop it. This is very likely to
create a memory leak.
After invoking the shutdown.sh script I invoke ps -ef | grep tomcat and the process is still running. If my app is not loaded or if I do not load this route in my app tomcat stops properly.
FYI, so the solution was posted on Nabble. This was that I needed to shutdown the executor service in Spring. I did this by adding a destory-method="shutdown" to the executor service.
FYI, I had set up the executor service this was so that I could have different thread names per route in a single context. Neither Spring nor Camel seems to provide this mechanism.
The Nabble thread is here
I have written a javaagent application to get the execution time of a java application and it works fine. i tried to use this application to get the execution time of a application hosted in tomcat server. i didn't get the required output. my javaagent code is from "http://www.ibm.com/developerworks/java/library/j-jip/" .
I have two doubts
1. how to filter out specific application hosted in tomcat and profile using javaagent.
2. how does javaagent detect the start and end of an application in tomcat.
Why does this need a java agent ? Use a ServletContextListener and record the time in contextInitialized() and contextDestroyed().
From the servlet 3.0 spec
Implementations of javax.servlet.ServletContextListener are invoked at
their contextInitialized method in the order in which they have been
declared, and at their contextDestroyed method in reverse order.
I want to have some method run, only after my WAR has been deployed to JBoss.
The problem: Currently I am using #PostConstruct to load saved schedules from the DB. The problem is that I am creating instances of the Schedulers from this method, which in turn is starting the Quartz schedulers, which is stopping JBoss from completing the deploy.
If there are no schedules to load, my WAR deploys fine, but if there are schedules they are causing the deploy to fail, because JBoss is "waiting" for the schedules to actually complete.
Is there some way to delay the method call until after it is fully deployed?
Or alternatively, is it possible to make Async calls on the Server (from the Server code)?
Java EE specification heavily refrain any thread manipulation outside facility provided by the application server.
You shouldn't in any case use a container manged thread in an infinite loop; the container expect the thread to be returned. Thread creation can still be done without too much collateral damage (if you don't put several apps on the server as the container won't be able to manage the resources between all the applications) but the any container thread must be returned.
In the new Jboss 7 there is some Java EE scheduling facilities (#Scheduling and timer, with possible persistent timer). A quick search show some example how to run Quartz in JBoss 7: How to enable Quartz scheduling in Jboss AS 7.0?
In older JBoss more advanced integration exist (JCA integration is the only standard way to get finer thread management). Use google to find them.
Wouldn't the simple ServletContextListener solve the problem for you? Just implement whatever you need in contextInitialized method.
In JBoss 7, there is a management api.
Maybe you can use it to check if the server is started (with a singleton and a TimerService).
Sample code:
ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
ModelNode op = new ModelNode();
op.get(ClientConstants.OP).set("read-attribute");
op.get(ClientConstants.NAME).set("server-state");
ModelNode returnVal = client.execute(op);
if(StringUtils.equals(returnVal.get("result").toString(), "\"running\"")){
LOGGER.info("Server running, init start actions");
timer.cancel();
}else{
LOGGER.info("Server not running, wait");
}