25
25
import java .util .stream .Stream ;
26
26
27
27
/**
28
- * The propagation across different threads using the context which is immutable and can be extended/reduced by different elements.
29
- * Each element can be a simple data structure carrying its state across the threads, or it can implement {@link ThreadPropagatedContextElement}
30
- * for use-cases when thread-local values needs to be updated.
28
+ * A mechanism for propagating state across threads that's easier to use and safer than
29
+ * {@link ThreadLocal}.
30
+ *
31
+ * <p>
32
+ * A propagated context is an immutable list of objects. {@link #plus(PropagatedContextElement)
33
+ * Adding} or {@link #minus(PropagatedContextElement) deleting} elements from a context creates a
34
+ * new context that must then be explicitly brought into scope by {@link #propagate() propagating
35
+ * it}.
36
+ *
37
+ * <p>
38
+ * If an element wraps an existing thread local variable then it can implement {@link
39
+ * ThreadPropagatedContextElement} to take part in the enter-exit process.
40
+ *
41
+ * <p>
42
+ * In standard usage you would call {@link #getOrEmpty()}, then {@link
43
+ * #plus(PropagatedContextElement)} to add some data, then {@link #propagate(Supplier)} to execute a
44
+ * lambda with the context in scope.
31
45
*
32
46
* @author Denis Stepanov
33
47
* @since 4.0.0
@@ -76,7 +90,9 @@ static Optional<PropagatedContext> find() {
76
90
}
77
91
78
92
/**
79
- * Wrap runnable for this context to be propagated in.
93
+ * Captures the current context and returns a new {@link Runnable} that, when executed, will run
94
+ * the given runnable with the captured context in scope. If no context is in scope then the
95
+ * given callable is returned as-is.
80
96
*
81
97
* @param runnable The runnable
82
98
* @return new runnable or existing if the context is missing
@@ -87,7 +103,9 @@ static Runnable wrapCurrent(@NonNull Runnable runnable) {
87
103
}
88
104
89
105
/**
90
- * Wrap callable for this context to be propagated in.
106
+ * Captures the current context and returns a new {@link Callable} that, when executed, will run
107
+ * the given callable with the captured context in scope. If no context is in scope then the
108
+ * given callable is returned as-is.
91
109
*
92
110
* @param callable The callable
93
111
* @param <V> The callable type
@@ -99,7 +117,9 @@ static <V> Callable<V> wrapCurrent(@NonNull Callable<V> callable) {
99
117
}
100
118
101
119
/**
102
- * Wrap supplier for this context to be propagated in.
120
+ * Captures the current context and returns a new {@link Supplier} that, when executed, will run
121
+ * the given supplier with the captured context in scope. If no context is in scope then the
122
+ * given callable is returned as-is.
103
123
*
104
124
* @param supplier The supplier
105
125
* @param <V> The supplier type
@@ -111,61 +131,60 @@ static <V> Supplier<V> wrapCurrent(@NonNull Supplier<V> supplier) {
111
131
}
112
132
113
133
/**
114
- * Check if there is a context associated .
134
+ * Check if there is a context in scope .
115
135
*
116
- * @return true if the context exists
136
+ * @return true if a context has been {@link #propagate() propagated}.
117
137
*/
118
138
static boolean exists () {
119
139
return PropagatedContextImpl .exists ();
120
140
}
121
141
122
142
/**
123
- * Creates a new element with added element.
124
- * <p>
125
- * NOTE: The new element needs to be propagated .
143
+ * Returns a new context extended with the given element. This doesn't add anything
144
+ * to the existing in-scope context (if any), so you will need to propagate it
145
+ * yourself. You can add multiple elements of the same type .
126
146
*
127
- * @param element The element element to be added
128
- * @return new element
147
+ * @param element the element to be added
148
+ * @return the new context
129
149
*/
130
150
@ NonNull
131
151
PropagatedContext plus (@ NonNull PropagatedContextElement element );
132
152
133
153
/**
134
- * Creates a new context without the provided element.
135
- * <p>
136
- * NOTE: The new context needs to be propagated .
154
+ * Returns a new context without the provided element. This doesn't remove anything
155
+ * from the existing in-scope context (if any), so you will need to propagate it
156
+ * yourself. Elements are compared using {@link Object#equals(Object)} .
137
157
*
138
158
* @param element The context element to be removed
139
- * @return new context
159
+ * @return the new context
140
160
*/
141
161
@ NonNull
142
162
PropagatedContext minus (@ NonNull PropagatedContextElement element );
143
163
144
164
/**
145
- * Creates a new context with replaced the provided element.
146
- * <p>
147
- * NOTE: The new context needs to be propagated .
165
+ * Creates a new context with the given element replaced. This doesn't change anything
166
+ * in the existing in-scope context (if any), so you will need to propagate it
167
+ * yourself. Elements are compared using {@link Object#equals(Object)} .
148
168
*
149
- * @param oldElement The context element to be replaced
150
- * @param newElement The context element to be replaced with
151
- * @return new context
169
+ * @param oldElement the element to be replaced
170
+ * @param newElement the element that will replace it
171
+ * @return the new context
152
172
*/
153
173
@ NonNull
154
174
PropagatedContext replace (@ NonNull PropagatedContextElement oldElement ,
155
175
@ NonNull PropagatedContextElement newElement );
156
176
157
177
/**
158
- * Finds optional element of type.
159
- * In a case of multiple element of the same type the last one will be returned.
178
+ * Finds the first element of the given type, if any exist.
160
179
*
161
180
* @param elementType The element type
162
181
* @param <T> The element's type
163
- * @return optional element
182
+ * @return element if found
164
183
*/
165
184
<T extends PropagatedContextElement > Optional <T > find (@ NonNull Class <T > elementType );
166
185
167
186
/**
168
- * Find all elements of type. The first element processed by stream will be the last one added.
187
+ * Find all elements of the given type. The first element in the stream will be the last element added.
169
188
*
170
189
* @param elementType The element type
171
190
* @param <T> The element's type
@@ -174,11 +193,12 @@ PropagatedContext replace(@NonNull PropagatedContextElement oldElement,
174
193
<T extends PropagatedContextElement > Stream <T > findAll (@ NonNull Class <T > elementType );
175
194
176
195
/**
177
- * Gets element of type.
196
+ * Gets the first element of the given type.
178
197
*
179
198
* @param elementType The element type
180
199
* @param <T> The element's type
181
- * @return an element or exception
200
+ * @return an element
201
+ * @throws java.util.NoSuchElementException if no elements of that type are in the context.
182
202
*/
183
203
<T extends PropagatedContextElement > T get (@ NonNull Class <T > elementType );
184
204
@@ -190,17 +210,18 @@ PropagatedContext replace(@NonNull PropagatedContextElement oldElement,
190
210
List <PropagatedContextElement > getAllElements ();
191
211
192
212
/**
193
- * Propagate the context using try-resource block.
213
+ * Brings this context into scope, temporarily replacing the previous context (if any). The returned
214
+ * object must be closed to undo the propagation.
194
215
*
195
216
* @return auto-closeable block to be used in try-resource block.
196
217
*/
197
218
@ NonNull
198
219
Scope propagate ();
199
220
200
221
/**
201
- * Wrap runnable for this context to be propagated in .
222
+ * Returns a new runnable that runs the given runnable with this context in scope .
202
223
*
203
- * @param runnable The runnable
224
+ * @param runnable The runnable that will execute with this context in scope.
204
225
* @return new runnable
205
226
*/
206
227
@ NonNull
@@ -214,7 +235,7 @@ default Runnable wrap(@NonNull Runnable runnable) {
214
235
}
215
236
216
237
/**
217
- * Wrap callable for this context to be propagated in .
238
+ * Returns a new callable that runs the given callable with this context in scope .
218
239
*
219
240
* @param callable The callable
220
241
* @param <V> The callable return type
@@ -231,7 +252,7 @@ default <V> Callable<V> wrap(@NonNull Callable<V> callable) {
231
252
}
232
253
233
254
/**
234
- * Wrap supplier for this context to be propagated in .
255
+ * Returns a new supplier that runs the given supplier with this context in scope .
235
256
*
236
257
* @param supplier The supplier
237
258
* @param <V> The supplier return type
@@ -248,22 +269,22 @@ default <V> Supplier<V> wrap(@NonNull Supplier<V> supplier) {
248
269
}
249
270
250
271
/**
251
- * Propagate the context for the supplier .
272
+ * Executes the given supplier with this context in scope, restoring the previous context when execution completes .
252
273
*
253
274
* @param supplier The supplier
254
275
* @param <V> The supplier return type
255
- * @return new supplier
276
+ * @return the result of calling {@link Supplier#get()}.
256
277
*/
257
278
@ NonNull
258
279
default <V > V propagate (@ NonNull Supplier <V > supplier ) {
259
- PropagatedContext propagatedContext = this ;
260
- try (Scope ignore = propagatedContext .propagate ()) {
280
+ try (Scope ignore = propagate ()) {
261
281
return supplier .get ();
262
282
}
263
283
}
264
284
265
285
/**
266
- * Context propagation {@link AutoCloseable} to be used in try-resource block.
286
+ * Closing this object undoes the effect of calling {@link #propagate()} on a context. Intended to be used in a
287
+ * try-with-resources block.
267
288
*
268
289
* @author Denis Stepanov
269
290
* @since 4.0.0
@@ -272,5 +293,4 @@ interface Scope extends AutoCloseable {
272
293
@ Override
273
294
void close ();
274
295
}
275
-
276
296
}
0 commit comments