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,92 @@ 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
+ .withTransaction ( transaction -> session .persist ( new Competition ( "Cheese Rolling" ) )
67
+ .handle ( (v , e ) -> assertExceptionThrown ( e ).join () ) ) )
60
68
);
61
69
}
62
70
63
-
64
71
@ Test
65
- public void testFindWithStage (TestContext testContext ) throws Exception {
72
+ public void testFindWithStage (TestContext testContext ) {
73
+ Async async = testContext .async ();
66
74
Stage .Session session = openSession ();
67
75
Context testVertxContext = Vertx .currentContext ();
68
76
69
77
// Create a different new context
70
- Vertx vertx = Vertx .vertx ();
71
- Context newContext = vertx .getOrCreateContext ();
78
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
72
79
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
73
80
74
81
// 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
- } ) )
82
+ newContext .runOnContext ( event -> test ( async , testContext , session
83
+ .find ( Competition .class , "Chess boxing" )
84
+ .handle ( (v , e ) -> assertExceptionThrown ( e ).join () ) )
85
85
);
86
86
}
87
87
88
88
@ Test
89
- public void testOnPersistWithMutiny (TestContext testContext ) throws Exception {
89
+ public void testOnPersistWithMutiny (TestContext testContext ) {
90
+ Async async = testContext .async ();
90
91
Mutiny .Session session = openMutinySession ();
91
92
Context testVertxContext = Vertx .currentContext ();
92
93
93
94
// Create a different new context
94
- Vertx vertx = Vertx .vertx ();
95
- Context newContext = vertx .getOrCreateContext ();
95
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
96
96
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
97
97
98
98
// 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
- } ) )
99
+ newContext .runOnContext ( event -> test ( async , testContext , session
100
+ .persist ( new Competition ( "Cheese Rolling" ) )
101
+ .call ( session ::flush )
102
+ .onItemOrFailure ()
103
+ .transformToUni ( (unused , e ) -> Uni .createFrom ().completionStage ( assertExceptionThrown ( e ) ) ) )
108
104
);
109
105
}
110
106
111
107
@ Test
112
- public void testFindWithMutiny (TestContext testContext ) throws Exception {
108
+ public void testFindWithMutiny (TestContext testContext ) {
109
+ Async async = testContext .async ();
113
110
Mutiny .Session session = openMutinySession ();
114
111
Context testVertxContext = Vertx .currentContext ();
115
112
116
113
// Create a different new context
117
- Vertx vertx = Vertx .vertx ();
118
- Context newContext = vertx .getOrCreateContext ();
114
+ Context newContext = Vertx .vertx ().getOrCreateContext ();
119
115
Assertions .assertThat ( testVertxContext ).isNotEqualTo ( newContext );
120
116
121
117
// 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
- } ) )
118
+ newContext .runOnContext ( event -> test ( async , testContext , session
119
+ .find ( Competition .class , "Chess boxing" )
120
+ .onItemOrFailure ()
121
+ .transformToUni ( (unused , e ) -> Uni .createFrom ().completionStage ( assertExceptionThrown ( e ) ) ) )
131
122
);
132
123
}
133
124
125
+ // Check that at least one exception has the expected message
126
+ private static CompletableFuture <Void > assertExceptionThrown (Throwable e ) {
127
+ CompletableFuture <Void > result = new CompletableFuture <>();
128
+ Throwable t = e ;
129
+ while ( t != null ) {
130
+ if ( t .getClass ().equals ( IllegalStateException .class )
131
+ && t .getMessage ().contains ( ERROR_MESSAGE ) ) {
132
+ result .complete ( null );
133
+ return result ;
134
+ }
135
+ t = t .getCause ();
136
+ }
137
+ result .completeExceptionally ( new AssertionError ( "Expected exception not thrown. Exception thrown: " + e ) );
138
+ return result ;
139
+ }
140
+
134
141
@ Entity
135
142
static class Competition {
136
143
@ Id
0 commit comments