From d255b1a8570f27ca7bac3c8676f1c4a98dfc5d0c Mon Sep 17 00:00:00 2001 From: Tihomir Krasimirov Mateev Date: Fri, 11 Oct 2024 19:15:29 +0300 Subject: [PATCH] ClassNotFoundException: com.fasterxml.jackson.core.JsonProcessingException (2993) (#2997) * Load the Jackson-based implementation dynamically to avoid ClassNotFound * Complete the chanegs to the RELEASE-NOTES.MD * Extend list of exceptions * Tweaks to the presentation of the ne JSON guide * Behavior is the preferred spelling in American English. Behaviour is preferred everywhere else. Extending list of exceptions to include (most) cases of the usage. * Use the release version for the badge * Lazy initialize the JsonParser instance to avoid hitting NoClassDefFound error * Shame (ding) shame (ding) shame (ding) * Yet more words to add to the wordlist --- .github/wordlist.txt | 21 ++++++- README.md | 15 +++-- RELEASE-NOTES.md | 59 +++++++++---------- docs/getting-started.md | 6 +- docs/user-guide/redis-json.md | 34 +++++++---- mkdocs.yml | 1 + pom.xml | 17 +++++- .../core/AbstractRedisAsyncCommands.java | 7 ++- .../core/AbstractRedisReactiveCommands.java | 6 +- .../java/io/lettuce/core/ClientOptions.java | 30 +++++++--- .../lettuce/core/RedisAsyncCommandsImpl.java | 3 +- .../lettuce/core/RedisJsonCommandBuilder.java | 11 ++-- .../core/RedisReactiveCommandsImpl.java | 4 +- .../core/StatefulRedisConnectionImpl.java | 5 +- ...RedisAdvancedClusterAsyncCommandsImpl.java | 7 ++- ...isAdvancedClusterReactiveCommandsImpl.java | 6 +- .../core/cluster/RedisClusterClient.java | 6 +- .../StatefulRedisClusterConnectionImpl.java | 5 +- .../lettuce/core/json/DefaultJsonParser.java | 5 -- ...tefulRedisMasterReplicaConnectionImpl.java | 4 +- .../RedisSentinelReactiveCommandsImpl.java | 3 +- .../StatefulRedisSentinelConnectionImpl.java | 3 +- .../services/io.lettuce.core.json.JsonParser | 1 + .../MyExtendedRedisClusterClient.java | 3 +- .../MyRedisClusterConnection.java | 3 +- .../lettuce/core/ClientOptionsUnitTests.java | 8 +-- .../RedisJsonCommandBuilderUnitTests.java | 5 +- .../core/json/DefaultJsonParserUnitTests.java | 12 ++-- .../core/json/DelegateJsonArrayUnitTests.java | 18 +++--- .../json/DelegateJsonObjectUnitTests.java | 4 +- .../core/json/DelegateJsonValueUnitTests.java | 10 ++-- .../core/json/RedisJsonIntegrationTests.java | 3 +- .../json/UnproccessedJsonValueUnitTests.java | 12 ++-- .../output/JsonValueListOutputUnitTests.java | 2 +- .../dynamic/RedisCommandFactoryBenchmark.java | 3 +- 35 files changed, 206 insertions(+), 136 deletions(-) create mode 100644 src/main/resources/META-INF/services/io.lettuce.core.json.JsonParser diff --git a/.github/wordlist.txt b/.github/wordlist.txt index f51a8a92cd..5c11d89f82 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -252,4 +252,23 @@ uring whitespace xml RedisJSON -MkDocs \ No newline at end of file +MkDocs +ClientOptions +TimeoutOptions +timeoutOptions +ClusterCommand +completeExceptionally +spublish +BitSet +RedisClusterNode's +allOf +reentrant +jacoco +apache +failsafe +hdrhistogram +bom +ubuntu +behaviour +databind +jackson \ No newline at end of file diff --git a/README.md b/README.md index 8358a1538e..3fcbcc63b5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ [![Integration](https://github.com/redis/lettuce/actions/workflows/integration.yml/badge.svg?branch=main)](https://github.com/redis/lettuce/actions/workflows/integration.yml) [![codecov](https://codecov.io/gh/redis/lettuce/branch/main/graph/badge.svg?token=pAstxAAjYo)](https://codecov.io/gh/redis/lettuce) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.txt) - [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.lettuce/lettuce-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.lettuce/lettuce-core) + [![Maven Central](https://img.shields.io/maven-central/v/io.lettuce/lettuce-core?versionSuffix=RELEASE&logo=redis + )](https://maven-badges.herokuapp.com/maven-central/io.lettuce/lettuce-core) [![Javadocs](https://www.javadoc.io/badge/io.lettuce/lettuce-core.svg)](https://www.javadoc.io/doc/io.lettuce/lettuce-core) [![Discord](https://img.shields.io/discord/697882427875393627.svg?style=social&logo=discord)](https://discord.gg/redis) @@ -35,17 +36,15 @@ See the [reference documentation](https://redis.github.io/lettuce/) and [API Ref ## How do I Redis? -[Learn for free at Redis University](https://university.redis.com/) +[Learn for free at Redis University](https://university.redis.io/academy) -[Build faster with the Redis Launchpad](https://launchpad.redis.com/) +[Try the Redis Cloud](https://redis.io/try-free/) -[Try the Redis Cloud](https://redis.com/try-free/) +[Dive in developer tutorials](https://redis.io/learn/) -[Dive in developer tutorials](https://developer.redis.com/) +[Join the Redis community](https://redis.io/community/) -[Join the Redis community](https://redis.com/community/) - -[Work at Redis](https://redis.com/company/careers/jobs/) +[Work at Redis](https://redis.io/careers/jobs/) Documentation --------------- diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 481c2b4cf8..5f8b73369f 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,11 +1,10 @@ -Lettuce 6.4.0 RELEASE NOTES +Lettuce 6.5.0 RELEASE NOTES ============================== -The Redis team is delighted to announce general availability of Lettuce 6.4. +The Redis team is delighted to announce the general availability of Lettuce 6.5. -This Lettuce driver is now going to be shipped under the MIT licensing scheme. The `CLIENT SETINFO` -is now working in a fire-and-forget mode to allow better compatibility with Redis servers that do -not support this command. +Great news, everyone! Lettuce 6.5.0 comes with RedisJSON support enabled. +For more on that, please consult with the [RedisJSON documentation](https://redis.io/docs/latest/develop/data-types/json/) and the [Lettuce guide on RedisJSON](https://redis.github.io/lettuce/user-guide/redis-json/). Lettuce 6 supports Redis 2.6+ up to Redis 7.x. In terms of Java runtime, Lettuce requires at least Java 8 and works with Java 21. @@ -16,45 +15,43 @@ If you need any support, meet Lettuce at * GitHub Discussions: https://github.com/lettuce-io/lettuce-core/discussions * Stack Overflow (Questions): https://stackoverflow.com/questions/tagged/lettuce -* Join the chat at https://discord.gg/redis for general discussion -* GitHub Issues (Bug reports, feature - requests): https://github.com/lettuce-io/lettuce-core/issues -* Documentation: https://lettuce.io/core/6.4.0.RELEASE/reference/ -* Javadoc: https://lettuce.io/core/6.4.0.RELEASE/api/ +* Join the chat at https://discord.gg/redis and look for the "Help:Tools Lettuce" channel +* GitHub Issues (Bug reports, feature requests): https://github.com/lettuce-io/lettuce-core/issues +* Documentation: https://lettuce.io/core/6.5.0.RELEASE/reference/ +* Javadoc: https://lettuce.io/core/6.5.0.RELEASE/api/ Commands -------- -* Add `PUBSUB` shard channel commands `SHARDCHANNELS` #2756, `SHARDNUMSUB` #2776 -* Add `PUBSUB` shard channel commands `SPUBLISH` #2757, `SSUBSCRIBE` #2758 and `SUNSUBSCRIBE` #2758 -* Add support for `CLIENT KILL [MAXAGE]` #2782 -* Hash field expiration commands `HEXPIRE`, `HEXPIREAT`, `HEXPIRETIME` and `HPERSIST` #2836 -* Hash field expiration commands `HPEXPIRE`, `HPEXPIREAT`, `HPEXPIRETIME`, `HTTL` and `HPTTL` #2857 +* Add `CLUSTER MYSHARDID` in #2920 and `CLUSTER LINKS` in #2986 +* Add `CLIENT TRACKINGINFO` in #2862 Enhancements ------------ -* Add support for `HSCAN NOVALUES` #2763 -* Send the `CLIENT SETINFO` command in a fire-and-forget way #2082 -* Change the license to more permissive MIT #2173 -* Add a evalReadOnly overload that accepts the script as a String #2868 -* `XREAD` support for reading last message from stream #2863 -* Mark dnsResolver(DnsResolver) as deprecated #2855 -* Remove connection-related methods from commands API #2027 -* Move connection-related commands from BaseRedisCommands to RedisConnectionCommands #2031 +* Default ClientOptions.timeoutOptions to TimeoutOptions.enabled() (#2927) +* Update completeExceptionally on ClusterCommand using super (#2980) Fixes ----- +* fix(2971): spublish typo fix (#2972) +* Initialize slots with empty BitSet in RedisClusterNode's constructors (#2341) +* Add defensive copy for Futures allOf() method (#2943) +* fix:deadlock when reentrant exclusive lock (#2961) -* None Other ----- -* Bump `org.apache.commons:commons-pool2` from 2.11.1 to 2.12.0 #2877 -* Bump `org.openjdk.jmh:jmh-generator-annprocess` from 1.21 to 1.37 #2876 -* Bump `org.apache.maven.plugins:maven-jar-plugin` from 3.3.0 to 3.4.1 #2875 -* Bump `org.codehaus.mojo:flatten-maven-plugin from` 1.5.0 to 1.6.0 #2874 -* Bump `org.apache.maven.plugins:maven-javadoc-plugin` from 3.6.3 to 3.7.0 #2873 -* Applying code formatter each time we run a Maven build #2841 -* Bump `setup-java` to v4 #2807 +* Add badges to the README.md file (#2939) +* Convert wiki to markdown docs (#2944) +* Bump org.jacoco:jacoco-maven-plugin from 0.8.9 to 0.8.12 (#2921) +* Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.5 to 3.3.1 (#2922) +* Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.1 (#2958) +* Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0 (#2957) +* Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.1 to 3.4.0 (#2968) +* Bump org.hdrhistogram:HdrHistogram from 2.1.12 to 2.2.2 (#2966) +* Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0 (#2978) +* Bump org.apache.logging.log4j:log4j-bom from 2.17.2 to 2.24.0 (#2988) +* Bump io.netty:netty-bom from 4.1.107.Final to 4.1.113.Final (#2990) +* Suspected change in ubuntu causing CI failures (#2949) diff --git a/docs/getting-started.md b/docs/getting-started.md index af6d3a6838..a9bdc97fd1 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -12,7 +12,7 @@ Add these lines to file pom.xml: io.lettuce lettuce-core - 6.4.0.RELEASE + 6.5.0.RELEASE ``` @@ -23,7 +23,7 @@ Add these lines to file ivy.xml: ``` xml - + ``` @@ -34,7 +34,7 @@ Add these lines to file build.gradle: ``` groovy dependencies { - implementation 'io.lettuce:lettuce-core:6.4.0.RELEASE' + implementation 'io.lettuce:lettuce-core:6.5.0.RELEASE' } ``` diff --git a/docs/user-guide/redis-json.md b/docs/user-guide/redis-json.md index 5c6905bd73..dbdf18bb1a 100644 --- a/docs/user-guide/redis-json.md +++ b/docs/user-guide/redis-json.md @@ -7,19 +7,24 @@ The driver generally allows three distinct ways of working with the RedisJSON mo * (Advanced mode) - custom JSON parsing using a user-provided JSON parser * (Power-user mode) - unprocessed JSON documents that have not gone through any process of deserialization or serialization -> [!IMPORTANT]\ -> In all the above modes, the driver would refrain from processing the JSON document in the main event loop and instead -delegate this to the user thread. This behaviour is consistent when both receiving and sending JSON documents - when -receiving the parsing is done lazily whenever a method is called that requires the JSON to be parsed; when sending the -JSON is serialized immediately after it is passed to any of the commands, but before dispatching the command to the -event loop. - +!!! INFO + In all the above modes, the driver would refrain from processing the JSON document in the main event loop and instead + delegate this to the user thread. This behaviour is consistent when both receiving and sending JSON documents - when + receiving the parsing is done lazily whenever a method is called that requires the JSON to be parsed; when sending the + JSON is serialized immediately after it is passed to any of the commands, but before dispatching the command to the + event loop. + +!!! WARNING + Unless you are using a custom JSON parser you would need to add a dependency to the + [jackson-databind](https://github.com/FasterXML/jackson-databind) library in your project. This is because the + default JSON parser uses Jackson to parse JSON documents to and from string representations. ## Default mode Best for: + * Most typical use-cases where the JSON document is parsed and processed -### Example usage: +### Example usage ```java RedisURI redisURI = RedisURI.Builder.redis("acme.com").build(); @@ -52,25 +57,29 @@ try (StatefulRedisConnection connect = redisClient.conne ## Advanced mode Best for: + * Applications that want to handle parsing manually - either by using another library or by implementing their own parser -### Example usage: +### Example usage ```java RedisURI redisURI = RedisURI.Builder.redis("127.0.0.1").withPort(16379).build(); try (RedisClient client = RedisClient.create(redisURI)) { - client.setOptions(ClientOptions.builder().jsonParser(new CustomParser()).build()); + client.setOptions(ClientOptions.builder().jsonParser(Mono.just(new CustomParser())).build()); StatefulRedisConnection connection = client.connect(StringCodec.UTF8); RedisCommands redis = connection.sync(); } ``` + + ## Power-user mode Best for: + * Applications that do little to no processing on the Java layer -### Example usage: +### Example usage ```java JsonPath myPath = JsonPath.of("$..mountain_bikes"); @@ -85,3 +94,6 @@ try (RedisClient client = RedisClient.create(redisURI)) { String result = stage.toCompletableFuture().get().get(); } ``` +!!! NOTE + The power-user mode is not exclusive to using a custom parser (Advanced mode), as long as the custom parser follows + the API contract of the `JsonParser`, `JsonValue`, `JsonArray` and `JsonObject` interfaces. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6a919928fb..14e269e148 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Kotlin API: user-guide/kotlin-api.md - Publish/Subscribe: user-guide/pubsub.md - Transactions/Multi: user-guide/transactions-multi.md + - Redis JSON: user-guide/redis-json.md - Redis programmability: - LUA Scripting: user-guide/lua-scripting.md - Redis Functions: user-guide/redis-functions.md diff --git a/pom.xml b/pom.xml index bc3225af6a..da7a50f5c5 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ io.lettuce lettuce-core - 6.4.0.BUILD-SNAPSHOT + 6.5.0.BUILD-SNAPSHOT jar Lettuce @@ -546,6 +546,21 @@ test + + + + org.openjdk.jmh + jmh-core + 1.37 + test + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + test + + diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index 5789812671..9c8b52849b 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -48,6 +48,7 @@ import io.lettuce.core.protocol.CommandType; import io.lettuce.core.protocol.ProtocolKeyword; import io.lettuce.core.protocol.RedisCommand; +import reactor.core.publisher.Mono; import java.time.Duration; import java.time.Instant; @@ -87,7 +88,7 @@ public abstract class AbstractRedisAsyncCommands implements RedisAclAsyncC private final RedisJsonCommandBuilder jsonCommandBuilder; - private final JsonParser parser; + private final Mono parser; /** * Initialize a new instance. @@ -95,7 +96,7 @@ public abstract class AbstractRedisAsyncCommands implements RedisAclAsyncC * @param connection the connection to operate on * @param codec the codec for command encoding */ - public AbstractRedisAsyncCommands(StatefulConnection connection, RedisCodec codec, JsonParser parser) { + public AbstractRedisAsyncCommands(StatefulConnection connection, RedisCodec codec, Mono parser) { this.parser = parser; this.connection = connection; this.commandBuilder = new RedisCommandBuilder<>(codec); @@ -3380,7 +3381,7 @@ public RedisFuture>> clusterLinks() { @Override public JsonParser getJsonParser() { - return this.parser; + return this.parser.block(); } private byte[] encodeFunction(String functionCode) { diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index 350fbce601..eb7e911ca4 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -98,7 +98,7 @@ public abstract class AbstractRedisReactiveCommands private final RedisJsonCommandBuilder jsonCommandBuilder; - private final JsonParser parser; + private final Mono parser; private final ClientResources clientResources; @@ -112,7 +112,7 @@ public abstract class AbstractRedisReactiveCommands * @param connection the connection to operate on. * @param codec the codec for command encoding. */ - public AbstractRedisReactiveCommands(StatefulConnection connection, RedisCodec codec, JsonParser parser) { + public AbstractRedisReactiveCommands(StatefulConnection connection, RedisCodec codec, Mono parser) { this.connection = connection; this.parser = parser; this.commandBuilder = new RedisCommandBuilder<>(codec); @@ -139,7 +139,7 @@ private EventExecutorGroup getScheduler() { @Override public JsonParser getJsonParser() { - return parser; + return parser.block(); } @Override diff --git a/src/main/java/io/lettuce/core/ClientOptions.java b/src/main/java/io/lettuce/core/ClientOptions.java index 9d8aeb4ad9..9f1f1c33d9 100644 --- a/src/main/java/io/lettuce/core/ClientOptions.java +++ b/src/main/java/io/lettuce/core/ClientOptions.java @@ -22,16 +22,20 @@ import java.io.Serializable; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; import io.lettuce.core.api.StatefulConnection; import io.lettuce.core.internal.LettuceAssert; -import io.lettuce.core.json.DefaultJsonParser; import io.lettuce.core.json.JsonParser; +import io.lettuce.core.json.RedisJsonException; import io.lettuce.core.protocol.DecodeBufferPolicies; import io.lettuce.core.protocol.DecodeBufferPolicy; import io.lettuce.core.protocol.ProtocolVersion; import io.lettuce.core.protocol.ReadOnlyCommands; import io.lettuce.core.resource.ClientResources; +import reactor.core.publisher.Mono; /** * Client Options to control the behavior of {@link RedisClient}. @@ -65,14 +69,22 @@ public class ClientOptions implements Serializable { public static final SocketOptions DEFAULT_SOCKET_OPTIONS = SocketOptions.create(); + public static final Mono DEFAULT_JSON_PARSER = Mono.defer(() -> Mono.fromCallable(() -> { + try { + Iterator services = ServiceLoader.load(JsonParser.class).iterator(); + return services.hasNext() ? services.next() : null; + } catch (ServiceConfigurationError e) { + throw new RedisJsonException("Could not load JsonParser, please consult the guide" + + "at https://redis.github.io/lettuce/user-guide/redis-json/", e); + } + })); + public static final SslOptions DEFAULT_SSL_OPTIONS = SslOptions.create(); public static final boolean DEFAULT_SUSPEND_RECONNECT_PROTO_FAIL = false; public static final TimeoutOptions DEFAULT_TIMEOUT_OPTIONS = TimeoutOptions.enabled(); - public static final JsonParser DEFAULT_JSON_PARSER = DefaultJsonParser.INSTANCE; - private final boolean autoReconnect; private final boolean cancelCommandsOnReconnectFailure; @@ -93,7 +105,7 @@ public class ClientOptions implements Serializable { private final Charset scriptCharset; - private final JsonParser jsonParser; + private final Mono jsonParser; private final SocketOptions socketOptions; @@ -192,7 +204,7 @@ public static class Builder { private Charset scriptCharset = DEFAULT_SCRIPT_CHARSET; - private JsonParser jsonParser = DEFAULT_JSON_PARSER; + private Mono jsonParser = DEFAULT_JSON_PARSER; private SocketOptions socketOptions = DEFAULT_SOCKET_OPTIONS; @@ -380,14 +392,14 @@ public Builder scriptCharset(Charset scriptCharset) { } /** - * Set a custom implementation for the {@link JsonParser} to use. Defaults to {@link DefaultJsonParser}. + * Set a custom implementation for the {@link JsonParser} to use. * - * @param parser must not be {@code null}. + * @param parser a {@link Mono} that emits the {@link JsonParser} to use. * @return {@code this} * @see JsonParser * @since 6.5 */ - public Builder jsonParser(JsonParser parser) { + public Builder jsonParser(Mono parser) { LettuceAssert.notNull(parser, "JsonParser must not be null"); this.jsonParser = parser; @@ -640,7 +652,7 @@ public Charset getScriptCharset() { * @return the implementation of the {@link JsonParser} to use. * @since 6.5 */ - public JsonParser getJsonParser() { + public Mono getJsonParser() { return jsonParser; } diff --git a/src/main/java/io/lettuce/core/RedisAsyncCommandsImpl.java b/src/main/java/io/lettuce/core/RedisAsyncCommandsImpl.java index 23ded92df9..d45215f082 100644 --- a/src/main/java/io/lettuce/core/RedisAsyncCommandsImpl.java +++ b/src/main/java/io/lettuce/core/RedisAsyncCommandsImpl.java @@ -5,6 +5,7 @@ import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.json.JsonParser; +import reactor.core.publisher.Mono; /** * An asynchronous and thread-safe API for a Redis connection. @@ -23,7 +24,7 @@ public class RedisAsyncCommandsImpl extends AbstractRedisAsyncCommands connection, RedisCodec codec, JsonParser parser) { + public RedisAsyncCommandsImpl(StatefulRedisConnection connection, RedisCodec codec, Mono parser) { super(connection, codec, parser); } diff --git a/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java b/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java index fb1e580179..ee7e8cf97b 100644 --- a/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java @@ -20,6 +20,7 @@ import io.lettuce.core.protocol.BaseRedisCommandBuilder; import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandArgs; +import reactor.core.publisher.Mono; import java.util.List; @@ -33,9 +34,9 @@ */ class RedisJsonCommandBuilder extends BaseRedisCommandBuilder { - private final JsonParser parser; + private final Mono parser; - RedisJsonCommandBuilder(RedisCodec codec, JsonParser theParser) { + RedisJsonCommandBuilder(RedisCodec codec, Mono theParser) { super(codec); parser = theParser; } @@ -117,7 +118,7 @@ Command> jsonArrpop(K key, JsonPath jsonPath, int index) { } } - return createCommand(JSON_ARRPOP, new JsonValueListOutput<>(codec, parser), args); + return createCommand(JSON_ARRPOP, new JsonValueListOutput<>(codec, parser.block()), args); } Command> jsonArrtrim(K key, JsonPath jsonPath, JsonRangeArgs range) { @@ -166,7 +167,7 @@ Command> jsonGet(K key, JsonGetArgs options, JsonPath... j } } - return createCommand(JSON_GET, new JsonValueListOutput<>(codec, parser), args); + return createCommand(JSON_GET, new JsonValueListOutput<>(codec, parser.block()), args); } Command jsonMerge(K key, JsonPath jsonPath, JsonValue value) { @@ -193,7 +194,7 @@ Command> jsonMGet(JsonPath jsonPath, K... keys) { args.add(jsonPath.toString()); } - return createCommand(JSON_MGET, new JsonValueListOutput<>(codec, parser), args); + return createCommand(JSON_MGET, new JsonValueListOutput<>(codec, parser.block()), args); } Command jsonMSet(List> arguments) { diff --git a/src/main/java/io/lettuce/core/RedisReactiveCommandsImpl.java b/src/main/java/io/lettuce/core/RedisReactiveCommandsImpl.java index 23ffd71ef2..fae12f611b 100644 --- a/src/main/java/io/lettuce/core/RedisReactiveCommandsImpl.java +++ b/src/main/java/io/lettuce/core/RedisReactiveCommandsImpl.java @@ -5,6 +5,7 @@ import io.lettuce.core.cluster.api.reactive.RedisClusterReactiveCommands; import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.json.JsonParser; +import reactor.core.publisher.Mono; /** * A reactive and thread-safe API for a Redis Sentinel connection. @@ -23,7 +24,8 @@ public class RedisReactiveCommandsImpl extends AbstractRedisReactiveComman * @param codec the codec for command encoding. * */ - public RedisReactiveCommandsImpl(StatefulRedisConnection connection, RedisCodec codec, JsonParser parser) { + public RedisReactiveCommandsImpl(StatefulRedisConnection connection, RedisCodec codec, + Mono parser) { super(connection, codec, parser); } diff --git a/src/main/java/io/lettuce/core/StatefulRedisConnectionImpl.java b/src/main/java/io/lettuce/core/StatefulRedisConnectionImpl.java index 1948062a59..aef29c99bb 100644 --- a/src/main/java/io/lettuce/core/StatefulRedisConnectionImpl.java +++ b/src/main/java/io/lettuce/core/StatefulRedisConnectionImpl.java @@ -40,6 +40,7 @@ import io.lettuce.core.output.MultiOutput; import io.lettuce.core.output.StatusOutput; import io.lettuce.core.protocol.*; +import reactor.core.publisher.Mono; /** * A thread-safe connection to a Redis server. Multiple threads may share one {@link StatefulRedisConnectionImpl} @@ -65,7 +66,7 @@ public class StatefulRedisConnectionImpl extends RedisChannelHandler private final PushHandler pushHandler; - private final JsonParser parser; + private final Mono parser; protected MultiOutput multi; @@ -78,7 +79,7 @@ public class StatefulRedisConnectionImpl extends RedisChannelHandler * @param timeout Maximum time to wait for a response. */ public StatefulRedisConnectionImpl(RedisChannelWriter writer, PushHandler pushHandler, RedisCodec codec, - Duration timeout, JsonParser parser) { + Duration timeout, Mono parser) { super(writer, timeout); diff --git a/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterAsyncCommandsImpl.java b/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterAsyncCommandsImpl.java index c0ba71e48a..14295db788 100644 --- a/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterAsyncCommandsImpl.java +++ b/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterAsyncCommandsImpl.java @@ -64,6 +64,7 @@ import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandType; import io.lettuce.core.protocol.ConnectionIntent; +import reactor.core.publisher.Mono; /** * An advanced asynchronous and thread-safe API for a Redis Cluster connection. @@ -87,11 +88,11 @@ public class RedisAdvancedClusterAsyncCommandsImpl extends AbstractRedisAs * @param connection the stateful connection * @param codec Codec used to encode/decode keys and values. * @deprecated since 5.1, use - * {@link #RedisAdvancedClusterAsyncCommandsImpl(StatefulRedisClusterConnection, RedisCodec, JsonParser)}. + * {@link #RedisAdvancedClusterAsyncCommandsImpl(StatefulRedisClusterConnection, RedisCodec, Mono)}. */ @Deprecated public RedisAdvancedClusterAsyncCommandsImpl(StatefulRedisClusterConnectionImpl connection, RedisCodec codec, - JsonParser parser) { + Mono parser) { super(connection, codec, parser); this.codec = codec; } @@ -103,7 +104,7 @@ public RedisAdvancedClusterAsyncCommandsImpl(StatefulRedisClusterConnectionImpl< * @param codec Codec used to encode/decode keys and values. */ public RedisAdvancedClusterAsyncCommandsImpl(StatefulRedisClusterConnection connection, RedisCodec codec, - JsonParser parser) { + Mono parser) { super(connection, codec, parser); this.codec = codec; } diff --git a/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterReactiveCommandsImpl.java b/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterReactiveCommandsImpl.java index bd8d6f671a..0517feb4c4 100644 --- a/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterReactiveCommandsImpl.java +++ b/src/main/java/io/lettuce/core/cluster/RedisAdvancedClusterReactiveCommandsImpl.java @@ -77,11 +77,11 @@ public class RedisAdvancedClusterReactiveCommandsImpl extends AbstractRedi * @param connection the stateful connection. * @param codec Codec used to encode/decode keys and values. * @deprecated since 5.2, use - * {@link #RedisAdvancedClusterReactiveCommandsImpl(StatefulRedisClusterConnection, RedisCodec, JsonParser)}. + * {@link #RedisAdvancedClusterReactiveCommandsImpl(StatefulRedisClusterConnection, RedisCodec, Mono)}. */ @Deprecated public RedisAdvancedClusterReactiveCommandsImpl(StatefulRedisClusterConnectionImpl connection, RedisCodec codec, - JsonParser parser) { + Mono parser) { super(connection, codec, parser); this.codec = codec; } @@ -93,7 +93,7 @@ public RedisAdvancedClusterReactiveCommandsImpl(StatefulRedisClusterConnectionIm * @param codec Codec used to encode/decode keys and values. */ public RedisAdvancedClusterReactiveCommandsImpl(StatefulRedisClusterConnection connection, RedisCodec codec, - JsonParser parser) { + Mono parser) { super(connection, codec, parser); this.codec = codec; } diff --git a/src/main/java/io/lettuce/core/cluster/RedisClusterClient.java b/src/main/java/io/lettuce/core/cluster/RedisClusterClient.java index 499e3cd6da..577689cecc 100644 --- a/src/main/java/io/lettuce/core/cluster/RedisClusterClient.java +++ b/src/main/java/io/lettuce/core/cluster/RedisClusterClient.java @@ -576,12 +576,13 @@ ConnectionFuture> connectToNodeAsync(RedisC * @param pushHandler the handler for push notifications * @param codec codec * @param timeout default timeout + * @param parser the JSON parser to be used * @param Key-Type * @param Value Type * @return new instance of StatefulRedisConnectionImpl */ protected StatefulRedisConnectionImpl newStatefulRedisConnection(RedisChannelWriter channelWriter, - PushHandler pushHandler, RedisCodec codec, Duration timeout, JsonParser parser) { + PushHandler pushHandler, RedisCodec codec, Duration timeout, Mono parser) { return new StatefulRedisConnectionImpl<>(channelWriter, pushHandler, codec, timeout, parser); } @@ -700,13 +701,14 @@ private CompletableFuture> connectCl * @param pushHandler the handler for push notifications * @param codec codec * @param timeout default timeout + * @param parser the Json parser to be used * @param Key-Type * @param Value Type * @return new instance of StatefulRedisClusterConnectionImpl */ protected StatefulRedisClusterConnectionImpl newStatefulRedisClusterConnection( RedisChannelWriter channelWriter, ClusterPushHandler pushHandler, RedisCodec codec, Duration timeout, - JsonParser parser) { + Mono parser) { return new StatefulRedisClusterConnectionImpl(channelWriter, pushHandler, codec, timeout, parser); } diff --git a/src/main/java/io/lettuce/core/cluster/StatefulRedisClusterConnectionImpl.java b/src/main/java/io/lettuce/core/cluster/StatefulRedisClusterConnectionImpl.java index e248f36822..4a27ef1a14 100644 --- a/src/main/java/io/lettuce/core/cluster/StatefulRedisClusterConnectionImpl.java +++ b/src/main/java/io/lettuce/core/cluster/StatefulRedisClusterConnectionImpl.java @@ -58,6 +58,7 @@ import io.lettuce.core.protocol.ConnectionIntent; import io.lettuce.core.protocol.ConnectionWatchdog; import io.lettuce.core.protocol.RedisCommand; +import reactor.core.publisher.Mono; /** * A thread-safe connection to a Redis Cluster. Multiple threads may share one {@link StatefulRedisClusterConnectionImpl} @@ -75,7 +76,7 @@ public class StatefulRedisClusterConnectionImpl extends RedisChannelHandle protected final RedisCodec codec; - protected final JsonParser parser; + protected final Mono parser; protected final RedisAdvancedClusterCommands sync; @@ -96,7 +97,7 @@ public class StatefulRedisClusterConnectionImpl extends RedisChannelHandle * @param timeout Maximum time to wait for a response. */ public StatefulRedisClusterConnectionImpl(RedisChannelWriter writer, ClusterPushHandler pushHandler, RedisCodec codec, - Duration timeout, JsonParser parser) { + Duration timeout, Mono parser) { super(writer, timeout); this.pushHandler = pushHandler; diff --git a/src/main/java/io/lettuce/core/json/DefaultJsonParser.java b/src/main/java/io/lettuce/core/json/DefaultJsonParser.java index a002d9782a..afab7afa70 100644 --- a/src/main/java/io/lettuce/core/json/DefaultJsonParser.java +++ b/src/main/java/io/lettuce/core/json/DefaultJsonParser.java @@ -24,11 +24,6 @@ */ public class DefaultJsonParser implements JsonParser { - public static final DefaultJsonParser INSTANCE = new DefaultJsonParser(); - - private DefaultJsonParser() { - } - @Override public JsonValue loadJsonValue(ByteBuffer bytes) { return new UnproccessedJsonValue(bytes, this); diff --git a/src/main/java/io/lettuce/core/masterreplica/StatefulRedisMasterReplicaConnectionImpl.java b/src/main/java/io/lettuce/core/masterreplica/StatefulRedisMasterReplicaConnectionImpl.java index 974b18a045..4908a6afef 100644 --- a/src/main/java/io/lettuce/core/masterreplica/StatefulRedisMasterReplicaConnectionImpl.java +++ b/src/main/java/io/lettuce/core/masterreplica/StatefulRedisMasterReplicaConnectionImpl.java @@ -6,6 +6,7 @@ import io.lettuce.core.StatefulRedisConnectionImpl; import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.json.JsonParser; +import reactor.core.publisher.Mono; /** * @author Mark Paluch @@ -19,9 +20,10 @@ class StatefulRedisMasterReplicaConnectionImpl extends StatefulRedisConnec * @param writer the channel writer * @param codec Codec used to encode/decode keys and values. * @param timeout Maximum time to wait for a response. + * @param parser the JSON parser to use */ StatefulRedisMasterReplicaConnectionImpl(MasterReplicaChannelWriter writer, RedisCodec codec, Duration timeout, - JsonParser parser) { + Mono parser) { super(writer, NoOpPushHandler.INSTANCE, codec, timeout, parser); } diff --git a/src/main/java/io/lettuce/core/sentinel/RedisSentinelReactiveCommandsImpl.java b/src/main/java/io/lettuce/core/sentinel/RedisSentinelReactiveCommandsImpl.java index abd388827d..e02cf4d960 100644 --- a/src/main/java/io/lettuce/core/sentinel/RedisSentinelReactiveCommandsImpl.java +++ b/src/main/java/io/lettuce/core/sentinel/RedisSentinelReactiveCommandsImpl.java @@ -51,7 +51,8 @@ public class RedisSentinelReactiveCommandsImpl extends AbstractRedisReacti private final SentinelCommandBuilder commandBuilder; - public RedisSentinelReactiveCommandsImpl(StatefulConnection connection, RedisCodec codec, JsonParser parser) { + public RedisSentinelReactiveCommandsImpl(StatefulConnection connection, RedisCodec codec, + Mono parser) { super(connection, codec, parser); commandBuilder = new SentinelCommandBuilder(codec); } diff --git a/src/main/java/io/lettuce/core/sentinel/StatefulRedisSentinelConnectionImpl.java b/src/main/java/io/lettuce/core/sentinel/StatefulRedisSentinelConnectionImpl.java index e8f1ec5ed9..a302847752 100644 --- a/src/main/java/io/lettuce/core/sentinel/StatefulRedisSentinelConnectionImpl.java +++ b/src/main/java/io/lettuce/core/sentinel/StatefulRedisSentinelConnectionImpl.java @@ -34,6 +34,7 @@ import io.lettuce.core.sentinel.api.async.RedisSentinelAsyncCommands; import io.lettuce.core.sentinel.api.reactive.RedisSentinelReactiveCommands; import io.lettuce.core.sentinel.api.sync.RedisSentinelCommands; +import reactor.core.publisher.Mono; /** * @author Mark Paluch @@ -52,7 +53,7 @@ public class StatefulRedisSentinelConnectionImpl extends RedisChannelHandl private final SentinelConnectionState connectionState = new SentinelConnectionState(); public StatefulRedisSentinelConnectionImpl(RedisChannelWriter writer, RedisCodec codec, Duration timeout, - JsonParser parser) { + Mono parser) { super(writer, timeout); diff --git a/src/main/resources/META-INF/services/io.lettuce.core.json.JsonParser b/src/main/resources/META-INF/services/io.lettuce.core.json.JsonParser new file mode 100644 index 0000000000..f53cf85425 --- /dev/null +++ b/src/main/resources/META-INF/services/io.lettuce.core.json.JsonParser @@ -0,0 +1 @@ +io.lettuce.core.json.DefaultJsonParser \ No newline at end of file diff --git a/src/test/java/biz/paluch/redis/extensibility/MyExtendedRedisClusterClient.java b/src/test/java/biz/paluch/redis/extensibility/MyExtendedRedisClusterClient.java index e87f278de3..1ac2848077 100644 --- a/src/test/java/biz/paluch/redis/extensibility/MyExtendedRedisClusterClient.java +++ b/src/test/java/biz/paluch/redis/extensibility/MyExtendedRedisClusterClient.java @@ -31,6 +31,7 @@ import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.json.JsonParser; import io.lettuce.core.resource.ClientResources; +import reactor.core.publisher.Mono; /** * Demo code for extending a RedisClusterClient. @@ -50,7 +51,7 @@ public MyExtendedRedisClusterClient() { @Override protected StatefulRedisClusterConnectionImpl newStatefulRedisClusterConnection( RedisChannelWriter channelWriter, ClusterPushHandler pushHandler, RedisCodec codec, Duration timeout, - JsonParser parser) { + Mono parser) { return new MyRedisClusterConnection<>(channelWriter, pushHandler, codec, timeout, parser); } diff --git a/src/test/java/biz/paluch/redis/extensibility/MyRedisClusterConnection.java b/src/test/java/biz/paluch/redis/extensibility/MyRedisClusterConnection.java index 088c6831fc..04632e463c 100644 --- a/src/test/java/biz/paluch/redis/extensibility/MyRedisClusterConnection.java +++ b/src/test/java/biz/paluch/redis/extensibility/MyRedisClusterConnection.java @@ -26,6 +26,7 @@ import io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl; import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.json.JsonParser; +import reactor.core.publisher.Mono; /** * Demo code for extending a @{@link StatefulRedisClusterConnectionImpl} @@ -36,7 +37,7 @@ class MyRedisClusterConnection extends StatefulRedisClusterConnectionImpl { public MyRedisClusterConnection(RedisChannelWriter writer, ClusterPushHandler pushHandler, RedisCodec codec, - Duration timeout, JsonParser parser) { + Duration timeout, Mono parser) { super(writer, pushHandler, codec, timeout, parser); } diff --git a/src/test/java/io/lettuce/core/ClientOptionsUnitTests.java b/src/test/java/io/lettuce/core/ClientOptionsUnitTests.java index 9b86ee189e..5d2134b05d 100644 --- a/src/test/java/io/lettuce/core/ClientOptionsUnitTests.java +++ b/src/test/java/io/lettuce/core/ClientOptionsUnitTests.java @@ -9,13 +9,13 @@ import io.lettuce.core.json.JsonArray; import io.lettuce.core.json.JsonObject; import io.lettuce.core.json.JsonParser; -import io.lettuce.core.json.JsonPath; import io.lettuce.core.json.JsonValue; import org.junit.jupiter.api.Test; import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandType; import io.lettuce.core.protocol.ProtocolVersion; +import reactor.core.publisher.Mono; /** * Unit tests for {@link ClientOptions}. @@ -37,7 +37,7 @@ void testDefault() { assertThat(options.getReadOnlyCommands().isReadOnly(new Command<>(CommandType.SET, null))).isFalse(); assertThat(options.getReadOnlyCommands().isReadOnly(new Command<>(CommandType.PUBLISH, null))).isFalse(); assertThat(options.getReadOnlyCommands().isReadOnly(new Command<>(CommandType.GET, null))).isTrue(); - assertThat(options.getJsonParser()).isInstanceOf(DefaultJsonParser.class); + assertThat(options.getJsonParser().block()).isInstanceOf(DefaultJsonParser.class); } @Test @@ -63,8 +63,8 @@ void testCopy() { @Test void jsonParser() { JsonParser parser = new CustomJsonParser(); - ClientOptions options = ClientOptions.builder().jsonParser(parser).build(); - assertThat(options.getJsonParser()).isInstanceOf(CustomJsonParser.class); + ClientOptions options = ClientOptions.builder().jsonParser(Mono.justOrEmpty(parser)).build(); + assertThat(options.getJsonParser().block()).isInstanceOf(CustomJsonParser.class); } static class CustomJsonParser implements JsonParser { diff --git a/src/test/java/io/lettuce/core/RedisJsonCommandBuilderUnitTests.java b/src/test/java/io/lettuce/core/RedisJsonCommandBuilderUnitTests.java index 3c658ec509..ca17b93bf9 100644 --- a/src/test/java/io/lettuce/core/RedisJsonCommandBuilderUnitTests.java +++ b/src/test/java/io/lettuce/core/RedisJsonCommandBuilderUnitTests.java @@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -39,13 +40,13 @@ class RedisJsonCommandBuilderUnitTests { public static final String ID_BIKE_6 = "{\"id\":\"bike6\"}"; - public static final JsonParser PARSER = DefaultJsonParser.INSTANCE; + public static final JsonParser PARSER = new DefaultJsonParser(); public static final JsonValue ELEMENT = PARSER.createJsonValue(ID_BIKE_6); public static final JsonPath MY_PATH = JsonPath.of("$..commuter_bikes"); - RedisJsonCommandBuilder builder = new RedisJsonCommandBuilder<>(StringCodec.UTF8, PARSER); + RedisJsonCommandBuilder builder = new RedisJsonCommandBuilder<>(StringCodec.UTF8, Mono.just(PARSER)); @Test void shouldCorrectlyConstructJsonArrappend() { diff --git a/src/test/java/io/lettuce/core/json/DefaultJsonParserUnitTests.java b/src/test/java/io/lettuce/core/json/DefaultJsonParserUnitTests.java index 61efa3d25b..b99933fccf 100644 --- a/src/test/java/io/lettuce/core/json/DefaultJsonParserUnitTests.java +++ b/src/test/java/io/lettuce/core/json/DefaultJsonParserUnitTests.java @@ -23,7 +23,7 @@ class DefaultJsonParserUnitTests { void loadJsonValue() { final String unprocessed = "{\"a\":1,\"b\":2}"; - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue jsonValue = parser.loadJsonValue(ByteBuffer.wrap(unprocessed.getBytes())); assertThat(jsonValue).isNotNull(); @@ -35,7 +35,7 @@ void loadJsonValue() { void createJsonValue() { final String unprocessed = "\"someValue\""; - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue jsonValue = parser.createJsonValue(ByteBuffer.wrap(unprocessed.getBytes())); assertThat(jsonValue).isNotNull(); @@ -47,14 +47,14 @@ void createJsonValue() { void createJsonObject() { final String unprocessed = "{\"a\":1,\"b\":2}"; - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue jsonValue = parser.createJsonObject(); assertThat(jsonValue).isNotNull(); assertThat(jsonValue.isJsonObject()).isTrue(); assertThat(jsonValue.asJsonObject().size()).isZero(); - parser = DefaultJsonParser.INSTANCE; + parser = new DefaultJsonParser(); jsonValue = parser.createJsonValue(ByteBuffer.wrap(unprocessed.getBytes())); assertThat(jsonValue).isNotNull(); @@ -72,7 +72,7 @@ void createJsonObject() { @Test void createJsonArray() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue jsonValue = parser.createJsonArray(); assertThat(jsonValue).isNotNull(); @@ -93,7 +93,7 @@ void createJsonArray() { void parsingIssues() { final String unprocessed = "{a\":1,\"b\":2}"; - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); assertThatThrownBy(() -> parser.createJsonValue(unprocessed)).isInstanceOf(RedisJsonException.class); assertThatThrownBy(() -> parser.createJsonValue(ByteBuffer.wrap(unprocessed.getBytes()))) diff --git a/src/test/java/io/lettuce/core/json/DelegateJsonArrayUnitTests.java b/src/test/java/io/lettuce/core/json/DelegateJsonArrayUnitTests.java index f08cc63d90..1b681af0d3 100644 --- a/src/test/java/io/lettuce/core/json/DelegateJsonArrayUnitTests.java +++ b/src/test/java/io/lettuce/core/json/DelegateJsonArrayUnitTests.java @@ -21,7 +21,7 @@ class DelegateJsonArrayUnitTests { @Test void add() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("\"test\"")).add(parser.createJsonValue("\"test2\"")) .add(parser.createJsonValue("\"test3\"")); @@ -37,7 +37,7 @@ void add() { @Test void addCornerCases() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(null).add(parser.createJsonValue("null")).add(parser.createJsonValue("\"test3\"")); @@ -52,7 +52,7 @@ void addCornerCases() { @Test void getCornerCases() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("\"test\"")).add(parser.createJsonValue("\"test2\"")) .add(parser.createJsonValue("\"test3\"")); @@ -63,7 +63,7 @@ void getCornerCases() { @Test void addAll() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray array = new DelegateJsonArray(); array.add(parser.createJsonValue("\"test\"")).add(parser.createJsonValue("\"test2\"")) .add(parser.createJsonValue("\"test3\"")); @@ -83,7 +83,7 @@ void addAll() { @Test void asList() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("1")).add(parser.createJsonValue("2")).add(parser.createJsonValue("3")); @@ -95,7 +95,7 @@ void asList() { @Test void getFirst() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("\"test\"")).add(parser.createJsonValue("\"test2\"")) .add(parser.createJsonValue("\"test3\"")); @@ -107,7 +107,7 @@ void getFirst() { @Test void iterator() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("1")).add(parser.createJsonValue("2")).add(parser.createJsonValue("3")); @@ -120,7 +120,7 @@ void iterator() { @Test void remove() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("1")).add(parser.createJsonValue("2")).add(parser.createJsonValue("3")); @@ -132,7 +132,7 @@ void remove() { @Test void replace() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonArray underTest = new DelegateJsonArray(); underTest.add(parser.createJsonValue("1")).add(parser.createJsonValue("2")).add(parser.createJsonValue("3")); underTest.replace(1, parser.createJsonValue("4")); diff --git a/src/test/java/io/lettuce/core/json/DelegateJsonObjectUnitTests.java b/src/test/java/io/lettuce/core/json/DelegateJsonObjectUnitTests.java index c542a41480..5a9bde49a1 100644 --- a/src/test/java/io/lettuce/core/json/DelegateJsonObjectUnitTests.java +++ b/src/test/java/io/lettuce/core/json/DelegateJsonObjectUnitTests.java @@ -18,7 +18,7 @@ class DelegateJsonObjectUnitTests { @Test void put() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonObject underTest = new DelegateJsonObject(); underTest.put("test", parser.createJsonValue("\"test\"")).put("test2", parser.createJsonValue("1")).put("test2", @@ -31,7 +31,7 @@ void put() { @Test void remove() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); DelegateJsonObject underTest = new DelegateJsonObject(); underTest.put("test", parser.createJsonValue("\"test\"")).put("test2", parser.createJsonValue("1")).remove("test"); diff --git a/src/test/java/io/lettuce/core/json/DelegateJsonValueUnitTests.java b/src/test/java/io/lettuce/core/json/DelegateJsonValueUnitTests.java index 5fab965057..657572f09b 100644 --- a/src/test/java/io/lettuce/core/json/DelegateJsonValueUnitTests.java +++ b/src/test/java/io/lettuce/core/json/DelegateJsonValueUnitTests.java @@ -18,7 +18,7 @@ class DelegateJsonValueUnitTests { @Test void testString() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue underTest = parser.createJsonValue("\"test\""); assertThat(underTest.toString()).isEqualTo("\"test\""); @@ -44,7 +44,7 @@ void testString() { @Test void testNumber() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue underTest = parser.createJsonValue("1"); assertThat(underTest.toString()).isEqualTo("1"); @@ -70,7 +70,7 @@ void testNumber() { @Test void testNumberExtended() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue underTest = parser.createJsonValue("1"); assertThat(underTest.isNumber()).isTrue(); @@ -92,7 +92,7 @@ void testNumberExtended() { @Test void testBoolean() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue underTest = parser.createJsonValue("true"); assertThat(underTest.toString()).isEqualTo("true"); @@ -118,7 +118,7 @@ void testBoolean() { @Test void testNull() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); JsonValue underTest = parser.createJsonValue("null"); assertThat(underTest.toString()).isEqualTo("null"); diff --git a/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java b/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java index 25ea348c76..fbf64bef3d 100644 --- a/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java +++ b/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import reactor.core.publisher.Mono; import java.io.IOException; import java.nio.ByteBuffer; @@ -579,7 +580,7 @@ void withCustomParser() { RedisURI redisURI = RedisURI.Builder.redis("127.0.0.1").withPort(16379).build(); try (RedisClient client = RedisClient.create(redisURI)) { - client.setOptions(ClientOptions.builder().jsonParser(new CustomParser()).build()); + client.setOptions(ClientOptions.builder().jsonParser(Mono.just(new CustomParser())).build()); StatefulRedisConnection connection = client.connect(StringCodec.UTF8); RedisCommands redis = connection.sync(); assertThat(redis.getJsonParser()).isInstanceOf(CustomParser.class); diff --git a/src/test/java/io/lettuce/core/json/UnproccessedJsonValueUnitTests.java b/src/test/java/io/lettuce/core/json/UnproccessedJsonValueUnitTests.java index 369bae1689..1d35326f3f 100644 --- a/src/test/java/io/lettuce/core/json/UnproccessedJsonValueUnitTests.java +++ b/src/test/java/io/lettuce/core/json/UnproccessedJsonValueUnitTests.java @@ -38,7 +38,7 @@ void asString() { final String unprocessed = "{\"a\":1,\"b\":2}"; final String modified = "{\"a\":1}"; - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap(unprocessed.getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); @@ -55,7 +55,7 @@ void asString() { @Test void asTextual() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap("\"textual\"".getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); @@ -72,7 +72,7 @@ void asTextual() { @Test void asNull() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap("null".getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); @@ -88,7 +88,7 @@ void asNull() { @Test void asNumber() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap("1".getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); @@ -105,7 +105,7 @@ void asNumber() { @Test void asBoolean() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap("true".getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); @@ -122,7 +122,7 @@ void asBoolean() { @Test void asArray() { - DefaultJsonParser parser = DefaultJsonParser.INSTANCE; + DefaultJsonParser parser = new DefaultJsonParser(); ByteBuffer buffer = ByteBuffer.wrap("[1,2,3,4]".getBytes()); UnproccessedJsonValue underTest = new UnproccessedJsonValue(buffer, parser); diff --git a/src/test/java/io/lettuce/core/output/JsonValueListOutputUnitTests.java b/src/test/java/io/lettuce/core/output/JsonValueListOutputUnitTests.java index 0406133881..97cbf82759 100644 --- a/src/test/java/io/lettuce/core/output/JsonValueListOutputUnitTests.java +++ b/src/test/java/io/lettuce/core/output/JsonValueListOutputUnitTests.java @@ -22,7 +22,7 @@ class JsonValueListOutputUnitTests { @Test void set() { - JsonValueListOutput sut = new JsonValueListOutput<>(StringCodec.UTF8, DefaultJsonParser.INSTANCE); + JsonValueListOutput sut = new JsonValueListOutput<>(StringCodec.UTF8, new DefaultJsonParser()); sut.multi(2); sut.set(ByteBuffer.wrap("[1,2,3]".getBytes())); sut.set(ByteBuffer.wrap("world".getBytes())); diff --git a/src/test/jmh/io/lettuce/core/dynamic/RedisCommandFactoryBenchmark.java b/src/test/jmh/io/lettuce/core/dynamic/RedisCommandFactoryBenchmark.java index 04085e1d22..83ce325998 100644 --- a/src/test/jmh/io/lettuce/core/dynamic/RedisCommandFactoryBenchmark.java +++ b/src/test/jmh/io/lettuce/core/dynamic/RedisCommandFactoryBenchmark.java @@ -12,6 +12,7 @@ import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.core.codec.StringCodec; import io.lettuce.core.dynamic.batch.BatchSize; +import reactor.core.publisher.Mono; /** * Benchmark for commands executed through {@link RedisCommandFactory}. @@ -31,7 +32,7 @@ public void setup() { redisCommandFactory = new RedisCommandFactory(new MockStatefulConnection(EmptyRedisChannelWriter.INSTANCE)); regularCommands = redisCommandFactory.getCommands(RegularCommands.class); - asyncCommands = new RedisAsyncCommandsImpl<>(EmptyStatefulRedisConnection.INSTANCE, StringCodec.UTF8, DefaultJsonParser.INSTANCE); + asyncCommands = new RedisAsyncCommandsImpl<>(EmptyStatefulRedisConnection.INSTANCE, StringCodec.UTF8, Mono.just(new DefaultJsonParser())); } @Benchmark