Submitting Callable to ExecutorService is never completed

471 views Asked by At

The problem which i am facing has been nagging for a week now and here it is: I have a class AdminBlocageBackgroundProcessing.java which processes a CSV file by reading data from it and validating it and storing it in a array list as:

public Object call( ) {
    // TODO Auto-generated method stub
    try{
    data = ImportMetier.extractFromCSV(
        new String(fichier.getFileData(), 
                   "ISO-8859-1"),blocage);

    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return data;

}

And i am calling it from my action class using :

ServletContext servletContext=getServlet().getServletContext();
ExecutorService execService = (ExecutorService)servletContext.getAttribute("threadPoolAlias");
AdminBlocageBackgroundProcessing adminBlocageBackgroundProcessing= new AdminBlocageBackgroundProcessing(fichier,blocage);
if(status==0 && refreshParam.equals("eventParameter"))
        {
                future= execService.submit(adminBlocageBackgroundProcessing);
                status=1;
                autoRefControl=1;
                req.setAttribute("CHARGEMENT_EN_COURS","chargement");
                return mapping.findForward("self");
        }



        if(status==1)
        {
        // for checking if the submitted future task is completed or not    
        isFutureDone=future.isDone();

        if(isFutureDone)
        {
            data=future.get();
            status=0;
            System.out.println("Process is Completed");
            req.setAttribute("TRAITEMENT_TERMINE","termine");
            //sessiondata.putBean(Constantes.BEAN_CONTRATCLIENT_CONTRAT_CLE_FIA, null);
            //formulaire.set("refreshParam","" );
            execService.shutdown();
            isFutureDone=false;

        }
        else{
            System.out.println("Les données sont encore en cours de traitement");
            req.setAttribute("CHARGEMENT_EN_ENCORE","encore");
            return mapping.findForward("self");
            }
        }

Now the problem is CSV is having too much data and when we click for importing it, the process is started in background asynchronously but it never gets to completion although have used autorefresh in jsp to maintain the session. How can we make sure that it is completed although the code is working fine for small data?
but for large data this functionality crumbles and cannot be monitored.

The threadpool which i am using is provided by the container :

public class ThreadPoolServlet implements ServletContextListener
 {

    public void contextDestroyed(ServletContextEvent arg0) {
    final ExecutorService execService = (ExecutorService) arg0.getServletContext().getAttribute("threadPoolAlias");
    execService.shutdown();
    System.out.println("ServletContextListener destroyed");
    // TODO Auto-generated method stub

}
    //for initializing the thread pool
    public void contextInitialized(ServletContextEvent arg0) {
    // TODO Auto-generated method stub
      final ExecutorService execService = Executors.newFixedThreadPool(25);
      final ServletContext servletContext = arg0.getServletContext();
      servletContext.setAttribute("threadPoolAlias", execService);
      System.out.println("ServletContextListener started");         
}

}

1

There are 1 answers

0
foamroll On BEST ANSWER

Had a quick look.. your isFutureDone depends on status, which is executed right after the submission of the task - which is fairly quick. status is updated only once, and not updated again. This is fine in the case of very short, seemingly instant, tasks, though it will break for large tasks. It breaks because you use the future.get method conditionally based on the isFutureDone, which will be false for longer tasks. So you never get a result, even though your task completed in the executor. Do away with isFutureDone. Read up a bit on [Future.get][1] (both versions [with and without timeout] block, which is what you need here - to wait for the task to finish). It would be a good idea to utilize a timeout in your code that calls the CSV service, to allow for a failure if it takes inappropriately long.