Skip to content

Commit 4abf157

Browse files
committed
Fix InvocationContext reuse in scheduled async and add missing license headers
Replace ctx.proceed() with direct Method.invoke() in scheduled async re-executions. InvocationContext's interceptor iterator is single-use, so re-calling proceed() would bypass TX/security interceptors after the first scheduled execution. Context propagation is handled by ContextService.enter/exit. Also add Apache License headers to TCK resource files to fix RAT check.
1 parent dceef6e commit 4abf157

3 files changed

Lines changed: 51 additions & 6 deletions

File tree

container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,15 @@ private Object aroundInvokeScheduled(final InvocationContext ctx, final Asynchro
147147
final AtomicReference<ScheduledFuture<?>> scheduledRef = new AtomicReference<>();
148148
final AtomicReference<LastExecution> lastExecutionRef = new AtomicReference<>();
149149

150+
// Extract method and target from InvocationContext for direct invocation.
151+
// We must NOT reuse ctx.proceed() — InvocationContext's interceptor iterator
152+
// is single-use, so subsequent proceed() calls would bypass TX/security interceptors.
153+
final Method beanMethod = ctx.getMethod();
154+
final Object target = ctx.getTarget();
155+
final Object[] params = ctx.getParameters();
156+
150157
scheduleNextExecution(triggerDelegate, snapshot, ctxService, trigger, outerFuture,
151-
ctx, isVoid, scheduledRef, lastExecutionRef);
158+
beanMethod, target, params, isVoid, scheduledRef, lastExecutionRef);
152159

153160
// Cancel the underlying scheduled task when the future completes externally
154161
// (e.g. Asynchronous.Result.complete() or cancel())
@@ -182,7 +189,8 @@ private ManagedScheduledExecutorServiceImpl resolveMses(final String executorNam
182189

183190
private void scheduleNextExecution(final ScheduledExecutorService delegate, final ContextServiceImpl.Snapshot snapshot,
184191
final ContextServiceImpl ctxService, final ZonedTrigger trigger,
185-
final CompletableFuture<Object> future, final InvocationContext ctx,
192+
final CompletableFuture<Object> future, final Method beanMethod,
193+
final Object target, final Object[] params,
186194
final boolean isVoid, final AtomicReference<ScheduledFuture<?>> scheduledRef,
187195
final AtomicReference<LastExecution> lastExecutionRef) {
188196
final ZonedDateTime taskScheduledTime = ZonedDateTime.now();
@@ -203,13 +211,18 @@ private void scheduleNextExecution(final ScheduledExecutorService delegate, fina
203211
if (trigger.skipRun(lastExecutionRef.get(), nextRun)) {
204212
// Skipped — reschedule for the next run
205213
scheduleNextExecution(delegate, snapshot, ctxService, trigger, future,
206-
ctx, isVoid, scheduledRef, lastExecutionRef);
214+
beanMethod, target, params, isVoid, scheduledRef, lastExecutionRef);
207215
return;
208216
}
209217

210218
final ZonedDateTime runStart = ZonedDateTime.now();
211219
Asynchronous.Result.setFuture(future);
212-
final Object result = ctx.proceed();
220+
221+
// Invoke the bean method directly instead of ctx.proceed() —
222+
// InvocationContext's interceptor iterator is single-use, so re-calling
223+
// proceed() would bypass other interceptors (TX, security).
224+
// Context propagation is handled by ContextService.enter/exit above.
225+
final Object result = beanMethod.invoke(target, params);
213226
final ZonedDateTime runEnd = ZonedDateTime.now();
214227

215228
// Track last execution for trigger computation
@@ -218,7 +231,7 @@ private void scheduleNextExecution(final ScheduledExecutorService delegate, fina
218231
if (isVoid) {
219232
Asynchronous.Result.setFuture(null);
220233
scheduleNextExecution(delegate, snapshot, ctxService, trigger, future,
221-
ctx, isVoid, scheduledRef, lastExecutionRef);
234+
beanMethod, target, params, isVoid, scheduledRef, lastExecutionRef);
222235
return;
223236
}
224237

@@ -241,7 +254,10 @@ private void scheduleNextExecution(final ScheduledExecutorService delegate, fina
241254
Asynchronous.Result.setFuture(null);
242255
// null return: schedule continues
243256
scheduleNextExecution(delegate, snapshot, ctxService, trigger, future,
244-
ctx, isVoid, scheduledRef, lastExecutionRef);
257+
beanMethod, target, params, isVoid, scheduledRef, lastExecutionRef);
258+
} catch (final java.lang.reflect.InvocationTargetException e) {
259+
future.completeExceptionally(e.getCause() != null ? e.getCause() : e);
260+
Asynchronous.Result.setFuture(null);
245261
} catch (final Exception e) {
246262
future.completeExceptionally(e);
247263
Asynchronous.Result.setFuture(null);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
115
org.apache.tomee.tck.concurrency.ConcurrencyTCKExtension

tck/concurrency-standalone/src/test/resources/logging.properties

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
116
## Logging configuration for Concurrency TCK
217

318
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler

0 commit comments

Comments
 (0)