-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide utilities to properly use Vert.x duplicated context and Conte…
…xt locals.
- Loading branch information
1 parent
7d6bb5a
commit f877f83
Showing
6 changed files
with
530 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>io.smallrye.common</groupId> | ||
<artifactId>smallrye-common-parent</artifactId> | ||
<version>1.9.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>smallrye-common-vertx-context</artifactId> | ||
<name>SmallRye Common: Vert.x Context Utilities</name> | ||
<description>A set of utility classes to ease the usage of Vert.x context locals and duplicated contexts.</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.vertx</groupId> | ||
<artifactId>vertx-core</artifactId> | ||
<version>${version.vertx}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.smallrye.common</groupId> | ||
<artifactId>smallrye-common-constraint</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.vertx</groupId> | ||
<artifactId>vertx-junit5</artifactId> | ||
<version>${version.vertx}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.jboss.jandex</groupId> | ||
<artifactId>jandex-maven-plugin</artifactId> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<profiles> | ||
<profile> | ||
<id>coverage</id> | ||
<properties> | ||
<argLine>@{jacocoArgLine}</argLine> | ||
</properties> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.jacoco</groupId> | ||
<artifactId>jacoco-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>report</id> | ||
<phase>verify</phase> | ||
<goals> | ||
<goal>report</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |
85 changes: 85 additions & 0 deletions
85
vertx-context/src/main/java/io/smallrye/common/vertx/ContextLocals.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package io.smallrye.common.vertx; | ||
|
||
import java.util.Optional; | ||
|
||
import io.smallrye.common.constraint.Assert; | ||
import io.vertx.core.Context; | ||
import io.vertx.core.Vertx; | ||
|
||
/** | ||
* Utilities to access Vert.x Context locals. | ||
*/ | ||
public class ContextLocals { | ||
|
||
private ContextLocals() { | ||
// Avoid direct instantiation | ||
} | ||
|
||
private static Context ensureDuplicatedContext() { | ||
Context current = Vertx.currentContext(); | ||
if (current == null || !VertxContext.isDuplicatedContext(current)) { | ||
throw new UnsupportedOperationException("Access to Context Locals are forbidden from a 'root' context as " + | ||
"it can leak data between unrelated processing. Make sure the method runs on a 'duplicated' (local)" + | ||
" Context"); | ||
} | ||
return current; | ||
} | ||
|
||
/** | ||
* Gets the value from the context local associated with the given key. | ||
* | ||
* @param key the key, must not be {@code null} | ||
* @param <T> the expected type of the associated value | ||
* @return an optional containing the associated value if any, empty otherwise. | ||
*/ | ||
public static <T> Optional<T> get(String key) { | ||
Context current = ensureDuplicatedContext(); | ||
return Optional.ofNullable(current.getLocal(Assert.checkNotNullParam("key", key))); | ||
} | ||
|
||
/** | ||
* Gets the value from the context local associated with the given key. | ||
* If there is no associated value, it returns the given default. | ||
* | ||
* @param key the key, must not be {@code null} | ||
* @param def the default value returned if there is no associated value with the given key. | ||
* Can be {@code null} | ||
* @param <T> the expected type of the associated value | ||
* @return the associated value if any, the given default otherwise. | ||
*/ | ||
public static <T> T get(String key, T def) { | ||
Context current = ensureDuplicatedContext(); | ||
T local = current.getLocal(Assert.checkNotNullParam("key", key)); | ||
if (local == null) { | ||
return def; | ||
} | ||
return local; | ||
} | ||
|
||
/** | ||
* Stores the given key/value in the context local. | ||
* This method overwrite the existing value if any. | ||
* | ||
* @param key the key, must not be {@code null} | ||
* @param value the value, must not be {@code null} | ||
* @param <T> the expected type of the associated value | ||
*/ | ||
public static <T> void put(String key, T value) { | ||
Context current = ensureDuplicatedContext(); | ||
current.putLocal( | ||
Assert.checkNotNullParam("key", key), | ||
Assert.checkNotNullParam("value", value)); | ||
} | ||
|
||
/** | ||
* Removes the value associated with the given key from the context locals. | ||
* | ||
* @param key the key, must not be {@code null} | ||
* @return {@code true} if there were a value associated with the given key. {@code false} otherwise. | ||
*/ | ||
public static boolean remove(String key) { | ||
Context current = ensureDuplicatedContext(); | ||
return current.removeLocal(Assert.checkNotNullParam("key", key)); | ||
} | ||
|
||
} |
134 changes: 134 additions & 0 deletions
134
vertx-context/src/main/java/io/smallrye/common/vertx/VertxContext.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package io.smallrye.common.vertx; | ||
|
||
import io.smallrye.common.constraint.Assert; | ||
import io.smallrye.common.constraint.Nullable; | ||
import io.vertx.core.Context; | ||
import io.vertx.core.Vertx; | ||
import io.vertx.core.impl.ContextInternal; | ||
import io.vertx.core.impl.EventLoopContext; | ||
import io.vertx.core.impl.WorkerContext; | ||
|
||
/** | ||
* Utility classes allowing to create duplicated contexts. | ||
* <p> | ||
* The rationale for this class is to avoid end-users to use the Vert.x internal API, and avoids common mistakes when | ||
* dealing with Contexts and duplicated Contexts. | ||
*/ | ||
public class VertxContext { | ||
|
||
private VertxContext() { | ||
// Avoid direct instantiation | ||
} | ||
|
||
/** | ||
* Gets or creates a duplicated context. | ||
* If the given context is already a duplicated context, it returns this duplicated context. | ||
* Otherwise, it creates a new duplicated context, using the given context as <em>root</em> context. | ||
* | ||
* @param context the context, must not be {@code null} | ||
* @return the given context if it's a duplicated context, or a new duplicated context using the given one as | ||
* <em>root</em>. | ||
*/ | ||
public static Context getOrCreateDuplicatedContext(Context context) { | ||
if (isDuplicatedContext(context)) { // Also checks that the context is not null | ||
return context; | ||
} else { | ||
return ((ContextInternal) context).duplicate(); | ||
} | ||
} | ||
|
||
/** | ||
* Gets or creates a duplicated context. | ||
* <p> | ||
* If this method is called from a non-Vert.x thread (so, there is no current context), it creates a new (event loop) | ||
* context and a duplicated context (and returns the duplicated context). | ||
* <p> | ||
* If this method is called from a Vert.x thread (so, there is a current context), and if the current context is | ||
* already a duplicated context, it returns the current duplicated context. | ||
* <p> | ||
* It this method is called from a Vert.x thread (so, there is a current context), and if the current context is not | ||
* a duplicated context, it creates a new duplicated context, using the current context as <em>root</em> context. | ||
* | ||
* @param vertx the Vert.x instance to use to create the context if needed. Must not be {@code null} | ||
* @return the current context if it's a duplicated context, or a new duplicated context. | ||
* @see #getOrCreateDuplicatedContext(Context) | ||
*/ | ||
public static Context getOrCreateDuplicatedContext(Vertx vertx) { | ||
Vertx actual = Assert.checkNotNullParam("vertx", vertx); | ||
Context context = actual.getOrCreateContext(); // Creates an event loop context if none | ||
if (isDuplicatedContext(context)) { // Also checks that the context is not null | ||
return context; | ||
} else { | ||
return ((ContextInternal) context).duplicate(); | ||
} | ||
} | ||
|
||
/** | ||
* Gets or creates a duplicated context. | ||
* <p> | ||
* If the method is not called from a Vert.x thread, it returns {@code null}. | ||
* If the caller context is already a duplicated context, it returns this duplicated context. | ||
* Otherwise, it creates a new duplicated context, using current context as <em>root</em> context. | ||
* | ||
* @return the current context if it's a duplicated context, a new duplicated context using the given one | ||
* as <em>root</em>, {@code null} if not called from a Vert.x thread. | ||
* @see #getOrCreateDuplicatedContext(Context) | ||
*/ | ||
public static @Nullable Context getOrCreateDuplicatedContext() { | ||
Context context = Vertx.currentContext(); | ||
if (context == null) { | ||
return null; | ||
} | ||
return getOrCreateDuplicatedContext(context); | ||
} | ||
|
||
/** | ||
* Creates a new duplicated context, even if the current one is already a duplicated context. | ||
* If the method is not called from a Vert.x thread, it returns {@code null}. | ||
* | ||
* @return a new duplicated context if called from a Vert.x thread, {@code null} otherwise. | ||
*/ | ||
public static @Nullable Context createNewDuplicatedContext() { | ||
Context context = Vertx.currentContext(); | ||
if (context == null) { | ||
return null; | ||
} | ||
// This creates a duplicated context from the root context of the current duplicated context (if that's one) | ||
return ((ContextInternal) context).duplicate(); | ||
} | ||
|
||
/** | ||
* Checks if the given context is a duplicated context. | ||
* | ||
* @param context the context, must not be {@code null} | ||
* @return {@code true} if the given context is a duplicated context, {@code false} otherwise. | ||
*/ | ||
public static boolean isDuplicatedContext(Context context) { | ||
Context actual = Assert.checkNotNullParam("context", context); | ||
return !(actual instanceof EventLoopContext || actual instanceof WorkerContext); | ||
} | ||
|
||
/** | ||
* Checks if the current context is a duplicated context. | ||
* If the method is called from a Vert.x thread, it retrieves the current context and checks if it's a duplicated | ||
* context. Otherwise, it returns false. | ||
* | ||
* @return {@code true} if the method is called from a duplicated context, {@code false} otherwise. | ||
*/ | ||
public static boolean isOnDuplicatedContext() { | ||
Context context = Vertx.currentContext(); | ||
return context != null && isDuplicatedContext(context); | ||
} | ||
|
||
/** | ||
* Returns the parent context from a given Vert.x context. | ||
* <p> | ||
* A duplicate context returns the wrapped context otherwise the given context is returned. | ||
* | ||
* @param context the context, must not be {@code null} | ||
* @return the <em>root</em> context if the given context is a duplicated context, returns the given context otherwise. | ||
*/ | ||
public static Context getRootContext(Context context) { | ||
return isDuplicatedContext(context) ? ((ContextInternal) context).unwrap() : context; | ||
} | ||
} |
Oops, something went wrong.