When using a "global" filter, one which is located in the root lib directory of an apache tomcat webserver and applies to all web application contexts:
I was wondering if the web application contexts are initialized synchronously - one at a time, or can there be a case where the Filter.init() function is called by two different contexts in the same time.
I'm asking this since I want to initialize a database connection configuration object based on a specific FilterConfig.initParameter the first time init() is called by any of the application contexts, and I'm wondering if I should put the above in a synchronized block or not...
I think it's the internals of Tomcat, it could change any time so I'd do it in a synchronized block. It's not a big deal or performance issue because it runs only once per application context initialization.
From Java Servlet Specification 6.2.1 Filter Lifecycle:
Only one instance per <filter> declaration in the deployment
descriptor is instantiated per JVM of the container.
You could reach the same result with a custom Valve:
The Valve Component
Valve javadoc
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 have a service where I want to maintain data persistence in a mysql db using jdbc. While i have experience building jdbc apps and jax-rs apps in isolation, I've never combined the two. The question is, where does the build up and tear down required for the jdbc-type stuff go? Ordinarily i'd put the build up in a static block, or in a constructor, and id have have a cleanup method that gets called in a finally. this doesnt seem to work in the jax-rs framework- the constructor gets called at every invocation, and there is no place to my knowledge to put any clean up methods. unfortunately, there are sparse examples for combining the two technologies online, something i find surprising. Can you guys help me out?
As a general rule, to do things at the startup and shutdown of your web application, you should create custom ServletContextListeners and list them in your web.xml.
With JDBC resources in a WAR, often times you have your container (e.g. Tomcat, Websphere, etc.) create and manage a connection pool which can be shared with a number of web applications. You would define a resource-ref for a javax.sql.DataSource in your web.xml. Then there is a container specific method for defining and binding the JDBC DataSource to the resource-ref of your application.
I'm not familiar with Memchached and what is needed on startup/shutdown so this is only a guess. If you need to register/unregister with a Memcache server you might try having one or more env-entry tags defined in your web.xml which could be used by a custom ServletContextListener to do your bidding.
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.
Permanent servlets are loaded when the server is started, and live until the server is
shutdown.
I have requirement to start some server side java programs and These programs then provide functionality that is totally unique and independent of the web server. I wish to do it on Tomcat startup. Solution I see is Permanent Servlet, Which will invokes these Java programs.
So How to configure Permanent Servlets in Tomcat 6 ?
More Details about Permanent Servlets from http://java.sun.com/developer/onlineTraining/Servlets/Fundamentals/servlets.html
Temporary versus Permanent Servlets
Servlets can be started and stopped for each client request, or they can be started as the web server is started and kept alive until the server is shut down. Temporary servlets are loaded on demand and offer a good way to conserve resources in the server for less-used functions.
Permanent servlets are loaded when the server is started, and live until the server is shutdown. Servlets are installed as permanent extensions to a server when their start-up costs are very high (such as establishing a connection with a DBMS), when they offer permanent server-side functionality (such as an RMI service), or when they must respond as fast as possible to client requests.
There is no special code necessary to make a servlet temporary or permanent; this is a function of the server configuration.
Because servlets can be loaded when a web server starts, they can use this auto-loading mechanism to provide easier loading of server-side Java programs. These programs can then provide functionality that is totally unique and independent of the web server. For example, a servlet could provide R-based services (rlogin, rsh, ...) through TCP/IP ports while using the servlet request/response protocol to present and process HTML pages used to manage the servlet.
You can do what you need with a ServletContextListener. Register one in your web.xml, e.g.:
<listener>
<listener-class>com.example.MyServletContextListener</listener-class>
</listener>
Then create that class to do what you want:
public class MyServletContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
// initialize and startup whatever you need here
}
public void contextDestroyed(ServletContextEvent sce) {
// shutdown and destroy those things here
}
}
I think what they are referring to when they say "permanent servlets" are just the servlets you define in the web.xml, a la,
<servlet>
<description>I'm permanent</description>
<display-name>Servlet</display-name>
<servlet-name>Servlet</servlet-name>
<servlet-class>com.servlet.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
This servlet will be started up when the server starts and will be kept around until it shuts down, probably (See below).
An example temporary servlet would be a .jsp file. It wont load the file up until it is requested and it will probably dispose of it after servicing the request.
Looking at the Servlet Specification about servlet lifecycles,
When the servlet engine is started, needed servlet classes must be located by the
servlet container. The servlet container loads the servlet class using normal Java class
loading facilities. ...
After loading the Servlet class, the container instantiates it for use.
Then for eol,
The servlet container is not required to keep a servlet loaded for any particular
period of time. A servlet instance may be kept active in a servlet container for a
period of milliseconds, for the lifetime of the servlet container (which could be a
number of days, months, or years), or any amount of time in between.
When the servlet container determines that a servlet should be removed from
service, it calls the destroy method of the Servlet interface to allow the servlet to
release any resources it is using and save any persistent state. For example, the
container may do this when it wants to conserve memory resources, or when it is
being shut down.
Before the servlet container calls the destroy method, it must allow any threads that
are currently running in the service method of the servlet to complete execution, or
exceed a server-defined time limit.
Once the destroy method is called on a servlet instance, the container may not route
other requests to that instance of the servlet. If the container needs to enable the
servlet again, it must do so with a new instance of the servlet’s class.
After the destroy method completes, the servlet container must release the servlet
instance so that it is eligible for garbage collection.
So I think bottom line, the servlet specification makes no guarantee as to how long a servlet will be kept, it is implementation specific, but I think its a pretty safe bet that if you load it on start up it will remain loaded for the whole time the server is running.
For your specific use case though, follow WhiteFang34, as using a servlet for something other than servicing requests is abusing the API IMO.
[Edit] Everywhere I look to see how a servlets' lifecycle is managed seems to say that it will remain loaded for the entirety of the webapps lifetime.
Servlets
What is the difference between JSF, Servlet and JSP?
java servlet instantiation and session variables
But nowhere can I find a reference that says that, so I just don't know for certain.
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.