How to stop a java code from running using a stop button

前端 未结 2 743
被撕碎了的回忆
被撕碎了的回忆 2021-02-05 21:45

I have a button that calls a method from the backing Bean. This method allows to extract data from parsing html code. While the method is running i have a dialog showing a progr

2条回答
  •  [愿得一人]
    2021-02-05 22:03

    With your current architecture it's not going to be easy. By looking at your code it seems that you are calling two big operations that can't be aborted in the middle. You must break the work into small units and make the processing abortable.

    The easiest solution that uses your current code could look something like this.

     public class SessionScopedMailBean {
         volatile boolean searchAborted;
    
         public void searchEmails() throws Exception {
             searchAborted = false;
             while(!searchAborted) {
                 // Process a single unit of work
             }
         }
    
         public void abortSearch() {
             searchAborted = true;
         }
    }
    

    In JSF:

    
    

    That said I'd recommend using executors and futures based approach for cleaner architecture. Then you can also implement a real progress bar not just an animated GIF spinner.

    Another problem with performing a long operation in command handler is that eventually the HTTP request will time out.

    A cleaner solution will look like this:

    public class SessionScopedBean {
        ExecutorService pool;
        List> pendingWork;
    
        @PostConstruct
        public void startPool() {
            pool = Executors.newFixedThreadPool(1);
        }
    
        @PreDestroy
        public void stopPool() {
            if(executor != null)
                pool.shutdownNow();
        }
    
        public void startSearch() {
            pendingWork = new ArrayList>();
    
            // Prepare units of work (assuming it can be done quickly)
            while(/* no more work found */) {
                final MyType unit = ...; // Determine next unit of work
                Callable worker = new Callable() {
                    @Override
                    public Void call() throws Exception {
                        // Do whatever is needed to complete unit
                    }
                };
                pendingWork.add(pool.submit(worker));
            }
        }
    
        public int getPending() {
            int nPending = 0;
    
            for(Future i: pendingWork)
                if(!i.isDone()) nPending++;
    
            return nPending;
        }
    
        public void stopSearch() {
            for(Future i: pendingWork)
                if(!i.isDone()) i.cancel(true);
        }
    }
    

    Then use an AJAX polling component to poll getPending to determine when it's done and hide the window.

    See also:

    • http://www.vogella.com/tutorials/JavaConcurrency/article.html#futures
    • JSF polling a database from an application bean at timed intervals
    • http://www.mkyong.com/spring/spring-postconstruct-and-predestroy-example/

提交回复
热议问题