This question already has answers here:
Is there a way to run a method/class only on Tomcat/Wildfly/Glassfish startup?
(3 answers)
Closed 5 years ago.
I am trying to call a method when my webapplication starts. The purpose is to kick-off a timer that does some work at defined intervals.
how do i call a function helloworld when my jboss 7.1 web application starts up?
If you want to run some code before your web app serves any of your clients you need a ServletContextListener.
Create your listener class
import javax.servlet.*;
public class MyServletContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent e) {
//Call your function from the event object here
}
public void contextDestroyed(ServletContextEvent e) {
}
}
Put the class in WEB-INF/classes
Put a <listener> element in the web.xml file.
<listener>
<listener-class>
com.test.MyServletContextListener
</listener-class>
</listener>
Hope this helps.
Other then ContextListeners, you can also have a servlet in web.xml loading on startup:
<servlet>
<servlet-name>mytask</servlet-name>
<servlet-class>servlets.MyTaskServlet</servlet-class>
...
<load-on-startup>1</load-on-startup>
</servlet>
This servlet can start your task using whatever means you want, see for example this link.
But you shouldn't use that approach, imho.
Use a proven framework/lib like quartz or a similar tool. There are a lot of problems/issues in running and syncing tasks in web servers and it's better to use some proven tool than to repeat mistakes these tools already met and solved. It might take a little while to grasp but will avoid many headaches.
Jboss itself has some tooling for that purpose: scheduling and managing tasks. Never used so can't recommend.
Check out Quartz Scheduler. You can use a CronTrigger to fire at defined intervals. For example, every 5 minutes would look like this:
"0 0/5 * * * ?"
The idea is to implement the Job interface which is the task to run, schedule it using the SchedulerFactory/Scheduler, build the Job and CronTrigger and start it.
There is a very clear example here.
Use a ServletContextListener configured in your web.xml. Write the code that kicks off the timer in the contextInitialized method.
Related
i am working on a GWT web application and i was wondering if there is a way to keep some classes alive on the server.
The point is that i would like to create a static class that will run on the server and manage something for me.. lets say currently logged in users.
public class someclass{
private static someclass instance;
private List<user> users;
private someclass(){
users = new ArrayList<user>();
}
public someclass getInstance()
{
if (instance == null)
instance = new someclass();
return instance;
}
public addUser(user u)
{
users.add(user);
}
}
assume that there is no sync needed its not impotent for the question.
lets say first user logs in, and is added to the users list.
when a second user logs in. will the user list be empty? or will it have the old user as well?
Thanks...
There are different ways to do this. However, a very simple way to tackle this scenario would be to use a startup servlet
In web.xml define it as follows.
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>TestServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Maintain the stat in static fields of that servlet.
While the answer of ring bearer is the most compatible (it will work even in some very old servlet containers), I think the current approach would be to register a context listener for your application. As an example, I use this in my web.xml in order to have the Quartz task scheduler available:
<listener>
<listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
</listener>
Your context listener must implement the javax.servlet.ServletContextListener interface.The servlet container will call void contextInitialized(javax.servlet.ServletContextEvent sce) to notify application startup. On shutdown, the servlet container will call void contextDestroyed(javax.servlet.ServletContextEvent sce).
The approach with servlets is similar but your logic would be in the servlet lifecycle operations.
You'll have to excuse me if I'm describing this incorrectly, but essentially I'm trying to get a service-like class to be instantiated just once at server start and to sort of "exist" in the background until it is killed off at server stop. At least from what I can tell, this is not exactly the same as a typical servlet (though I may be wrong about this). What's even more important is that I need to also be able to access this service/object later down the line.
As an example, in another project I've worked on, we used the Spring Framework to accomplish something similar. Essentially, we used the configuration XML file along with the built-in annotations to let Spring know to instantiate instances of some of our services. Later down the line, we used the annotation #Autowired to sort of "grab" the object reference of this pre-instantiated service/object.
So, though it may seem against some of the major concepts of Java itself, I'm just trying to figure out how to reinvent this wheel here. I guess sometimes I feel like these big app frameworks do too much "black-box magic" behind the scenes that I'd really like to be able to fine-tune.
Thanks for any help and/or suggestions!
Oh and I'm trying to run this all from JBoss 6
Here's one way to do it. Add a servlet context listener to your web.xml, e.g.:
<listener>
<listener-class>com.example.BackgroundServletContextListener</listener-class>
</listener>
Then create that class to manage your background service. In this example I use a single-threaded ScheduledExecutorService to schedule it to run every 5 minutes:
public class BackgroundServletContextListener implements ServletContextListener {
private ScheduledExecutorService executor;
private BackgroundService service;
public void contextInitialized(ServletContextEvent sce) {
service = new BackgroundService();
// setup single thread to run background service every 5 minutes
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(service, 0, 5, TimeUnit.MINUTES);
// make the background service available to the servlet context
sce.getServletContext().setAttribute("service", service);
}
public void contextDestroyed(ServletContextEvent sce) {
executor.shutdown();
}
}
public class BackgroundService implements Runnable {
public void run() {
// do your background processing here
}
}
If you need to access the BackgroundService from web requests, you can access it through the ServletContext. E.g.:
ServletContext context = request.getSession().getServletContext();
BackgroundService service = (BackgroundService) context.getAttribute("service");
Have you considered using an EJB 3.1 Session bean? These can be deployed in a war file, and can be annotated with #Singleton and #Startup.
A number of annotations available with EJB 3.1 are designed to bring Spring goodies into the Java EE framework. It may be the re-invention you're considering has been done for you.
If you must roll your own, you can create a servlet and configure it start up when the application does using load-on-startup. I built a system like that a few years ago. We then used the new(ish) java.util.concurrent stuff like ExecutorService to have it process work from other servlets.
More information about what you're trying to do, and why the existing ways of doing things is insufficient, would be helpful.
You can use messaging for that. Just send message to the queue, and let the message listener do the processing asynchronously in the background.
You can use JMS for the implementation, and ActiveMQ for the message broker.
Spring has JMSTemplate, JMSGateWaySupport API to make JMS Implementation simple
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html
I'm trying to timeout an HttpSession in Java. My container is WebLogic.
Currently, we have our session timeout set in the web.xml file, like this
<session-config>
<session-timeout>15</session-timeout>
</session-config>
Now, I'm being told that this will terminate the session (or is it all sessions?) in the 15th minute of use, regardless their activity.
I'm wondering if this approach is the correct one, or should I programatically set the time limit of inactivity by
session.setMaxInactiveInterval(15 * 60); //15 minutes
I don't want to drop all sessions at 15 minutes, only those that have been inactive for 15 minutes.
Are these methods equivalent? Should I favour the web.xml config?
Now, i'm being told that this will terminate the session (or is it all sessions?) in the 15th minute of use, regardless their activity.
This is wrong. It will just kill the session when the associated client (webbrowser) has not accessed the website for more than 15 minutes. The activity certainly counts, exactly as you initially expected, seeing your attempt to solve this.
The HttpSession#setMaxInactiveInterval() doesn't change much here by the way. It does exactly the same as <session-timeout> in web.xml, with the only difference that you can change/set it programmatically during runtime. The change by the way only affects the current session instance, not globally (else it would have been a static method).
To play around and experience this yourself, try to set <session-timeout> to 1 minute and create a HttpSessionListener like follows:
#WebListener
public class HttpSessionChecker implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
System.out.printf("Session ID %s created at %s%n", event.getSession().getId(), new Date());
}
public void sessionDestroyed(HttpSessionEvent event) {
System.out.printf("Session ID %s destroyed at %s%n", event.getSession().getId(), new Date());
}
}
(if you're not on Servlet 3.0 yet and thus can't use #WebListener, then register in web.xml as follows):
<listener>
<listener-class>com.example.HttpSessionChecker</listener-class>
</listener>
Note that the servletcontainer won't immediately destroy sessions after exactly the timeout value. It's a background job which runs at certain intervals (e.g. 5~15 minutes depending on load and the servletcontainer make/type). So don't be surprised when you don't see destroyed line in the console immediately after exactly one minute of inactivity. However, when you fire a HTTP request on a timed-out-but-not-destroyed-yet session, it will be destroyed immediately.
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
Now, i'm being told that this will terminate the session (or is it all sessions?) in the 15th minute of use, regardless their activity.
No, that's not true. The session-timeout configures a per session timeout in case of inactivity.
Are these methods equivalent? Should I favour the web.xml config?
The setting in the web.xml is global, it applies to all sessions of a given context. Programatically, you can change this for a particular session.
In web.xml I have this
<session-config>
<session-timeout>2</session-timeout>
</session-config>
<listener>
<listener-class>myapplication.SessionListener</listener-class>
</listener>
In the SessionListener.java I have
public void sessionDestroyed (HttpSessionEvent event){
System.out.println("Visitor Removed!!");
}
But it seems System.out.println("Visitor Removed!!") has never been executed. I am new to Tomcat 6 and JSP. Any suggestion please?
This can have at least 3 causes:
The session has never been created. Listen on sessionCreated() as well.
You are a bit impatient. Session destroy happens lazily and at intervals. It does not happen immediately. If you fire a new request in the same session while it has been expired, then sessionDestroyed() will be called. Or if you have a bit more patience, the server will run its low-prio timer job to reap all expired sessions.
You are not using the myapplication.SessionListener class in the classpath as you think you're using, maybe the one actually in the classpath doesn't have a sysout line.
This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 7 years ago.
I am not very familiar with Tomcat, in my head it is basically abstracted as a cgi server that saves the JVM between calls -- I know it can do a lot more than that, though.
I am looking for a way to launch a background thread when a Tomcat server starts, which would periodically update the Server Context (in my particular case this is a thread that listens to heartbeats from some other services and updates availability information, but one can imagine a variety of uses for this).
Is there a standard way to do this? Both the launching, and the updating/querying of the Context?
Any pointers to the relevant documentation and/or code samples would be much appreciated.
If you want to start a thread when your WAR is deployed, you can define a context listener within the web.xml:
<web-app>
<listener>
<listener-class>com.mypackage.MyServletContextListener</listener-class>
</listener>
</web-app>
Then implement that class something like:
public class MyServletContextListener implements ServletContextListener {
private MyThreadClass myThread = null;
public void contextInitialized(ServletContextEvent sce) {
if ((myThread == null) || (!myThread.isAlive())) {
myThread = new MyThreadClass();
myThread.start();
}
}
public void contextDestroyed(ServletContextEvent sce){
try {
myThread.doShutdown();
myThread.interrupt();
} catch (Exception ex) {
}
}
}
I am looking for a way to launch a background thread when a Tomcat server starts
I think you are looking for a way to launch a background thread when your web application is started by Tomcat.
This can be done using a ServletContextListener. It is registered in web.xml and will be called when your app is started or stopped. You can then created (and later stop) your Thread, using the normal Java ways to create a Thread (or ExecutionService).
Putting <load-on-startup>1</load-on-startup> in the <servlet> block in your web.xml will force your servlet's init() to happen as soon as Tomcat starts up, rather than waiting for the first request to arrive. This is useful if you want to spawn the background thread from init().
I'd just make a small change to the very detailed answer Chris gave; I would set myThread to be a Daemon thread by myThread.setDaemon(true); which will basically keep the thread active as long as you have other non-Daemon threads working which need your background thread around. When all these threads finish then your Daemon thread is stopped by the JVM and you do not need to handle it youself in contextDestroyed.
But that's just my 2 cents.
Another way if you are using spring based framework you can specify the class/thread which you want to initialize in the beans.xml. So when the tomcat starts up, beans.xml will initialize all the classes mentioned in it. You can also pass constructor arguments if required. Below is the example of the same.
beans.xml
<bean id="monitoringSvc" class="com.mypackage.MonitoringService">
<constructor-arg value="60"></constructor-arg>
</bean>
MonitoringService.java
public class MonitoringService{
private MyThread myThread;
public MonitoringService(int seconds){
myThread = new MyThread(seconds);
myThread.start();
}
}