001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.commonj; 018 019import java.util.Collection; 020import java.util.concurrent.Callable; 021import java.util.concurrent.Future; 022import java.util.concurrent.FutureTask; 023 024import javax.naming.NamingException; 025 026import commonj.work.Work; 027import commonj.work.WorkException; 028import commonj.work.WorkItem; 029import commonj.work.WorkListener; 030import commonj.work.WorkManager; 031import commonj.work.WorkRejectedException; 032 033import org.springframework.beans.factory.InitializingBean; 034import org.springframework.core.task.AsyncListenableTaskExecutor; 035import org.springframework.core.task.TaskDecorator; 036import org.springframework.core.task.TaskRejectedException; 037import org.springframework.jndi.JndiLocatorSupport; 038import org.springframework.lang.Nullable; 039import org.springframework.scheduling.SchedulingException; 040import org.springframework.scheduling.SchedulingTaskExecutor; 041import org.springframework.util.Assert; 042import org.springframework.util.concurrent.ListenableFuture; 043import org.springframework.util.concurrent.ListenableFutureTask; 044 045/** 046 * TaskExecutor implementation that delegates to a CommonJ WorkManager, 047 * implementing the {@link commonj.work.WorkManager} interface, 048 * which either needs to be specified as reference or through the JNDI name. 049 * 050 * <p><b>This is the central convenience class for setting up a 051 * CommonJ WorkManager in a Spring context.</b> 052 * 053 * <p>Also implements the CommonJ WorkManager interface itself, delegating all 054 * calls to the target WorkManager. Hence, a caller can choose whether it wants 055 * to talk to this executor through the Spring TaskExecutor interface or the 056 * CommonJ WorkManager interface. 057 * 058 * <p>The CommonJ WorkManager will usually be retrieved from the application 059 * server's JNDI environment, as defined in the server's management console. 060 * 061 * <p>Note: On EE 7/8 compliant versions of WebLogic and WebSphere, a 062 * {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} 063 * should be preferred, following JSR-236 support in Java EE 7/8. 064 * 065 * @author Juergen Hoeller 066 * @since 2.0 067 * @deprecated as of 5.1, in favor of the EE 7/8 based 068 * {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} 069 */ 070@Deprecated 071public class WorkManagerTaskExecutor extends JndiLocatorSupport 072 implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, InitializingBean { 073 074 @Nullable 075 private WorkManager workManager; 076 077 @Nullable 078 private String workManagerName; 079 080 @Nullable 081 private WorkListener workListener; 082 083 @Nullable 084 private TaskDecorator taskDecorator; 085 086 087 /** 088 * Specify the CommonJ WorkManager to delegate to. 089 * <p>Alternatively, you can also specify the JNDI name of the target WorkManager. 090 * @see #setWorkManagerName 091 */ 092 public void setWorkManager(WorkManager workManager) { 093 this.workManager = workManager; 094 } 095 096 /** 097 * Set the JNDI name of the CommonJ WorkManager. 098 * <p>This can either be a fully qualified JNDI name, or the JNDI name relative 099 * to the current environment naming context if "resourceRef" is set to "true". 100 * @see #setWorkManager 101 * @see #setResourceRef 102 */ 103 public void setWorkManagerName(String workManagerName) { 104 this.workManagerName = workManagerName; 105 } 106 107 /** 108 * Specify a CommonJ WorkListener to apply, if any. 109 * <p>This shared WorkListener instance will be passed on to the 110 * WorkManager by all {@link #execute} calls on this TaskExecutor. 111 */ 112 public void setWorkListener(WorkListener workListener) { 113 this.workListener = workListener; 114 } 115 116 /** 117 * Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable} 118 * about to be executed. 119 * <p>Note that such a decorator is not necessarily being applied to the 120 * user-supplied {@code Runnable}/{@code Callable} but rather to the actual 121 * execution callback (which may be a wrapper around the user-supplied task). 122 * <p>The primary use case is to set some execution context around the task's 123 * invocation, or to provide some monitoring/statistics for task execution. 124 * <p><b>NOTE:</b> Exception handling in {@code TaskDecorator} implementations 125 * is limited to plain {@code Runnable} execution via {@code execute} calls. 126 * In case of {@code #submit} calls, the exposed {@code Runnable} will be a 127 * {@code FutureTask} which does not propagate any exceptions; you might 128 * have to cast it and call {@code Future#get} to evaluate exceptions. 129 * @since 4.3 130 */ 131 public void setTaskDecorator(TaskDecorator taskDecorator) { 132 this.taskDecorator = taskDecorator; 133 } 134 135 @Override 136 public void afterPropertiesSet() throws NamingException { 137 if (this.workManager == null) { 138 if (this.workManagerName == null) { 139 throw new IllegalArgumentException("Either 'workManager' or 'workManagerName' must be specified"); 140 } 141 this.workManager = lookup(this.workManagerName, WorkManager.class); 142 } 143 } 144 145 private WorkManager obtainWorkManager() { 146 Assert.state(this.workManager != null, "No WorkManager specified"); 147 return this.workManager; 148 } 149 150 151 //------------------------------------------------------------------------- 152 // Implementation of the Spring SchedulingTaskExecutor interface 153 //------------------------------------------------------------------------- 154 155 @Override 156 public void execute(Runnable task) { 157 Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task); 158 try { 159 if (this.workListener != null) { 160 obtainWorkManager().schedule(work, this.workListener); 161 } 162 else { 163 obtainWorkManager().schedule(work); 164 } 165 } 166 catch (WorkRejectedException ex) { 167 throw new TaskRejectedException("CommonJ WorkManager did not accept task: " + task, ex); 168 } 169 catch (WorkException ex) { 170 throw new SchedulingException("Could not schedule task on CommonJ WorkManager", ex); 171 } 172 } 173 174 @Override 175 public void execute(Runnable task, long startTimeout) { 176 execute(task); 177 } 178 179 @Override 180 public Future<?> submit(Runnable task) { 181 FutureTask<Object> future = new FutureTask<>(task, null); 182 execute(future); 183 return future; 184 } 185 186 @Override 187 public <T> Future<T> submit(Callable<T> task) { 188 FutureTask<T> future = new FutureTask<>(task); 189 execute(future); 190 return future; 191 } 192 193 @Override 194 public ListenableFuture<?> submitListenable(Runnable task) { 195 ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null); 196 execute(future); 197 return future; 198 } 199 200 @Override 201 public <T> ListenableFuture<T> submitListenable(Callable<T> task) { 202 ListenableFutureTask<T> future = new ListenableFutureTask<>(task); 203 execute(future); 204 return future; 205 } 206 207 208 //------------------------------------------------------------------------- 209 // Implementation of the CommonJ WorkManager interface 210 //------------------------------------------------------------------------- 211 212 @Override 213 public WorkItem schedule(Work work) throws WorkException, IllegalArgumentException { 214 return obtainWorkManager().schedule(work); 215 } 216 217 @Override 218 public WorkItem schedule(Work work, WorkListener workListener) throws WorkException { 219 return obtainWorkManager().schedule(work, workListener); 220 } 221 222 @Override 223 @SuppressWarnings("rawtypes") 224 public boolean waitForAll(Collection workItems, long timeout) throws InterruptedException { 225 return obtainWorkManager().waitForAll(workItems, timeout); 226 } 227 228 @Override 229 @SuppressWarnings("rawtypes") 230 public Collection waitForAny(Collection workItems, long timeout) throws InterruptedException { 231 return obtainWorkManager().waitForAny(workItems, timeout); 232 } 233 234}