I asked this question earlier:
Jersey app-run initialization code on startup to initialize application
Is there any way to run this initialization code after the server has initialized the web app fully ? I am running into a catch-22 problem in that I need the web app fully started by Tomcat before I can run my login call once ?
There are a few considerations. First, Jersey is implemented as a servlet, and that's how it gets loaded. The simplest way to decouple servlet startup from servlet context startup is to not load it on startup. Accomplish this by omitting the load-on-startup element from the servlet descriptor in the web.xml. Setting it to a non-positive should also work.
If you must load the servlet on startup but still want to decouple it, which was my case, you'll probably have to write some custom code, which I did. I couldn't think of any other way. Use a listener of some type--a ServletContextListener or Spring ApplicationListener, depending on exactly how your app is set up--to kick off a new thread that will initialize your Jersey servlet by making an HTTP request to it. It feels a little dirty, but like I said, it's the only thing I and my team could come up with.
Related
My particular setup is a Java webapp packaged as a war file under Tomcat7, but the question is more general. In our webapp, we have multiple servlets being registered via the Servlet 3.x #WebServlet annotation (and also marked loadOnStartup=1). The question is what to do if one of the servlets fails for some legitimate reason during initialization by throwing an exception. In this case, we're seeing two issues:
Tomcat notices that the servlet failed. But our service keeps getting probed by a load balancer trying to decide whether to include us in the pool. Every probe is an access to a URL mapped to the servlet that failed. Tomcat keeps trying and retrying to initialize the webapp, failing each time. Is there a way to cause Tomcat to just stop trying and give up? We can monitor for initialization failure and take corrective action if required.
The other servlets in the same webapp did not fail (those are also loaded via a WebServlet annotation with loadOnStartup=1). So if we try to access them by hitting an appropriate URL, Tomcat lets us through. We would prefer it if the failure of one servlet in the webapp would cause the whole webapp to fail.
You could place all failable startup operations in a ServletContextListener which is initialized before any servlet. If the init of the ServletContextListener fails the whole webapp is not deployed.
Your servlets could then in their initialization simply ask the singleton ServletContextListener for their already initialized resources.
Here is my approach:
Put all startup operation code in the ServletContextListener.
At the end of all start up operations, put an attribute (true or false) in the context context.setAttribute(). Or put several T/F attributes for different init operation results.
Add a filter for this servlet to handle all requests. Check the context attribute, if startup operation failed, this filter will gracefully respond to the request, either by redirect or send error respond code to load balancer query.
I currently have a Jersey webapp without a web.xml. It deploys nicely, but doesn't start up until it receives its first web request.
To get the webapp to load at startup, I could create a web.xml for the webapp and give a load-on-startup tag. However, I'd strongly prefer not to make a web.xml.
Is there a way to get a JAX-RS application to load at startup without web.xml? I'll even accept a solution that is specific to Jersey and/or Tomcat.
EDIT: I would also accept a solution that loads all apps in a Tomcat instance eagerly.
EDIT: Let me give a little more information on how the app is being deployed, per a comment.
The deployment process is not sophisticated.
The App will live on an EC2 instance running Ubuntu 12.04. I'm setting up one instance of the App by hand; once it works, I will make an AMI of the app and create additional copies of it as needed.
To deploy the app on the initial instance, I'm simply copying the WAR file to /var/lib/tomcat7/webapps and restarting Tomcat. No other webapps will be running on this Tomcat instance.
If any additional information would be useful, let me know! I'll happily add it.
EDIT: For clarity's sake, this is how my webapp Application class looks, at a high level:
#ApplicationPath("/")
public class App extends ResourceConfig {
// ...
}
I'm using the Jersey-specific ResourceConfig class instead of the more general JAX-RS Application class because I'm using Jersey's built-in HK-2 to do some dependency injection.
The only way I can think of to do that is to switch to setting up the Jersey ServletContainer yourself and set its "load on startup" value to something greater than zero. You might use a ServletContainerInitializer (no relation--the naming is just a coincidence) to do it. If you happen to be using Spring, its WebApplicationInitializer offers the same mechanism with a slightly more convenient interface.
Another, rather hacky, way would be to write a class that extends ServletContainer and give it an appropriate Servlet 3.0 annotation, something like #WebServlet(value="/", loadOnStartup=1)
One solution would be to force a first request to the app by simply adding a call to curl or wget to your deployment script. It has the additional advantage of warming up any caches. And it can be used for testing if the deployment and the app really work. (Just check HTTP status code or some text on the response page...)
I want to initialize a global instance of a class before my Tomcat server completes startup and begins to offer my servlets. If this service somehow fails initialization, I'd like the entire startup sequence to fail as well (or as close to this as possible; it would be pointless for the server to be running otherwise). What's the best way I can accomplish this?
Each web application has a ServletContext associated with it. The ServletContext object is created when the application is started and is destroyed when the application is shut down. A ServletContext has a global scope and is similar to a global variable in an application.
http://www.javabeat.net/tips/178-servletcontextlistener-example.html
complete explanation here
http://onjava.com/pub/a/onjava/2001/04/12/listeners.html
One thing you can do portably is to implement a servlet that initializes everything you need in its init() method (and maybe call System.exit() if it fails, i do not know if you have permission to do this in Tomcat). Then you would load it using <load-on-startup> in your web.xml to specify initialization order.
Is there a way to initialize the ServletContext for a webapp on a Resin server using a method? I need something like that runs once, when the server starts up.
You need to use a ServletContextListener.
http://www.java-tips.org/java-ee-tips/java-servlet/how-to-work-with-servletcontextlistener.html
This J2EE tip demonstrates use of
ServletContextListener. This event
class handles notifications about
changes to the servlet context of the
Web application that they are part of.
This can be explained as if someone is
present on the server and dynamically
informing us about the events that are
occuring on the server. There acquire
need of Listners. Therefore,
ServletContextListner is helpful in
informing about context Initilazation
and destruction.
Use the <load-on-startup/> in the <servlet> tag.
I write couples of servlet program, however I dont think I fully understand how servlet run. So here is couples question that I have:
All the code I wrote about Servlet only run on Netbeans with apache tomcat run behind. When I run my html file that make request to the servlet, it usually give error saying that it could not find the servlet, I then have to redeploy the servlet then everything would run fine. Seem like my servlet timeout after a while or something.
Does the servlet run all the time? Servlet has init() and destroy(), so I guess it wont run all the time. So then when does it start and when does it end? Does it start when there is a request from the client, and end when it is time out? And how does I fixed my problem that I have to constantly redeploy the servlet. Thank you very much.
Under normal circumstances, a servlet is only destroyed at shutdown (ie when the application container, such as Tomcat, is shut down). Otherwise it remains in memory for the duration of the application. I couldn't say what's going on with your Netbeans setup, but try deploying your WAR file to a standalone Tomcat installation and see if the problem doesn't go away.
Another time that the application container will call destroy on a servlet is if it is running out of memory, but this is far less common.
Regarding your question about requests, a servlet is designed to handle many requests. It is said that the servlet is application-scoped, whereas the request has its own scope.
You're apparently in middle of developing with servlets. You need to ensure that the webapp is fully published whenever you have made changes to web.xml or any of the Servlet classes. Otherwise you may risk that the resource cannot be found.
In easy terms, a "resource not found" error is basically exactly the same as a "404 page not found". The servlet container can't seem to find a resource which matches the URL or url-pattern. That's all.
As to the Servlet lifecycle, it will be created only once during webapp startup (publish, create of context), the init() method will be called and the instance will be kept in the server's memory in a sort of a Map<Url-Pattern, Servlet>. If you have overriden the init() method in your Servlet, then it will be called. The servlet container will do the same for all of the servlets declared in web.xml (or as per Java EE 6, annotated with #WebServlet).
Everytime a request whose URL matches the url-pattern of the Servlet, the (inherited) service() method will be invoked. The normal HttpServlet implementation will then determine the method to be executed based on HttpServletRequest#getMethod(). If you did override any of those methods (doGet(), doPost(), etc) in your Servlet, then it will be invoked accordingly.
Finally, when the webapp is about to shutdown (unpublish, destroy of context), then the destroy() will be invoked for any of the Servlet instances kept in server's memory. If you have overriden the destroy() method in your Servlet, then it will be called.
A servlet "runs" only when it's invoked. The server will wait for a connection to come from the client, read the headers, find the proper servlet based on the mappings in web.xml, and then call the service() method of that servlet. The servlet object, will remain in-memory until the container decides to dispose it (which it may do at any time that it's not servicing requests). If the server decides to dispose of a particular servlet instance, it will create a new one the next time a request comes in for the servlet.
Which means you should not be getting an error that says the server can't find your servlet. Assuming that the application has been deployed, and there is a correct servlet mapping, the container will be able to process the request. If you edit your request and paste the exact error message, someone may be able to tell you why this isn't happening.
you need to research the servlet lifecycle - that's what the init() and destroy methods are there for
normally init() is called once, when the serlvet is first called (unless you did something like set it to autorun in tomcat)
and destroy() is called when the container shuts down
dopost() or doGet() (if it's an HTTP servlet) are called for each request