ams
ams

Reputation: 62702

How to perform an expensive one time initialization in a Servlet filter?

Here are the requirements for the problem:

I am trying to use the servlet filter below to solve the problem. and I have following questions.

 package com.exmaple;
    @WebFilter("/*")

 public class InitFilter implements Filter 
 {
    private volatile boolean initialized = false;

    public void destroy() {
        System.out.println("InitFilter.destroy()");
    }

        // is this method thread safe and will only execute the init code once
        // and will cause all requests to wait until initialization code is executed
        // thread code
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            System.out.println("InitFilter.doFilter()");

            if (initialized == false) {
                synchronized (this) {
                    // do expensive initialization work here
                    initialized = true;
                }
            }
            chain.doFilter(request, response);
        }

        public void init(FilterConfig fConfig) throws ServletException {
            System.out.println("InitFilter.init()");
        }
      }

Upvotes: 1

Views: 997

Answers (2)

Stephen P
Stephen P

Reputation: 14810

I would approach it as a ServletContextListener and run the initialization in the contextInitialized method, as a separate thread, maybe using a FutureTask as @fge suggests, or a newSingleThreadExecutor rather than a pool.

Maybe something along the lines of...

public void contextInitialized(ServletContextEvent sce)
{
    Executors.newSingleThreadExecutor().execute(new Runnable() {

        @Override
        public void run()
        {
            // Long running initialization code, or a call to it.
        }

    });

}

This avoids problems with synchronization and only runs the initialization once. (Once per Context)

In any case, doing this or a Filter, the rest of your program has to deal with initialization being incomplete.

Upvotes: 1

Danilo Muñoz
Danilo Muñoz

Reputation: 623

I recommend you to put your long-running initialization in a thread, like:

public void init() throws ServletException {
    //Configure logging, app, pool ...
    MyAppStarter.getInstance().start();
}

Upvotes: 0

Related Questions