[jboss-jira] [JBoss JIRA] (WFLY-3683) ScheduledFuture#cancel(boolean) failing to cancel tasks on bean PreDestroy

Aaron Cordova (JIRA) issues at jboss.org
Mon Jul 28 19:45:31 EDT 2014


Aaron Cordova created WFLY-3683:
-----------------------------------

             Summary: ScheduledFuture#cancel(boolean) failing to cancel tasks on bean PreDestroy
                 Key: WFLY-3683
                 URL: https://issues.jboss.org/browse/WFLY-3683
             Project: WildFly
          Issue Type: Feature Request
      Security Level: Public (Everyone can see)
          Components: EE
    Affects Versions: 8.1.0.Final
            Reporter: Aaron Cordova
            Assignee: David Lloyd


Calls to ScheduledFuture#cancel on bean cleanup are failing to cancel subsequent tasks. 

*NOTE* This only occurs when using the Trigger function. I tested the same code with scheduleAtFixedRate, and it works as expected.

The following bean demonstrates the bug:
{code:title=Executor.java|borderStyle=sold}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.concurrent.LastExecution;
import javax.enterprise.concurrent.ManagedScheduledExecutorService;
import javax.enterprise.concurrent.Trigger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Session Bean implementation class DataRecorderManagerBean
 */
@Singleton
@Startup
public class ExecutorBug {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorBug.class);

    @Resource
    private ManagedScheduledExecutorService executorService;

    private List<ScheduledFuture<?>> scheduledTasks;

    /**
     * Default constructor.
     */
    public ExecutorBug() {
    }

    @PostConstruct
    void intialize() {
        this.scheduledTasks = Collections.synchronizedList(new ArrayList<ScheduledFuture<?>>());

        // Schedule the device task.
        PeriodicTrigger trigger = new PeriodicTrigger(0, 10, TimeUnit.SECONDS);
        ScheduledFuture<?> future = this.executorService.schedule(new LogRunner(), trigger);

        // Create the scheduled task and add it to the map.
        this.scheduledTasks.add(future);
    }

    @PreDestroy
    void cleanup() {
        // Cancel any scheduled tasks, ensuring that the map is locked.
        synchronized (this.scheduledTasks) {
            Iterator<ScheduledFuture<?>> i = this.scheduledTasks.iterator();

            while (i.hasNext()) {
                ScheduledFuture<?> future = i.next();
                // Cancel the task.
                future.cancel(true);
            }
        }
        this.scheduledTasks.clear();
        this.scheduledTasks = null;
    }

    private class LogRunner implements Runnable {
        public LogRunner() {
        }

        @Override
        public void run() {
            LOGGER.info("I am running");
        }
    }

    private class PeriodicTrigger implements Trigger {
        private final long periodMillis;
        private Date startTime;

        /**
         * Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay
         * then initialDelay+period, then initialDelay + 2 * period, and so on.
         * 
         * @param initialDelay the time to delay first execution
         * @param period the period between successive executions
         * @param unit the time unit of the initialDelay and period parameters
         */
        public PeriodicTrigger(final long initialDelay, final long period, final TimeUnit unit) {
            this.periodMillis = TimeUnit.MILLISECONDS.convert(period, unit);

            // Calculate the start time.
            Date now = new Date();
            long millis = TimeUnit.MILLISECONDS.convert(initialDelay, unit);
            this.startTime = new Date(now.getTime() + millis);
        }


        @Override
        public Date getNextRunTime(final LastExecution lastExecutionInfo, final Date taskScheduledTime) {
            if (lastExecutionInfo == null) {
                return this.startTime;
            }
            else {
                return new Date(lastExecutionInfo.getScheduledStart().getTime() + this.periodMillis);
            }
        }

        @Override
        public boolean skipRun(final LastExecution lastExecutionInfo, final Date scheduledRunTime) {
            return false;
        }
    }
}
{code}



--
This message was sent by Atlassian JIRA
(v6.2.6#6264)


More information about the jboss-jira mailing list