1
1
package io .quarkus .hibernate .reactive .panache .common .runtime ;
2
2
3
- import java .util .function .Function ;
4
- import java .util .function .Supplier ;
5
-
6
3
import org .hibernate .reactive .common .spi .Implementor ;
7
4
import org .hibernate .reactive .context .Context .Key ;
8
5
import org .hibernate .reactive .context .impl .BaseKey ;
6
+ import org .hibernate .reactive .context .impl .ContextualDataStorage ;
9
7
import org .hibernate .reactive .mutiny .Mutiny ;
10
8
import org .hibernate .reactive .mutiny .Mutiny .Session ;
11
- import org .hibernate .reactive .mutiny .Mutiny .SessionFactory ;
12
9
import org .hibernate .reactive .mutiny .Mutiny .Transaction ;
13
10
14
11
import io .quarkus .arc .Arc ;
15
12
import io .quarkus .arc .ClientProxy ;
16
13
import io .quarkus .arc .impl .LazyValue ;
17
14
import io .quarkus .vertx .core .runtime .context .VertxContextSafetyToggle ;
18
15
import io .smallrye .mutiny .Uni ;
19
- import io .vertx .core .Context ;
20
- import io .vertx .core .Vertx ;
16
+ import io .vertx .core .impl .ContextInternal ;
17
+ import io .vertx .core .spi .context .storage .AccessMode ;
18
+ import java .util .Map ;
19
+ import java .util .concurrent .ConcurrentHashMap ;
20
+ import java .util .function .Function ;
21
+ import java .util .function .Supplier ;
21
22
22
23
/**
23
24
* Static util methods for {@link Mutiny.Session}.
@@ -26,32 +27,23 @@ public final class SessionOperations {
26
27
27
28
private static final String ERROR_MSG = "Hibernate Reactive Panache requires a safe (isolated) Vert.x sub-context, but the current context hasn't been flagged as such." ;
28
29
29
- private static final LazyValue <Mutiny .SessionFactory > SESSION_FACTORY = new LazyValue <>(
30
- new Supplier <Mutiny .SessionFactory >() {
31
- @ Override
32
- public SessionFactory get () {
33
- // Note that Mutiny.SessionFactory is @ApplicationScoped bean - it's safe to use the cached client proxy
34
- Mutiny .SessionFactory sessionFactory = Arc .container ().instance (Mutiny .SessionFactory .class ).get ();
35
- if (sessionFactory == null ) {
36
- throw new IllegalStateException ("Mutiny.SessionFactory bean not found" );
37
- }
38
- return sessionFactory ;
39
- }
40
- });
41
-
42
- private static final LazyValue <Key <Mutiny .Session >> SESSION_KEY = new LazyValue <>(
43
- new Supplier <Key <Mutiny .Session >>() {
30
+ private static final LazyValue <Mutiny .SessionFactory > SESSION_FACTORY = new LazyValue <>(() -> {
31
+ // Note that Mutiny.SessionFactory is @ApplicationScoped bean - it's safe to use the cached client proxy
32
+ Mutiny .SessionFactory sessionFactory = Arc .container ().instance (Mutiny .SessionFactory .class ).get ();
33
+ if (sessionFactory == null ) {
34
+ throw new IllegalStateException ("Mutiny.SessionFactory bean not found" );
35
+ }
36
+ return sessionFactory ;
37
+ });
44
38
45
- @ Override
46
- public Key <Session > get () {
47
- Implementor implementor = (Implementor ) ClientProxy .unwrap (SESSION_FACTORY .get ());
48
- return new BaseKey <>(Mutiny .Session .class , implementor .getUuid ());
49
- }
50
- });
39
+ private static final LazyValue <Key <Mutiny .Session >> SESSION_KEY = new LazyValue <>(() -> {
40
+ Implementor implementor = (Implementor ) ClientProxy .unwrap (SESSION_FACTORY .get ());
41
+ return new BaseKey <>(Mutiny .Session .class , implementor .getUuid ());
42
+ });
51
43
52
44
// This key is used to indicate that a reactive session should be opened lazily (when needed) in the current vertx context
53
- private static final String SESSION_ON_DEMAND_KEY = "hibernate.reactive.panache.sessionOnDemand" ;
54
- private static final String SESSION_ON_DEMAND_OPENED_KEY = "hibernate.reactive.panache.sessionOnDemandOpened" ;
45
+ private static final Key < Boolean > SESSION_ON_DEMAND_KEY = new BaseKey <>( Boolean . class , "hibernate.reactive.panache.sessionOnDemand" ) ;
46
+ private static final Key < Boolean > SESSION_ON_DEMAND_OPENED_KEY = new BaseKey <>( Boolean . class , "hibernate.reactive.panache.sessionOnDemandOpened" ) ;
55
47
56
48
/**
57
49
* Marks the current vertx duplicated context as "lazy" which indicates that a reactive session should be opened lazily if
@@ -63,17 +55,17 @@ public Key<Session> get() {
63
55
* @see #getSession()
64
56
*/
65
57
static <T > Uni <T > withSessionOnDemand (Supplier <Uni <T >> work ) {
66
- Context context = vertxContext ();
67
- if (context . getLocal (SESSION_ON_DEMAND_KEY ) != null ) {
58
+ Map < Key < Boolean >, Boolean > contextualDataMap = contextualDataMap ( vertxContext () );
59
+ if (contextualDataMap . get (SESSION_ON_DEMAND_KEY ) != null ) {
68
60
// context already marked - no need to set the key and close the session
69
61
return work .get ();
70
62
} else {
71
63
// mark the lazy session
72
- context . putLocal (SESSION_ON_DEMAND_KEY , true );
64
+ contextualDataMap . put (SESSION_ON_DEMAND_KEY , Boolean . TRUE );
73
65
// perform the work and eventually close the session and remove the key
74
66
return work .get ().eventually (() -> {
75
- context . removeLocal (SESSION_ON_DEMAND_KEY );
76
- context . removeLocal (SESSION_ON_DEMAND_OPENED_KEY );
67
+ contextualDataMap . remove (SESSION_ON_DEMAND_KEY );
68
+ contextualDataMap . remove (SESSION_ON_DEMAND_OPENED_KEY );
77
69
return closeSession ();
78
70
});
79
71
}
@@ -109,17 +101,17 @@ public static <T> Uni<T> withTransaction(Function<Transaction, Uni<T>> work) {
109
101
* @return a new {@link Uni}
110
102
*/
111
103
public static <T > Uni <T > withSession (Function <Mutiny .Session , Uni <T >> work ) {
112
- Context context = vertxContext ();
104
+ Map < Key < Session >, Session > contextualDataMap = SessionOperations .< Session > contextualDataMap ( vertxContext () );
113
105
Key <Mutiny .Session > key = getSessionKey ();
114
- Mutiny .Session current = context . getLocal (key );
106
+ Mutiny .Session current = contextualDataMap . get (key );
115
107
if (current != null && current .isOpen ()) {
116
108
// reactive session exists - reuse this session
117
109
return work .apply (current );
118
110
} else {
119
111
// reactive session does not exist - open a new one and close it when the returned Uni completes
120
112
return getSessionFactory ()
121
113
.openSession ()
122
- .invoke (s -> context . putLocal (key , s ))
114
+ .invoke (s -> contextualDataMap . put (key , s ))
123
115
.chain (work ::apply )
124
116
.eventually (SessionOperations ::closeSession );
125
117
}
@@ -140,22 +132,24 @@ public static <T> Uni<T> withSession(Function<Mutiny.Session, Uni<T>> work) {
140
132
* @return the {@link Mutiny.Session}
141
133
*/
142
134
public static Uni <Mutiny .Session > getSession () {
143
- Context context = vertxContext ();
135
+ ContextInternal context = vertxContext ();
144
136
Key <Mutiny .Session > key = getSessionKey ();
145
- Mutiny .Session current = context .getLocal (key );
137
+ final Mutiny .Session current = SessionOperations .<Session > contextualDataMap (context ).get (key );
138
+ final Map <Key <Boolean >, Boolean > objectsDataMap = contextualDataMap (context );
146
139
if (current != null && current .isOpen ()) {
147
140
// reuse the existing reactive session
148
141
return Uni .createFrom ().item (current );
149
142
} else {
150
- if (context . getLocal (SESSION_ON_DEMAND_KEY ) != null ) {
151
- if (context . getLocal (SESSION_ON_DEMAND_OPENED_KEY ) != null ) {
143
+ if (objectsDataMap . get (SESSION_ON_DEMAND_KEY ) != null ) {
144
+ if (objectsDataMap . get (SESSION_ON_DEMAND_OPENED_KEY ) != null ) {
152
145
// a new reactive session is opened in a previous stage
153
146
return Uni .createFrom ().item (SessionOperations ::getCurrentSession );
154
147
} else {
155
148
// open a new reactive session and store it in the vertx duplicated context
156
149
// the context was marked as "lazy" which means that the session will be eventually closed
157
- context .putLocal (SESSION_ON_DEMAND_OPENED_KEY , true );
158
- return getSessionFactory ().openSession ().invoke (s -> context .putLocal (key , s ));
150
+ objectsDataMap .put (SESSION_ON_DEMAND_OPENED_KEY , Boolean .TRUE );
151
+ return getSessionFactory ().openSession ().invoke (s -> SessionOperations
152
+ .<Session > contextualDataMap (context ).put (key , s ));
159
153
}
160
154
} else {
161
155
throw new IllegalStateException ("No current Mutiny.Session found"
@@ -170,23 +164,31 @@ public static Uni<Mutiny.Session> getSession() {
170
164
* @return the current reactive session stored in the context, or {@code null} if no session exists
171
165
*/
172
166
public static Mutiny .Session getCurrentSession () {
173
- Context context = vertxContext ();
174
- Mutiny .Session current = context .getLocal (getSessionKey ());
167
+ Mutiny .Session current = SessionOperations .<Session > contextualDataMap (vertxContext ()).get (getSessionKey ());
175
168
if (current != null && current .isOpen ()) {
176
169
return current ;
177
170
}
178
171
return null ;
179
172
}
180
173
174
+ @ SuppressWarnings ({ "unchecked" })
175
+ private static <T > Map <Key <T >, T > contextualDataMap (ContextInternal vertxContext ) {
176
+ return vertxContext .getLocal (
177
+ ContextualDataStorage .CONTEXTUAL_DATA_KEY ,
178
+ AccessMode .CONCURRENT ,
179
+ ConcurrentHashMap ::new );
180
+ }
181
+
181
182
/**
182
183
*
183
184
* @return the current vertx duplicated context
184
185
* @throws IllegalStateException If no vertx context is found or is not a safe context as mandated by the
185
186
* {@link VertxContextSafetyToggle}
186
187
*/
187
- private static Context vertxContext () {
188
- Context context = Vertx . currentContext ();
188
+ private static ContextInternal vertxContext () {
189
+ ContextInternal context = ContextInternal . current ();
189
190
if (context != null ) {
191
+ // TODO: Update check for ContextItnernal
190
192
VertxContextSafetyToggle .validateContextIfExists (ERROR_MSG , ERROR_MSG );
191
193
return context ;
192
194
} else {
@@ -195,11 +197,11 @@ private static Context vertxContext() {
195
197
}
196
198
197
199
static Uni <Void > closeSession () {
198
- Context context = vertxContext ();
199
200
Key <Mutiny .Session > key = getSessionKey ();
200
- Mutiny .Session current = context .getLocal (key );
201
+ Map <Key <Session >, Session > contextualDataMap = contextualDataMap (vertxContext ());
202
+ Mutiny .Session current = contextualDataMap .get (key );
201
203
if (current != null && current .isOpen ()) {
202
- return current .close ().eventually (() -> context . removeLocal (key ));
204
+ return current .close ().eventually (() -> contextualDataMap . remove (key ));
203
205
}
204
206
return Uni .createFrom ().voidItem ();
205
207
}
0 commit comments