I'm trying to implements initialization and shutdown of a webapp. That includes initialization and shutdown of:
Hibernate (v3.6);
C3P0 (v0.9.1.2);
EHCache (v2.3.0);
Quartz (1.8.4);
Other tasks specific to my webapp;
Using Tomcat 5.5.30 and Java 6. My idea is to avoid resource leaking, mostly because of the redeploy of the webapp in the development environment.
How should I implement this?
Usually for Web initialization and shutdown, you will write a ServletContextListener.
The steps to do this are:
Write a class that implements javax.Servlet.ServletContextListener
Add a tag to web.xml deployment descriptor to register the class you've just created
Deploy your application
When you deploy your application, contextInitialized method will be called. You can place all initialization you want here. On application shutdown contextDestroyed method will be called.
Its also possible to use the HTTP Servlet instead but the listener is a better option.
You have to extend a class with HttpServlet and setting the following stuff to your web.xml:
<servlet>
<servlet-name>StartupServlet</servlet-name>
<servlet-class>your.package.servlets.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The class can overwrite the init and the destroy method.
But still you want to manage your resources in such a way that they do not leak if the application crashes and normal shutdown routines are not called.
Related
I have a standard Java 11 Web application, with multiple servlets in it. Some servlets are imported by libraries, others are written within the application itself.
I need to perform a task AFTER all web servlets have been initialized, preferably before any requests come in. The task requires access to ServletContext.
I have tried performing this by creating a ServletContextListener and it's corresponding contextInitialized method, but this performs the task BEFORE the servlets have been initialized.
I cannot add the task to the last servlet to load, as the last servlet loaded is imported from an external library.
It would be preferable if the solution does not involve creating a servlet with no mapping.
If you have access to your deployment descriptor (web.xml) and the servlets are eager loaded, then you could append your servlet in the servlet list and set a high number in load-on-startup element.
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.project.LastServlet</servlet-class>
<load-on-startup>99</load-on-startup>
</servlet>
I tried to find a workaround in the documentation, but I couldn't find it and the ServletContextListener is a no go:
"All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized."
New to Tomcat and running Tomcat 7 in an Eclipse environment.
I followed a tutorial for creating a ServletContextListener class. My question is, simply, how do I get this loaded and running in Tomcat? Can I use annotations? Do I need to edit an xml file?
Javadoc to the rescue:
In order to receive these notification events, the implementation
class must be either declared in the deployment descriptor of the web
application, annotated with WebListener, or registered via one of the
addListener methods defined on ServletContext.
As an example in the web.xml:
<listener>
<listener-class>fully qualified class name of your listener class</listener-class>
</listener>
When you download Tomcat 7.0 from the Apache Tomcat website you'll get a version that includes an examples application. There is source code and configuration for some of the Servlet 3.0 features, like annotations.
Have a look at those examples - they're useful.
I have a web application deployed as war file in weblogic 10.3.3. Now I want to make this application clusterable. For this I'm using the HttpClusterServlet from Weblogic as a load balancer. According to the documentation I can put this servlet configuration into the web.xml
<servlet>
<servlet-name>HttpClusterServlet</servlet-name>
<servlet-class>weblogic.servlet.proxy.HttpClusterServlet</servlet-class>
<init-param>
<param-name>WebLogicCluster</param-name>
<param-value>server-1:7122|server-1:7123</param-value>
</init-param>
</servlet>
The problem is that this configuration is hard wired at build time and can't be reconfigured at runtime. For instance I would like to be able to add 5 more servers dynamically. I had several ideas to solve that problem:
Extend the weblogic.servlet.proxy.HttpClusterServlet with an own servlet implentation. This is not possible, the class is final.
Use a servlet filter to reconfigure the servlet. The servlet is not accessible anymore through ServletContext().getServlet(String) since Java Servlet API 2.1, with no direct replacement.
Reflection might be an option, but I couldn't figure out a reliable way to access the configuration
All of my attempts to reconfigure this init-param externally failed so far. I'm open to any solutions.
This might help How to externalize web.xml servlet init-param? Spring DelegatingFilterProxy for Servlets? Even if your not using Spring it wouldn't be too hard to port that servlet to another IoC container.
I need to save some data preferrably when the java web application is stopped, or when tomcat is stopped. how can this be done?
Edit:
any drawback if I use the jvm shutdown hook?
Use a class that implements ServletContextListener in your web.xml:
<web-app>
<!-- Usual stuff here -->
<listener>
<listener-class>com.mycompany.MyClass</listener-class>
</listener>
</web-app>
Why do you want to do it specifically during shutdown? And do you really need to save it (as in "is it absolutely critical?") or would you like to (as in "would be nice but I'll live without it")?
The distinction is important - no matter what method you try (servlet / context listener as suggested by other answers or JVM shutdown hook) there are no guarantees that it will actually be invoked.
Servlet / context listener destroy events would only be triggered during normal (graceful) container shutdown OR during application reload. JVM shutdown hook would be triggered during process interruption as well; however killing a process (or cutting out the power) would obviously trigger neither.
As an addition to leonm's answer:
If you use Spring, you can use Spring's "lifecycle management" to achieve a similar effect. For example, you can annotate a method in a bean with #PreDestroy to have it invoked automatically on container shutdown. That way, you don't need to put anything into the web.xml.
See Spring beans factory lifecycle.
I suggest using ehcache to cache this information. If you use ehcache's persistent store, then when you start Tomcat again, the cached data will still be available.
In effect, this delegates the issue to ehcache, which is optimised for these types of problems.
I have a 3rd party library that I use in my webapp. I need to call an init method from this library during axis2 startup.
I can't wait until the first request comes in - it must be done at startup.
in your web.xml:
<listener>
<listener-class>com.my.YourServletContextListener</listener-class>
</listener>
Where YourServletContextListener has to implement javax.servlet.ServletContextListener and provide your initialization code in the contextInitialized(..) method.
This method is called as soon as the servlet context is loaded.