18
18
import static org .assertj .core .api .Assertions .*;
19
19
20
20
import java .util .Collection ;
21
+ import java .util .List ;
22
+ import java .util .concurrent .CopyOnWriteArrayList ;
23
+ import java .util .concurrent .CountDownLatch ;
21
24
22
25
import org .junit .jupiter .api .Test ;
23
26
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
33
36
34
37
/**
35
38
* @author Christoph Strobl
39
+ * @author Myeonghyeon Lee
36
40
*/
37
41
class EntityCallbackDiscovererUnitTests {
38
42
@@ -49,6 +53,40 @@ void shouldDiscoverCallbackType() {
49
53
assertThat (entityCallbacks ).hasSize (1 ).element (0 ).isInstanceOf (MyBeforeSaveCallback .class );
50
54
}
51
55
56
+ @ Test // DATACMNS-1735
57
+ void shouldDiscoverCallbackTypeConcurrencyCache () throws InterruptedException {
58
+
59
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext (MyConfig .class );
60
+
61
+ EntityCallbackDiscoverer discoverer = new EntityCallbackDiscoverer (ctx );
62
+
63
+ int concurrencyCount = 4000 ;
64
+ CountDownLatch startLatch = new CountDownLatch (concurrencyCount );
65
+ CountDownLatch doneLatch = new CountDownLatch (concurrencyCount );
66
+
67
+ List <Exception > exceptions = new CopyOnWriteArrayList <>();
68
+ for (int i = 0 ; i < concurrencyCount ; i ++) {
69
+ Thread thread = new Thread (() -> {
70
+ try {
71
+ startLatch .countDown ();
72
+ startLatch .await ();
73
+
74
+ discoverer .getEntityCallbacks (PersonDocument .class ,
75
+ ResolvableType .forType (BeforeSaveCallback .class ));
76
+ } catch (Exception ex ) {
77
+ exceptions .add (ex );
78
+ } finally {
79
+ doneLatch .countDown ();
80
+ }
81
+ });
82
+ thread .start ();
83
+ }
84
+
85
+ doneLatch .await ();
86
+
87
+ assertThat (exceptions ).isEmpty ();
88
+ }
89
+
52
90
@ Test // DATACMNS-1467
53
91
void shouldDiscoverCallbackTypeByName () {
54
92
0 commit comments