001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package javax.util.concurrent;
018    
019    import java.util.concurrent.Future;
020    
021    
022    
023    /**
024     * A ManagedTaskListener is used to monitor the state of a task's Future.
025     * It can be registered with a {@link javax.util.concurrent.ManagedExecutorService} using the
026     * <code>submit</code> methods and will be invoked when the state of the Future changes.
027     * Each listener method will run with the same context in which the task runs.
028     * The listener becomes a Contextual Task.  All listeners run without an explicit transaction (they do not enlist in the application
029     * component's transaction).  If a transaction is required, use a
030     * {@link javax.transaction.UserTransaction} instance.<p>
031     *
032     * Each listener instance will be invoked within the same process in which the listener was registered.
033     * If a single listener is submitted to multiple ManagedExecutorService instances, the
034     * listener object may be invoked concurrently by multiple threads.<p>
035     *
036     * Each listener method supports a minimum quality of service of at-most-once.  A listener is not
037     * guaranteed to be invoked due to a process failure or termination.
038     *
039     * <b>State Transition Diagram</b>
040     * The following state transition figure and tables describe
041     * the possible task lifecycle events that can occur when a
042     * ManagedTaskListener is associated with a task.  Each method is invoked
043     * when the state of the future moves from one state to another.<p>
044     * <img src="doc-files/TaskListener_StateDiagram.gif"><p>
045     *
046     * <b>A. The task runs normally:</b>
047     * <table>
048     * <tr><td valign="top"><strong><u>Sequence</u></strong></td><td valign="top"><strong><u>State</u></strong></td><td valign="top"><strong><u>Action</u></strong></td><td valign="top"><strong><u>Listener</u></strong></td><td valign="top"><strong><u>Next state</u></strong></td></tr>
049     * <tr><td valign="top">1.</td><td valign="top">None</td><td valign="top">submit()</td><td valign="top">taskSubmitted</td><td valign="top">Submitted</td></tr>
050     * <tr><td valign="top">2.</td><td valign="top">Submitted</td><td valign="top">About to call run()</td><td valign="top">taskStarting</td><td valign="top">Started</td></tr>
051     * <tr><td valign="top">3.</td><td valign="top">Started</td><td valign="top">Exit run()</td><td valign="top">taskDone</td><td valign="top">Done</td></tr>
052     * </table><p>
053     *
054     * <b>B. The task is cancelled during taskSubmitted():</b>
055     * <table>
056     * <tr><td valign="top"><strong><u>Sequence</u></strong></td><td valign="top"><strong><u>State</u></strong></td><td valign="top"><strong><u>Action</u></strong></td><td valign="top"><strong><u>Listener</u></strong></td><td valign="top"><strong><u>Next state</u></strong></td></tr>
057     * <tr><td valign="top">1.</td><td valign="top">None</td><td valign="top">submit()</td><td valign="top">taskSubmitted<br>Future is cancelled.</td><td valign="top">Cancelling</td></tr>
058     * <tr><td valign="top">2.</td><td valign="top">Cancelling</td><td valign="top">&nbsp;</td><td valign="top">taskAborted</td><td valign="top">Cancelled</td></tr>
059     * <tr><td valign="top">3.</td><td valign="top">Cancelled</td><td valign="top">&nbsp;</td><td valign="top">taskDone</td><td valign="top">Done</td></tr>
060     * </table><p>
061     *
062     * <b>C. The task is cancelled or aborted after submitted, but before started:</b>
063     * <table>
064     * <tr><td valign="top"><strong><u>Sequence</u></strong></td><td valign="top"><strong><u>State</u></strong></td><td valign="top"><strong><u>Action</u></strong></td><td valign="top"><strong><u>Listener</u></strong></td><td valign="top"><strong><u>Next state</u></strong></td></tr>
065     * <tr><td valign="top">1.</td><td valign="top">None</td><td valign="top">submit()</td><td valign="top">taskSubmitted</td><td valign="top">Submitted</td></tr>
066     * <tr><td valign="top">2.</td><td valign="top">Submitted</td><td valign="top">cancel() or abort</td><td valign="top">taskAborted</td><td valign="top">Cancelled</td></tr>
067     * <tr><td valign="top">3.</td><td valign="top">Cancelled</td><td valign="top">&nbsp;</td><td valign="top">taskDone</td><td valign="top">Done</td></tr>
068     * </table><p>
069     *
070     * <b>D. The task is cancelled when it is starting:</b>
071     * <table>
072     * <tr><td valign="top"><strong><u>Sequence</u></strong></td><td valign="top"><strong><u>State</u></strong></td><td valign="top"><strong><u>Action</u></strong></td><td valign="top"><strong><u>Listener</u></strong></td><td valign="top"><strong><u>Next state</u></strong></td></tr>
073     * <tr><td valign="top">1.</td><td valign="top">None</td><td valign="top">submit()</td><td valign="top">taskSubmitted</td><td valign="top">Submitted</td></tr>
074     * <tr><td valign="top">2.</td><td valign="top">Submitted</td><td valign="top">About to call run()</td><td valign="top">taskStarting<br>Future is cancelled.</td><td valign="top">Cancelling</td></tr>
075     * <tr><td valign="top">3.</td><td valign="top">Cancelling</td><td valign="top">&nbsp;</td><td valign="top">taskAborted</td><td valign="top">Cancelled</td></tr>
076     * <tr><td valign="top">4.</td><td valign="top">Cancelled</td><td valign="top">&nbsp;</td><td valign="top">taskDone</td><td valign="top">Done</td></tr>
077     * </table>
078     */
079    public interface ManagedTaskListener
080    {
081        /**
082         * Called after the task has been submitted to the Executor.
083         * The task will not enter the starting state until the taskSubmitted
084         * listener has completed.  This method may be called from
085         * the same thread that the task was submitted with. <p>
086         *
087         * This event does not indicate that the task has been scheduled for execution.
088         *
089         * @param future the future instance that was created when the task was submitted.
090         * The <code>Future.get()</code> methods should not be used within the scope
091         * of this listener method, as they may cause deadlocks.
092         * @param executor the executor used to run the associated Future.
093         */
094        void taskSubmitted(Future<?> future, ManagedExecutorService executor);
095    
096        /**
097         * Called when a task?s Future has been cancelled anytime
098         * during the life of a task.  This method may be called after taskDone().
099         *
100         * The <code>Future.isCancelled()</code> method returns false if the task was aborted
101         * through another means other than Future.cancel().  The Future.get() method will throw
102         * an exception that will represent the cause of the cancellation:
103         * <ul>
104         * <li>{@link java.util.concurrent.CancellationException} if the task was cancelled,
105         * <li>{@link javax.util.concurrent.SkippedException} if the task was skipped or
106         * <li>{@link javax.util.concurrent.AbortedException} if the task failed to start for another reason.
107         * </ul>
108         * The <code>AbortedException#getCause()</code> method will return the exception
109         * that caused the task to fail to start.
110         *
111         * @param future the future instance that was created when the task was submitted.
112         * @param executor the executor used to run the associated Future.
113         */
114        void taskAborted(Future<?> future, ManagedExecutorService executor, Throwable exception);
115    
116        /**
117         * Called when a submitted task has completed running, successful or otherwise after
118         * submitted.
119         * @param future the future instance that was created when the task was submitted.
120         * @param executor the executor used to run the associated Future.
121         */
122        void taskDone(Future<?> future, ManagedExecutorService executor, Throwable exception);
123    
124        /**
125         * Called when a task is about to start running.<p>
126         *
127         * This method may be called from the same thread that the task was submitted with.
128         *
129         * @param future the future instance that was created when the task was submitted.
130         * The <code>Future.get()</code> methods should not be used within the scope
131         * of this listener method, as they may cause deadlocks.
132         * @param executor the executor used to run the associated Future.
133         */
134        void taskStarting(Future<?> future, ManagedExecutorService executor);
135    
136    }