@@ -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 );
0 commit comments