diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
index 0e72821a88..e6522168bb 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
@@ -43,8 +43,9 @@ public class ControlSubThread implements Runnable {
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
- // no-op, just loop again
- }
+ Thread.currentThread().interrupt();
+ System.out.println("Thread was interrupted, Failed to complete operation");
+ }
// do something
}
stopped.set(true);
diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml
index b511f0dd7b..2cd5275eeb 100644
--- a/core-kotlin/pom.xml
+++ b/core-kotlin/pom.xml
@@ -44,6 +44,11 @@
kotlin-stdlib
${kotlin-stdlib.version}
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jre8
+ ${kotlin-stdlib.version}
+
org.jetbrains.kotlin
kotlin-test-junit
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/UseTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/UseTest.kt
new file mode 100644
index 0000000000..15bdfcafd8
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/UseTest.kt
@@ -0,0 +1,67 @@
+package com.baeldung.kotlin
+
+import org.junit.Test
+import java.beans.ExceptionListener
+import java.beans.XMLEncoder
+import java.io.*
+import java.lang.Exception
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+class UseTest {
+
+ @Test
+ fun givenCloseable_whenUseIsCalled_thenItIsClosed() {
+ val stringWriter = StringWriter()
+ val writer = BufferedWriter(stringWriter) //Using a BufferedWriter because after close() it throws.
+ writer.use {
+ assertEquals(writer, it)
+
+ it.write("something")
+ }
+ try {
+ writer.write("something else")
+
+ fail("write() should have thrown an exception because the writer is closed.")
+ } catch (e: IOException) {
+ //Ok
+ }
+
+ assertEquals("something", stringWriter.toString())
+ }
+
+ @Test
+ fun givenAutoCloseable_whenUseIsCalled_thenItIsClosed() {
+ val baos = ByteArrayOutputStream()
+ val encoder = XMLEncoder(PrintStream(baos)) //XMLEncoder is AutoCloseable but not Closeable.
+ //Here, we use a PrintStream because after close() it throws.
+ encoder.exceptionListener = ThrowingExceptionListener()
+ encoder.use {
+ assertEquals(encoder, it)
+
+ it.writeObject("something")
+ }
+ try {
+ encoder.writeObject("something else")
+ encoder.flush()
+
+ fail("write() should have thrown an exception because the encoder is closed.")
+ } catch (e: IOException) {
+ //Ok
+ }
+ }
+
+ @Test
+ fun whenSimpleFormIsUsed_thenItWorks() {
+ StringWriter().use { it.write("something") }
+ }
+}
+
+class ThrowingExceptionListener : ExceptionListener {
+ override fun exceptionThrown(e: Exception?) {
+ if(e != null) {
+ throw e
+ }
+ }
+}
\ No newline at end of file
diff --git a/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java b/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java
index 50d35b9b1c..6c7a03cb70 100644
--- a/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java
+++ b/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java
@@ -55,7 +55,7 @@ public class InfluxDBConnectionLiveTest {
InfluxDB connection = connectDatabase();
- // Create "baeldung and check for it
+ // Create "baeldung" and check for it
connection.createDatabase("baeldung");
assertTrue(connection.databaseExists("baeldung"));
diff --git a/persistence-modules/redis/README.md b/persistence-modules/redis/README.md
index d179b80c33..dd655ca7aa 100644
--- a/persistence-modules/redis/README.md
+++ b/persistence-modules/redis/README.md
@@ -1,3 +1,5 @@
### Relevant Articles:
- [Intro to Jedis – the Java Redis Client Library](http://www.baeldung.com/jedis-java-redis-client-library)
- [A Guide to Redis with Redisson](http://www.baeldung.com/redis-redisson)
+- [Intro to Lettuce – the Java Redis Client Library](http://www.baeldung.com/lettuce-java-redis-client-library)
+
diff --git a/persistence-modules/redis/pom.xml b/persistence-modules/redis/pom.xml
index 4321b491eb..1f27faa09a 100644
--- a/persistence-modules/redis/pom.xml
+++ b/persistence-modules/redis/pom.xml
@@ -36,6 +36,13 @@
redisson
3.3.0
+
+
+ io.lettuce
+ lettuce-core
+ 5.0.1.RELEASE
+
+
diff --git a/persistence-modules/redis/src/test/java/com/baeldung/LettuceIntegrationLiveTest.java b/persistence-modules/redis/src/test/java/com/baeldung/LettuceIntegrationLiveTest.java
new file mode 100644
index 0000000000..eb879d1d21
--- /dev/null
+++ b/persistence-modules/redis/src/test/java/com/baeldung/LettuceIntegrationLiveTest.java
@@ -0,0 +1,312 @@
+package com.baeldung;
+
+import io.lettuce.core.LettuceFutures;
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisFuture;
+import io.lettuce.core.TransactionResult;
+import io.lettuce.core.api.StatefulRedisConnection;
+import io.lettuce.core.api.async.RedisAsyncCommands;
+import io.lettuce.core.api.sync.RedisCommands;
+import io.lettuce.core.pubsub.RedisPubSubListener;
+import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
+import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertTrue;
+
+public class LettuceIntegrationLiveTest {
+
+ private static Logger log = LoggerFactory.getLogger(LettuceIntegrationLiveTest.class);
+
+ private static StatefulRedisConnection redisConnection;
+
+ private static RedisClient redisClient;
+
+ @BeforeClass
+ public static void setUp() {
+ // Docker defaults to mapping redis port to 32768
+ redisClient = RedisClient.create("redis://localhost:32768/");
+ redisConnection = redisClient.connect();
+ }
+
+ @AfterClass
+ public static void destroy() {
+ redisConnection.close();
+ }
+
+ @Test
+ public void givenAString_thenSaveItAsRedisStringsSync() {
+
+ RedisCommands syncCommands = redisConnection.sync();
+
+ String key = "key";
+ String value = "value";
+
+ syncCommands.set(key, value);
+ String response = syncCommands.get(key);
+
+ Assert.assertEquals(value, response);
+ }
+
+ @Test
+ public void givenValues_thenSaveAsRedisHashSync() {
+
+ RedisCommands syncCommands = redisConnection.sync();
+
+ String recordName = "record1";
+ String name = "FirstName";
+ String value = "John";
+ String surname = "LastName";
+ String value1 = "Smith";
+
+ syncCommands.hset(recordName, name, value);
+ syncCommands.hset(recordName, surname, value1);
+ Map record = syncCommands.hgetall(recordName);
+
+ Assert.assertEquals(record.get(name), value);
+ Assert.assertEquals(record.get(surname), value1);
+ }
+
+ @Test
+ public void givenAString_thenSaveItAsRedisStringsAsync() throws Exception {
+
+ RedisAsyncCommands asyncCommands = redisConnection.async();
+
+ String key = "key";
+ String value = "value";
+
+ asyncCommands.set(key, value);
+ RedisFuture redisFuture = asyncCommands.get(key);
+
+ String response = redisFuture.get();
+
+ Assert.assertEquals(value, response);
+ }
+
+ @Test
+ public void givenValues_thenSaveAsRedisHashAsync() throws Exception {
+
+ RedisAsyncCommands asyncCommands = redisConnection.async();
+
+ String recordName = "record1";
+ String name = "FirstName";
+ String value = "John";
+ String surname = "LastName";
+ String value1 = "Smith";
+
+ asyncCommands.hset(recordName, name, value);
+ asyncCommands.hset(recordName, surname, value1);
+ RedisFuture