2

How can a reload a servlet once a month?

We got some data which will change once a month, the data is for the servlet, but we don't need to save the data into DB, instead we want to make it a configuration file which will be replaced once a month, how can I do this?

I know that the servlet's lifecycle policy is controlled by the container, I am using websphere 7, but I don't know if there is a way to configure that in websphere.

Will calling the destory() method affect the running instances of servlet? AFAIK, the servlet is multi-threaded.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
lamwaiman1988
  • 3,729
  • 15
  • 55
  • 87

1 Answers1

6

Don't use a servlet to store the data. Rather store the data as an attribute of the ServletContext. You can do it with help of a ServletContextListener. The very same listener class can also be used to reload the data at timed intervals with help of ScheduledExecutorService.

Here's a kickoff example:

public class Config implements ServletContextListener {

    private ScheduledExecutorService scheduler;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        Data data = new Data();
        event.getServletContext().setAttribute("data", data);
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new Reloader(data), 0, 30, TimeUnit.DAYS);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        scheduler.shutdownNow();
    }

}

(note that there's no TimeUnit.MONTH, so this is the best you can get for "once a month")

Where the Reloader class look like this:

public class Reloader implements Runnable {

    private Data data;

    public Reloader(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        data.reload();
    }

}

After registering the listener in /WEB-INF/web.xml as follows

<listener>
    <listener-class>com.example.Config</listener-class>
</listener>

it will create the Data instance and a single thread scheduler which executes the data.reload() every 30 days and you can access the Data instance in every servlet as follows:

Data data = (Data) getServletContext().getAttribute("data");

and in JSPs as follows:

${data}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • How can I implement this? Add 2 new class? – lamwaiman1988 Apr 27 '11 at 04:05
  • 2
    Yes. And modify your `Data` class. Just write code. There is no magic. The classnames doesn't really matter, it's just a kickoff example. You're the programmer, not us. By the way, Websphere 7 is I believe still on the old Servlet 2.5 version. You'd need to replace `@WebListener` by a `` entry in `/WEB-INF/web.xml`, I've edited the code example. But for the remnant it should work just fine. – BalusC Apr 27 '11 at 04:07
  • I am confused, where should I call these new class? – lamwaiman1988 Apr 27 '11 at 04:15
  • 2
    You don't need. The `` entry in `web.xml` will do it. It will let the servletcontainer (Websphere in your case) create an instance of `Config` and it will call `contextInitialized()` during startup and `contextDestroyed()` during shutdown. Please put your mouse above the blue `ServletContextListener` text in the first paragraph of my answer and press the left button. Read that document to understand what it is for. Do the same for `ScheduledExecutorService`. – BalusC Apr 27 '11 at 04:17
  • Probably scheduling the reloading each day and checking the day of month would work more reliable - if new data arrives each calendar month. 30 days interval will lead to shift of the reloading day each year and at some time it would reload twice in January and none in February. – Tomasz Stanczak Apr 27 '11 at 07:12
  • @Tomasz: a `@Singleton` EJB with `@Schedule` would be the ultimate solution. It can be scheduled for every first day of the month. See also http://stackoverflow.com/questions/5357033/background-timer-task-in-jsp-web-application/5357856#5357856 However, this requires a Java EE 6 container. – BalusC Apr 27 '11 at 16:54