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.Collection;
020    import java.util.List;
021    import java.util.concurrent.Callable;
022    import java.util.concurrent.ExecutionException;
023    import java.util.concurrent.ExecutorService;
024    import java.util.concurrent.Future;
025    import java.util.concurrent.RejectedExecutionException;
026    import java.util.concurrent.TimeUnit;
027    import java.util.concurrent.TimeoutException;
028    
029    
030    
031    /**
032     * A manageable version of a {@link java.util.concurrent.ExecutorService}.<p>
033     *
034     * A ManagedExecutorService provides methods for submitting tasks for execution
035     * in a managed environment.  Implementations of the ManagedExecutorService are
036     * provided by a Java&trade; EE Product Provider.  Application Component Providers
037     * use the Java Naming and Directory Interface&trade; (JNDI) to look-up instances of one
038     * or more ManagedExecutorService objects using resource environment references.<p>
039     *
040     * The Concurrency Utilities for Java&trade; EE specification describes several
041     * behaviors that a ManagedExecutorService can implement.  The Application
042     * Component Provider and Deployer identify these requirements and map the
043     * resource environment reference appropriately.<p>
044     *
045     * The most common uses for a ManagedExecutorService is to run short-duration asynchronous
046     * tasks in the local JVM from a container such as an Enterprise
047     * JavaBean&trade; (EJB&trade;) or servlet.  Use a managed ThreadFactory for long-running
048     * daemon tasks.<p>
049     *
050     * Tasks run within the application component context that either
051     * submitted the task or created the ManagedExecutorService instance (server-managed or component-managed).
052     * All tasks run without an explicit transaction (they do not enlist in the application
053     * component's transaction).  If a transaction is required, use a
054     * {@link javax.transaction.UserTransaction} instance.  A UserTransaction instance is
055     * available in JNDI using the name: &QUOT;java:comp/UserTransaction&QUOT<p>
056     *
057     * Example:<pre>
058     * public run() {
059     *     // Begin of task
060     *     InitialContext ctx = new InitialContext();
061     *     UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
062     *     ut.begin();
063     *
064     *     // Perform transactional business logic
065     *
066     *     ut.commit();
067     * }</PRE>
068     *
069     * Asynchronous tasks are typically submitted to the ManagedExecutorService using one
070     * of the <code>submit</code> methods, each of which return a {@link java.util.concurrent.Future}
071     * instance.  The <code>Future</code> represents the result of the task and can also be used to
072     * check if the task is complete or wait for its completion.<p>
073     *
074     * If the task is cancelled, the result fo the task is a
075     * {@link java.util.concurrent.CancellationException} exception.  If the task is unable
076     * to run due to start due to a reason other than cancellation, the result is a
077     * {@link javax.util.concurrent.AbortedException} exception.<p>
078     *
079     * Example:<pre>
080     * &#47;**
081     *  * Retrieve all accounts from several account databases in parallel.
082     *  * Resource Mappings:
083     *  *  type:      javax.util.concurrent.ManagedExecutorService
084     *  *  jndi-name: mes/ThreadPool
085     *  *  attributes:
086     *  *    Run Location = Local
087     *  *&#47;
088     * public List<Account> getAccounts(long accountId) {
089     *     try {
090     *         javax.naming.InitialContext ctx = new InitialContext();
091     *         <b>ManagedExecutorService mes = (ManagedExecutorService)
092     *             ctx.lookup("java:comp/env/concurrent/ThreadPool");</b>
093     *
094     *         // Create a set of tasks to perform the account retrieval.
095     *         ArrayList<Callable<Account>> retrieverTasks = new ArrayList<Callable<Account>>();
096     *         retrieverTasks.add(new EISAccountRetriever());
097     *         retrieverTasks.add(new RDBAccountRetriever());
098     *
099     *         // Submit the tasks to the thread pool and wait for them
100     *         // to complete (successfully or otherwise).
101     *         <b>List<Future<Account>> taskResults= mes.invokeAll(retrieverTasks);</b>
102     *
103     *         // Retrieve the results from the resulting Future list.
104     *         ArrayList<Account> results = new ArrayList<Account>();
105     *         for(Future<Account> taskResult : taskResults) {
106     *             try {
107     *                 <b>results.add(taskResult.get());</b>
108     *             } catch (ExecutionException e) {
109     *                 Throwable cause = e.getCause();
110     *                 // Handle the AccountRetrieverError.
111     *             }
112     *         }
113     *
114     *         return results;
115     *
116     *     } catch (NamingException e) {
117     *         // Throw exception for fatal error.
118     *     } catch (InterruptedException e) {
119     *         // Throw exception for shutdown or other interrupt condition.
120     *     }
121     *   }
122     *
123     * }
124     *
125     * public class EISAccountRetriever implements Callable<Account> {
126     *     public Account call() {
127     *         // Connect to our eis system and retrieve the info for the account.
128     *         //...
129     *         return null;
130     *     }
131     * }
132     *
133     * public class RDBAccountRetriever implements Callable<Account> {
134     *     public Account call() {
135     *         // Connect to our database and retrieve the info for the account.
136     *         //...
137     *     }
138     * }
139     *
140     * public class Account {
141     *     // Some account data...
142     * }
143     *
144     *</pre>
145     */
146    public interface ManagedExecutorService extends ExecutorService
147    {
148        /**
149         * This method has the same semantics as {@link ExecutorService#submit(java.lang.Runnable)}
150         * but also includes the ability to be notified when the task's lifecycle changes.
151         *
152         * @param task the task to submit
153         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
154         * @return a Future representing pending completion of the task,
155         * and whose <tt>get()</tt> method will return <tt>null</tt>
156         * upon completion.
157         * @throws RejectedExecutionException if task cannot be scheduled
158         * for execution
159         * @throws NullPointerException if task null
160         */
161        Future<?> submit(Runnable task, ManagedTaskListener taskListener);
162    
163        /**
164         * This method has the same semantics as {@link ExecutorService#submit(java.lang.Runnable, T)}
165         * but also includes the ability to be notified when the task's lifecycle changes.
166         *
167         * @param task the task to submit
168         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
169         * @param result the result to return
170         * @return a Future representing pending completion of the task,
171         * and whose <tt>get()</tt> method will return the given result
172         * upon completion.
173         * @throws RejectedExecutionException if task cannot be scheduled
174         * for execution
175         * @throws NullPointerException if task null
176         */
177        <T> Future<T> submit(Runnable task, T result, ManagedTaskListener taskListener);
178    
179        /**
180         * This method has the same semantics as {@link ExecutorService#submit(java.util.concurrent.Callable)}
181         * but also includes the ability to be notified when the task's lifecycle changes.
182         *
183         * @param task the task to submit
184         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
185         * @return a Future representing pending completion of the task
186         * @throws RejectedExecutionException if task cannot be scheduled
187         * for execution
188         * @throws NullPointerException if task null
189         */
190        <T> Future<T> submit(Callable<T> task, ManagedTaskListener taskListener);
191    
192        /**
193         * This method has the same semantics as {@link ExecutorService#invokeAll(java.util.Collection)}
194         * but also includes the ability to be notified when each task's lifecycle changes.
195         *
196         * @param tasks the collection of tasks
197         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
198         * @return A list of Futures representing the tasks, in the same
199         * sequential order as produced by the iterator for the given task
200         * list, each of which has completed.
201         * @throws InterruptedException if interrupted while waiting, in
202         * which case unfinished tasks are cancelled.
203         * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
204         * @throws RejectedExecutionException if any task cannot be scheduled
205         * for execution
206         */
207        <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks, ManagedTaskListener taskListener)
208            throws InterruptedException;
209    
210        /**
211         * This method has the same semantics as
212         * {@link ExecutorService#invokeAll(java.util.Collection, long, java.util.concurrent.TimeUnit)}
213         * but also includes the ability to be notified when each task's lifecycle changes.
214         *
215         * @param tasks the collection of tasks
216         * @param timeout the maximum time to wait
217         * @param unit the time unit of the timeout argument
218         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
219         * @return A list of Futures representing the tasks, in the same
220         * sequential order as produced by the iterator for the given
221         * task list. If the operation did not time out, each task will
222         * have completed. If it did time out, some of these tasks will
223         * not have completed.
224         * @throws InterruptedException if interrupted while waiting, in
225         * which case unfinished tasks are cancelled.
226         * @throws NullPointerException if tasks, any of its elements, or
227         * unit are <tt>null</tt>
228         * @throws RejectedExecutionException if any task cannot be scheduled
229         * for execution
230         */
231        <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
232                                        long timeout, TimeUnit unit, ManagedTaskListener taskListener)
233            throws InterruptedException;
234    
235        /**
236         * This method has the same semantics as
237         * {@link ExecutorService#invokeAny(java.util.Collection)}
238         * but also includes the ability to be notified when each task's lifecycle changes.
239         *
240         * Executes the given tasks, returning the result
241         * of one that has completed successfully (i.e., without throwing
242         * an exception), if any do. Upon normal or exceptional return,
243         * tasks that have not completed are cancelled.
244         * The results of this method are undefined if the given
245         * collection is modified while this operation is in progress.
246         * @param tasks the collection of tasks
247         * @param taskListener the ManagedTaskListener instance to receive a task's lifecycle events.
248         * @return The result returned by one of the tasks.
249         * @throws InterruptedException if interrupted while waiting
250         * @throws NullPointerException if tasks or any of its elements
251         * are <tt>null</tt>
252         * @throws IllegalArgumentException if tasks empty
253         * @throws ExecutionException if no task successfully completes
254         * @throws RejectedExecutionException if tasks cannot be scheduled
255         * for execution
256         */
257        <T> T invokeAny(Collection<Callable<T>> tasks, ManagedTaskListener taskListener)
258            throws InterruptedException, ExecutionException;
259    
260        /**
261         * This method has the same semantics as
262         * {@link ExecutorService#invokeAny(java.util.Collection, long, java.util.concurrent.TimeUnit)}
263         * but also includes the ability to be notified when each task's lifecycle changes.
264         *
265         * @param tasks the collection of tasks
266         * @param timeout the maximum time to wait
267         * @param unit the time unit of the timeout argument
268         * @return The result returned by one of the tasks.
269         * @throws InterruptedException if interrupted while waiting
270         * @throws NullPointerException if tasks, any of its elements, or
271         * unit are <tt>null</tt>
272         * @throws TimeoutException if the given timeout elapses before
273         * any task successfully completes
274         * @throws ExecutionException if no task successfully completes
275         * @throws RejectedExecutionException if tasks cannot be scheduled
276         * for execution
277         */
278        <T> T invokeAny(Collection<Callable<T>> tasks,
279                        long timeout, TimeUnit unit, ManagedTaskListener taskListener)
280            throws InterruptedException, ExecutionException, TimeoutException;
281    
282    
283    }