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"> </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"> </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"> </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"> </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"> </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 }