views:

711

answers:

3

Hello

Can anyone tell me if it is appropriate to use a ServletContextListener for a particular requirement?

What I have is a web application which runs a particular job every hour to poll a number of RSS feeds and at any time a user can define a new RSS feed for polling.

What I want to avoid is a user adding a feed(s) during a current hourly polling cycle and having this feed(s) included in that cycle.

So what I'm thinking about is using a ServletContextListener with a static boolean variable which records whether a polling cycle is running or not. If an hourly polling cycle is running, a new feed defined by a user will not be included in this cycle; if polling is not running, then the feed can be included in the next hourly run.

Can anyone advise? The only alternatives I see are to use a flag on a database table or to update a value in a properties file (if this can be done).

Thanks

Martin O'Shea.

+1  A: 

You keep the feed data in a database? Don't know how you access the database, but with plain jdbc you would select the feeds to poll and iterate over the resultset. Any newly added feed (after the select) would not appear in this resultset and therefore not get included.

If that for some reason does not apply to your problem, you could read the feats into a collection and work with that.

Or did i miss your question completely?

bert
You've not missed the question. I'm simply trying to put an additional layer of security on things by having a flag set when polling is active. This will prevent a newly defined feed being added to the result set at polling time by setting the new feed to poll at another time.
OP is right, this is something the database should be able to take care of. You just need to set isolation level SERIALIZABLE on the JDBC Connection that reads feeds. But if you really want to do this...
Sean Owen
+1  A: 

That sounds like a bad idea. Why not simply use the ServletContext for your web-app to hold a property for the web-app ("polling-cycle-running")? The component in your web-app that kicks off the job sets the property in the context; all interested components (such as your AddRSS action would check that property in the context as a matter of course.

servletCtx.setAttribute(POLLING_CYCLE_FLAG_ATTR, true);

and

if(!servletCtx.getAttribute((POLLING_CYCLE_FLAG_ATTR)) {
   // let the user add the feed ...
}

ServletContextListener is all about the web-app's life-cycle and the changes to the web-app's ServletContext. Typical use is for initializing and cleaning up resources for modules for the application. But basically, if you need to keep tabs on what is happening in the ServletContext, ServletContextListener is your friend.

This sounds exactly what is required. So POLLING_CYCLE_FLAG_ATTR becomes a global variable in the servlet context?
One question though; I can use a servlet to set polling to no when the system starts but the class that runs the hourly polling is not a servlet. Can ServletContext be accessed from a standard class at all? Or should the polling class be converted? To me this makes little sense if servlets are primarily request / response vehicles.
You said your web-app "runs a particular job every hour", so the assumption was that the job is initiated within the web-app. If that's the case, then at the point of initiating the job you should have access to the servlet context. You can always access the ServletContext using the getServletContext() method of a Servlet. It would be best to think of the context as a namespace for your web-app. If the app is clustered on containers on many nodes, then you must use the lifecycle hooks in the listener to synch the context attributes from a shared resources, typically a db.
A: 

Agree with the last post that ServletContext attributes are the way to create sort of 'global variables' in the Servlet API.

This would not work across servlet container instances, or even web apps in one container. Each would have its own ServletContext. If you have just one instance, it works. Otherwise I'd guess you need a database flag.

Servlets get access to the ServletContext object via the init() method. ServletContextListeners also get access through the contextInitialized(ServletContextEvent sce) lifecycle event. I think it's reasonable for your poll class to exist as a listener that starts and stops with the ServletContext lifecycle, yes. And it will have access to the ServletContext when initialized, yes.

Sean Owen
One thing confuses me: I would end up with two classes; (1) the listenser which runs when the application starts and sets the polling to no, and (2) the polling class. Are you saying (2) should be converted to a servlet or a listener?
Or could a single listener handle the initialisation and polling?
It could easily be one class. It just needs to implement the listener methods to receive the signal to start/stop, and access to the ServletContext. Beyond that, it can do whatever you like and no reason it has to be two classes.
Sean Owen