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™ EE Product Provider. Application Component Providers 037 * use the Java Naming and Directory Interface™ (JNDI) to look-up instances of one 038 * or more ManagedExecutorService objects using resource environment references.<p> 039 * 040 * The Concurrency Utilities for Java™ 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™ (EJB™) 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: "java:comp/UserTransaction"<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 * /** 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 * */ 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 }