how to execute some initialization code in a war package in tomcat? - java

I'm using a framework to deal with some request, now, I can start it from a main function like this:
public Main{
public static void main(String[] args) {
//init the framework
Init initer = new Init();
initer.initFramework();
//start my besiness code below
}
}
now I need to package my project in a war format and put it into tomcat, how can I be able to excute the initialization code?

When you start a war-file in Tomcat using servlet 2.3 or higher you can use the web.xml file to declare listeners.
<listener>
<listener-class>test.MyListener</listener-class>
</listener>
This listener should implement the ServletContextListener interface. Listeners gets notified of lifecycle changes (such as when the servlet context has been initialized). The listener can be implemented to run your initialization code as illustrated below:
public class MyListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
Init initer = new Init();
initer.initFramework();
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// destroy stuff
}
}
If you are running the war-file in a servlet 3 environment there might not even be a web.xml file. In that case the #WebListener annotation can be used to indicate that your component should be called. The JavaDoc for #WebListener can be found here but basically what you need to do is to add the annotation to your listener.

Just implement org.springframework.web.WebApplicationInitializer and that's it, no xml.

Related

Understanding Spring Boot's App Lifecycle and Startup Listeners

In Sprint Boot 2.x we can initialize our application in one of 2 approaches:
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
init();
}
private void init() {
// Init the app from in here...
}
}
Or we can use a startup listener that will execute on startup:
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Init the app from in here...
}
}
I'm wondering what tradeoffs exist by taking either approach. Not knowing much about Spring Boot's "app lifecycle", I'm wondering if there are things I will/won't have access to in either setup. Thanks in advance!
The init method is only called after startup, and is only called when running your application as a command-line program.
The init method is e.g. not called when deploying your application as a .war file.
The onApplicationEvent method is called whenever a ContextRefreshedEvent is fired, which does happen during startup, but can be called again later. See e.g. "When is ContextRefreshedEvent fired in Spring?"
For a more comparable event to the init method, use ApplicationStartedEvent.

What is the main method of a WAR file?

Recently, I've reapackaged my java spring application to become a WAR file for deployment in tomcat. After some testing I noticed, that public static void main(String[] args) is not executed. Some necessary initialization of my application is done in main. Is there something like a main method in a WAR file? What is the appropiate place in a WAR file to run some initialization?
You can add a listener to your web.xml file:
<listener>
<description>Application startup and shutdown events</description>
<display-name>Test</display-name>
<listener-class>com.package.package.StartClass</listener-class>
</listener>
public class StartClass implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//Context destroyed code here
}
#Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
//Context initialized code here
}
}
Well, You will have to create a listener in your web.xml that will be invoked by container at the time of startup.
<listener>
<listener-class>com.rdv.example.WebAppContext</listener-class>
</listener>
And this class will be implementing ServletContextListener
public class WebAppContext implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
// Do your processing that you are trying to do in main method.
}
I've found another way, that is independent of spring and tomcat: The #PostConstruct annotation. In code:
#PostConstruct
public void init() {
// initialization code goes here
}
This method gets executed whether I run my application standalone or in tomcat.
For more information see How to call a method after bean initialization is complete?
or Init method in Spring Controller (annotation version)

how to deploy java EE listener using #WebListener

I want to implement a new listener (using the servlet 3.0 spec).
#WebListener
public class LoadingManager implements ServletContextListener
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
I package the listener in a jar and I want to know which is the better deployment mode
Put the jar on the tomcat/lib
Put the jar inside webapps/My-Application/lib
If I deploy the jar under the tomcat/lib, how much time the method contextInitialized will be performed (knowing that I have a set of webapplicatio deployed on my tomcat instance)
Thanks in advance
Better to add it in the webapps/My-Application/lib so that it can be used based on individual application and not for all the applications
Even Gimby has some good points in the comment.

Trigger function when Undeploying application

How do I automatically trigger Java function to stop Quartz scheduler jobs when I deploy/undeploy/redeploy JEE5 application in Glassfish.
Implement ServletContextListener and hook on contextDestroyed().
Basic example:
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Write code here which should be executed on webapp startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Write code here which should be executed on webapp shutdown.
}
}
and register it as a <listener> in web.xml.
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
Once you get to JAVA EE-6+, annotate a class with #WebListener and implement ServletContextListener on that class to get a shutdown notification. No need to deal with web.xml. See here

Is there a way to run a method/class only on Tomcat/Wildfly/Glassfish startup?

I need to remove temp files on Tomcat startup, the pass to a folder which contains temp files is in applicationContext.xml.
Is there a way to run a method/class only on Tomcat startup?
You could write a ServletContextListener which calls your method from the contextInitialized() method. You attach the listener to your webapp in web.xml, e.g.
<listener>
<listener-class>my.Listener</listener-class>
</listener>
and
package my;
public class Listener implements javax.servlet.ServletContextListener {
public void contextInitialized(ServletContext context) {
MyOtherClass.callMe();
}
}
Strictly speaking, this is only run once on webapp startup, rather than Tomcat startup, but that may amount to the same thing.
You can also use (starting Servlet v3) an annotated aproach (no need to add anything to web.xml):
#WebListener
public class InitializeListner implements ServletContextListener {
#Override
public final void contextInitialized(final ServletContextEvent sce) {
}
#Override
public final void contextDestroyed(final ServletContextEvent sce) {
}
}
I'm sure there must be a better way to do it as part of the container's lifecycle (edit: Hank has the answer - I was wondering why he was suggesting a SessonListener before I answered), but you could create a Servlet which has no other purpose than to perform one-time actions when the server is started:
<servlet>
<description>Does stuff on container startup</description>
<display-name>StartupServlet</display-name>
<servlet-name>StartupServlet</servlet-name>
<servlet-class>com.foo.bar.servlets.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

Categories