5
5
*/
6
6
package org .hibernate .reactive ;
7
7
8
- import java .util .concurrent .CompletionException ;
8
+ import java .util .concurrent .CompletableFuture ;
9
9
import javax .persistence .Entity ;
10
10
import javax .persistence .Id ;
11
11
12
12
import org .hibernate .cfg .Configuration ;
13
13
import org .hibernate .reactive .mutiny .Mutiny ;
14
14
import org .hibernate .reactive .stage .Stage ;
15
+ import org .hibernate .reactive .testing .DatabaseSelectionRule ;
15
16
17
+ import org .junit .Rule ;
16
18
import org .junit .Test ;
17
19
18
20
import io .smallrye .mutiny .Uni ;
19
21
import io .vertx .core .Context ;
20
22
import io .vertx .core .Vertx ;
23
+ import io .vertx .ext .unit .Async ;
21
24
import io .vertx .ext .unit .TestContext ;
22
25
import org .assertj .core .api .Assertions ;
23
26
27
+ import static org .hibernate .reactive .containers .DatabaseConfiguration .DBType .POSTGRESQL ;
28
+ import static org .hibernate .reactive .testing .DatabaseSelectionRule .runOnlyFor ;
29
+
24
30
/**
25
31
* It's currently considered an error to share a Session between multiple reactive streams,
26
32
* so we should detect that condition and throw an exception.
33
+ * <p>
34
+ * WARNING: Because we are running the code to test inside a function, we must create the {@link Async}
35
+ * in advance. Otherwise the test will end successfully because the async has not been created yet.
36
+ * </p>
27
37
*/
28
38
public class MultipleContextTest extends BaseReactiveTest {
29
39
30
40
private static final String ERROR_MESSAGE = "Detected use of the reactive Session from a different Thread" ;
31
41
42
+ // These tests will fail before touching the database, so there is no reason
43
+ // to run them on all databases
44
+ @ Rule
45
+ public DatabaseSelectionRule rule = runOnlyFor ( POSTGRESQL );
46
+
32
47
@ Override
33
48
protected Configuration constructConfiguration () {
34
49
Configuration configuration = super .constructConfiguration ();
@@ -37,100 +52,93 @@ protected Configuration constructConfiguration() {
37
52
}
38
53
39
54
@ Test
40
- public void testPersistWithStage (TestContext testContext ) throws Exception {
55
+ public void testPersistWithStage (TestContext testContext ) {
56
+ Async async = testContext .async ();
41
57
Stage .Session session = openSession ();
42
58
Context testVertxContext = Vertx .currentContext ();
43
59
44
60
// Create a different new context
45
- Vertx vertx = Vertx .vertx ();
46
- Context newContext = vertx .getOrCreateContext ();
61
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
47
62
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
48
63
49
64
// Run test in the new context
50
- newContext .runOnContext ( event ->
51
- test ( testContext , session
52
- .persist ( new Competition ( "Cheese Rolling" ) )
53
- .handle ( (v , e ) -> {
54
- testContext .assertNotNull ( e );
55
- testContext .assertEquals ( CompletionException .class , e .getClass () );
56
- testContext .assertEquals ( IllegalStateException .class , e .getCause ().getClass () );
57
- testContext .assertTrue ( e .getMessage ().contains ( ERROR_MESSAGE ) );
58
- return null ;
59
- } ) )
65
+ newContext .runOnContext ( event -> test ( async , testContext , session
66
+ .persist ( new Competition ( "Cheese Rolling" ) )
67
+ .thenCompose ( v -> session .flush () )
68
+ .handle ( (v , e ) -> assertExceptionThrown ( e ).join () ) )
60
69
);
61
70
}
62
71
63
-
64
72
@ Test
65
- public void testFindWithStage (TestContext testContext ) throws Exception {
73
+ public void testFindWithStage (TestContext testContext ) {
74
+ Async async = testContext .async ();
66
75
Stage .Session session = openSession ();
67
76
Context testVertxContext = Vertx .currentContext ();
68
77
69
78
// Create a different new context
70
- Vertx vertx = Vertx .vertx ();
71
- Context newContext = vertx .getOrCreateContext ();
79
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
72
80
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
73
81
74
82
// Run test in the new context
75
- newContext .runOnContext ( event ->
76
- test ( testContext , session
77
- .find ( Competition .class , "Chess boxing" )
78
- .handle ( (v , e ) -> {
79
- testContext .assertNotNull ( e );
80
- testContext .assertEquals ( CompletionException .class , e .getClass () );
81
- testContext .assertEquals ( IllegalStateException .class , e .getCause ().getClass () );
82
- testContext .assertTrue ( e .getMessage ().contains ( ERROR_MESSAGE ) );
83
- return null ;
84
- } ) )
83
+ newContext .runOnContext ( event -> test ( async , testContext , session
84
+ .find ( Competition .class , "Chess boxing" )
85
+ .handle ( (v , e ) -> assertExceptionThrown ( e ).join () ) )
85
86
);
86
87
}
87
88
88
89
@ Test
89
- public void testOnPersistWithMutiny (TestContext testContext ) throws Exception {
90
+ public void testOnPersistWithMutiny (TestContext testContext ) {
91
+ Async async = testContext .async ();
90
92
Mutiny .Session session = openMutinySession ();
91
93
Context testVertxContext = Vertx .currentContext ();
92
94
93
95
// Create a different new context
94
- Vertx vertx = Vertx .vertx ();
95
- Context newContext = vertx .getOrCreateContext ();
96
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
96
97
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
97
98
98
99
// Run test in the new context
99
- newContext .runOnContext ( event ->
100
- test ( testContext , session
101
- .persist ( new Competition ( "Cheese Rolling" ) )
102
- .onItem ().invoke ( v -> testContext .fail ( "We were expecting an exception" ) )
103
- .onFailure ().recoverWithUni ( e -> {
104
- testContext .assertEquals ( IllegalStateException .class , e .getClass () );
105
- testContext .assertTrue ( e .getMessage ().contains ( ERROR_MESSAGE ) );
106
- return Uni .createFrom ().voidItem ();
107
- } ) )
100
+ newContext .runOnContext ( event -> test ( async , testContext , session
101
+ .persist ( new Competition ( "Cheese Rolling" ) )
102
+ .call ( session ::flush )
103
+ .onItemOrFailure ()
104
+ .transformToUni ( (unused , e ) -> Uni .createFrom ().completionStage ( assertExceptionThrown ( e ) ) ) )
108
105
);
109
106
}
110
107
111
108
@ Test
112
- public void testFindWithMutiny (TestContext testContext ) throws Exception {
109
+ public void testFindWithMutiny (TestContext testContext ) {
110
+ Async async = testContext .async ();
113
111
Mutiny .Session session = openMutinySession ();
114
112
Context testVertxContext = Vertx .currentContext ();
115
113
116
114
// Create a different new context
117
- Vertx vertx = Vertx .vertx ();
118
- Context newContext = vertx .getOrCreateContext ();
115
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
119
116
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
120
117
121
118
// Run test in the new context
122
- newContext .runOnContext (event ->
123
- test ( testContext , session
124
- .find ( Competition .class , "Chess boxing" )
125
- .onItem ().invoke ( v -> testContext .fail ( "We were expecting an exception" ) )
126
- .onFailure ().recoverWithUni ( e -> {
127
- testContext .assertEquals ( IllegalStateException .class , e .getClass () );
128
- testContext .assertTrue ( e .getMessage ().contains ( ERROR_MESSAGE ) );
129
- return Uni .createFrom ().nullItem ();
130
- } ) )
119
+ newContext .runOnContext ( event -> test ( async , testContext , session
120
+ .find ( Competition .class , "Chess boxing" )
121
+ .onItemOrFailure ()
122
+ .transformToUni ( (unused , e ) -> Uni .createFrom ().completionStage ( assertExceptionThrown ( e ) ) ) )
131
123
);
132
124
}
133
125
126
+ // Check that at least one exception has the expected message
127
+ private static CompletableFuture <Void > assertExceptionThrown (Throwable e ) {
128
+ CompletableFuture <Void > result = new CompletableFuture <>();
129
+ Throwable t = e ;
130
+ while ( t != null ) {
131
+ if ( t .getClass ().equals ( IllegalStateException .class )
132
+ && t .getMessage ().contains ( ERROR_MESSAGE ) ) {
133
+ result .complete ( null );
134
+ return result ;
135
+ }
136
+ t = t .getCause ();
137
+ }
138
+ result .completeExceptionally ( new AssertionError ( "Expected exception not thrown. Exception thrown: " + e ) );
139
+ return result ;
140
+ }
141
+
134
142
@ Entity
135
143
static class Competition {
136
144
@ Id
0 commit comments