Reputation: 528
I have below code which required below entry in server.xml and file must placed in tomcat/lib.
I want to add tomcat listener and do not want to make any changes in tomcat server configuration. Is there any way I can achieve this?
Note : I have already tried "ServletContextListener" but it is not accurate as LifecycleListener.
Server.xml
<Listener className="com.tomcat.listener.TomcatListener"/>
Java file
package com.tomcat.listener;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
public class TomcatListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if(Lifecycle.AFTER_START_EVENT.equals(event.getType())){
System.out.print("Tomcat successfully started");
}
}
}
Upvotes: 1
Views: 1663
Reputation: 528
With the help of ServletContextListener
, LifecycleListener
and reflection I am able to achieve what I was expecting.
So here we are first capturing event of ServletContextListener
to get the ServletContext
and then using reflection and we are accessing private fields to add listener in ServletContext
implementation of Tomcat
CustomServletListener.java
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ApplicationContextFacade;
import org.apache.catalina.core.StandardContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.lang.reflect.Field;
public final class CustomServletListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
}
@Override
public void contextInitialized(ServletContextEvent event) {
addLifeCycleListener(event);
}
/**
* Tomcat Implementation of ServletContext in ApplicationContextFacade, ApplicationContext,StandardContext as to addListener is located in StandardContext
* @param event
*/
private void addLifeCycleListener(ServletContextEvent event) {
ApplicationContextFacade source = (ApplicationContextFacade) event.getSource();
ApplicationContext objApplicationContext=get(source, "context");
StandardContext objStandardContext = get(objApplicationContext, "context");
objStandardContext.addLifecycleListener(new TomcatListener());
}
/**
* Get class field using reflection as it is no way to direct access
* @param object
* @param fieldName
* @param <V>
* @return
*/
@SuppressWarnings("unchecked")
private <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
Field field = null;
boolean wasAccessible = false;
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
wasAccessible = field.isAccessible();
if (!wasAccessible) {
field.setAccessible(true);
}
return (V) field.get(object);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} finally {
// Revert the Accessibility flag to previous state
if(null != field && field.isAccessible() != wasAccessible){
field.setAccessible(wasAccessible);
}
}
}
return null;
}
}
TomcatListener.java
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
public class TomcatListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
System.out.print("Tomcat successfully started");
}
}
}
Upvotes: 2