1616 */
1717package org .apache .openejb .cdi .concurrency ;
1818
19+ import jakarta .annotation .Priority ;
1920import jakarta .enterprise .concurrent .Asynchronous ;
2021import jakarta .enterprise .concurrent .Schedule ;
2122import jakarta .enterprise .context .ApplicationScoped ;
2223import jakarta .inject .Inject ;
24+ import jakarta .interceptor .AroundInvoke ;
25+ import jakarta .interceptor .Interceptor ;
26+ import jakarta .interceptor .InterceptorBinding ;
27+ import jakarta .interceptor .InvocationContext ;
2328import org .apache .openejb .jee .EnterpriseBean ;
2429import org .apache .openejb .jee .SingletonBean ;
2530import org .apache .openejb .junit .ApplicationComposer ;
2631import org .apache .openejb .testing .Module ;
2732import org .junit .Test ;
2833import org .junit .runner .RunWith ;
2934
35+ import java .lang .annotation .ElementType ;
36+ import java .lang .annotation .Retention ;
37+ import java .lang .annotation .RetentionPolicy ;
38+ import java .lang .annotation .Target ;
3039import java .util .concurrent .CompletableFuture ;
3140import java .util .concurrent .CountDownLatch ;
3241import java .util .concurrent .TimeUnit ;
3342import java .util .concurrent .atomic .AtomicInteger ;
3443
44+ import static org .junit .Assert .assertEquals ;
3545import static org .junit .Assert .assertTrue ;
3646
3747@ RunWith (ApplicationComposer .class )
@@ -48,7 +58,7 @@ public EnterpriseBean ejb() {
4858
4959 @ Module
5060 public Class <?>[] beans () {
51- return new Class <?>[]{ScheduledBean .class };
61+ return new Class <?>[]{ScheduledBean .class , CountingInterceptor . class };
5262 }
5363
5464 @ Test
@@ -73,13 +83,31 @@ public void scheduledReturningMethodExecutes() throws Exception {
7383 + ScheduledBean .RETURNING_COUNTER .get (), reached );
7484 }
7585
86+ @ Test
87+ public void scheduledMethodExecutesThroughCdiInterceptor () throws Exception {
88+ CountingInterceptor .INVOCATIONS .set (0 );
89+ assertEquals ("Control invocation should go through the CDI interceptor" , "ok" , scheduledBean .directInterceptedCall ());
90+ assertEquals ("Control invocation should increment the CDI interceptor" , 1 , CountingInterceptor .INVOCATIONS .get ());
91+
92+ ScheduledBean .INTERCEPTED_COUNTER .set (0 );
93+ CountingInterceptor .INVOCATIONS .set (0 );
94+
95+ final CompletableFuture <Integer > future = scheduledBean .everySecondIntercepted (2 );
96+ final Integer result = future .get (15 , TimeUnit .SECONDS );
97+
98+ assertEquals ("Scheduled method should complete after 2 runs" , Integer .valueOf (2 ), result );
99+ assertEquals ("Business method should have been invoked twice" , 2 , ScheduledBean .INTERCEPTED_COUNTER .get ());
100+ assertEquals ("CDI interceptor should run for each scheduled firing" , 2 , CountingInterceptor .INVOCATIONS .get ());
101+ }
102+
76103 @ ApplicationScoped
77104 public static class ScheduledBean {
78105 static final AtomicInteger VOID_COUNTER = new AtomicInteger ();
79106 static final CountDownLatch VOID_LATCH = new CountDownLatch (3 );
80107
81108 static final AtomicInteger RETURNING_COUNTER = new AtomicInteger ();
82109 static final CountDownLatch RETURNING_LATCH = new CountDownLatch (1 );
110+ static final AtomicInteger INTERCEPTED_COUNTER = new AtomicInteger ();
83111
84112 @ Asynchronous (runAt = @ Schedule (cron = "* * * * * *" ))
85113 public void everySecondVoid () {
@@ -93,6 +121,43 @@ public CompletableFuture<String> everySecondReturning() {
93121 RETURNING_LATCH .countDown ();
94122 return Asynchronous .Result .complete ("done" );
95123 }
124+
125+ @ Counted
126+ public String directInterceptedCall () {
127+ return "ok" ;
128+ }
129+
130+ @ Counted
131+ @ Asynchronous (runAt = @ Schedule (cron = "* * * * * *" ))
132+ public CompletableFuture <Integer > everySecondIntercepted (final int runs ) {
133+ final int count = INTERCEPTED_COUNTER .incrementAndGet ();
134+ if (count < runs ) {
135+ return null ;
136+ }
137+
138+ final CompletableFuture <Integer > future = Asynchronous .Result .getFuture ();
139+ future .complete (count );
140+ return future ;
141+ }
142+ }
143+
144+ @ InterceptorBinding
145+ @ Target ({ElementType .TYPE , ElementType .METHOD })
146+ @ Retention (RetentionPolicy .RUNTIME )
147+ public @interface Counted {
148+ }
149+
150+ @ Interceptor
151+ @ Counted
152+ @ Priority (Interceptor .Priority .APPLICATION )
153+ public static class CountingInterceptor {
154+ static final AtomicInteger INVOCATIONS = new AtomicInteger ();
155+
156+ @ AroundInvoke
157+ public Object aroundInvoke (final InvocationContext context ) throws Exception {
158+ INVOCATIONS .incrementAndGet ();
159+ return context .proceed ();
160+ }
96161 }
97162
98163 @ jakarta .ejb .Singleton
0 commit comments