diff --git a/persistence-modules/redis/pom.xml b/persistence-modules/redis/pom.xml index fffcfbb96b..c9206e5f92 100644 --- a/persistence-modules/redis/pom.xml +++ b/persistence-modules/redis/pom.xml @@ -9,16 +9,31 @@ com.baeldung - persistence-modules - 1.0.0-SNAPSHOT + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-redis + + redis.clients jedis - ${jedis.version} - + com.github.kstyrc embedded-redis @@ -32,15 +47,12 @@ io.lettuce lettuce-core - ${lettuce-core.version} - + - - 3.2.0 + 0.6 - 3.3.0 - 5.0.1.RELEASE + 3.3.0 diff --git a/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/RedisConfig.java b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/RedisConfig.java new file mode 100644 index 0000000000..ad43ad8159 --- /dev/null +++ b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/RedisConfig.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.redis.configuration; + +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; + +import com.baeldung.spring.redis.configuration.entity.Book; + +@Configuration +@EnableConfigurationProperties(RedisProperties.class) +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + // Add some specific configuration here. Key serializers, etc. + return template; + } + +} diff --git a/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/SpringRedisConfigurationApplication.java b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/SpringRedisConfigurationApplication.java new file mode 100644 index 0000000000..932a6b7478 --- /dev/null +++ b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/SpringRedisConfigurationApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.redis.configuration; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringRedisConfigurationApplication implements CommandLineRunner { + + public static void main(String[] args) { + SpringApplication.run(SpringRedisConfigurationApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + + } + +} diff --git a/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/controller/BooksController.java b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/controller/BooksController.java new file mode 100644 index 0000000000..b3faf030c9 --- /dev/null +++ b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/controller/BooksController.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.redis.configuration.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.redis.configuration.entity.Book; +import com.baeldung.spring.redis.configuration.repository.BooksRepository; + +@RestController +@RequestMapping("/books") +public class BooksController { + + @Autowired + private BooksRepository repository; + + @PostMapping("/create") + public String newBook(@RequestBody Book newBook) { + repository.save(newBook); + return "Added"; + } + + @GetMapping("/get/{id}") + public Book findOne(@PathVariable Long id) { + return repository.findById(id); + } + +} diff --git a/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/entity/Book.java b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/entity/Book.java new file mode 100644 index 0000000000..52d579d4fb --- /dev/null +++ b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/entity/Book.java @@ -0,0 +1,46 @@ +package com.baeldung.spring.redis.configuration.entity; + +import java.io.Serializable; + +public class Book implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + private String name; + + public Book() { + } + + public Book(String name) { + this.name = name; + } + + public Book(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Book [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/repository/BooksRepository.java b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/repository/BooksRepository.java new file mode 100644 index 0000000000..a6eba0e742 --- /dev/null +++ b/persistence-modules/redis/src/main/java/com/baeldung/spring/redis/configuration/repository/BooksRepository.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.redis.configuration.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import com.baeldung.spring.redis.configuration.entity.Book; + +@Component +public class BooksRepository { + + @Autowired + private RedisTemplate redisTemplate; + + public void save(Book book) { + redisTemplate.opsForValue() + .set(book.getId(), book); + } + + public Book findById(Long id) { + return redisTemplate.opsForValue() + .get(id); + } + +} diff --git a/persistence-modules/redis/src/main/resources/application.properties b/persistence-modules/redis/src/main/resources/application.properties new file mode 100644 index 0000000000..e3140c4e29 --- /dev/null +++ b/persistence-modules/redis/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.redis.database=0 +spring.redis.host=localhost +spring.redis.port=16379 +spring.redis.password=mypass +spring.redis.timeout=60000 +spring.redis.lettuce.pool.max-active=8 +spring.redis.lettuce.pool.max-idle=8 +spring.redis.lettuce.pool.max-wait=-1 +spring.redis.lettuce.pool.min-idle=0 \ No newline at end of file diff --git a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java new file mode 100644 index 0000000000..a5c3340065 --- /dev/null +++ b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.redis.configuration.controller; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.spring.redis.configuration.entity.Book; +import com.baeldung.spring.redis.configuration.repository.BooksRepository; + +@RunWith(SpringJUnit4ClassRunner.class) +public class BooksControllerUnitTest { + + @Spy + @InjectMocks + private BooksController booksController; + + @Mock + private BooksRepository booksRepository; + + private static final Long BOOK_ID = 1l; + private static final Long OTHER_BOOK_ID = 2l; + private static final String BOOK_NAME = "Ulysses"; + private static final String ADDED = "Added"; + + @Test + public void whenNewBook_thenCorrect() { + assertEquals(ADDED, booksController.newBook(new Book(BOOK_ID, BOOK_NAME))); + } + + @Test + public void whenFindOneFinds_thenCorrect() { + Book book = new Book(BOOK_ID, BOOK_NAME); + when(booksRepository.findById(BOOK_ID)).thenReturn(book); + assertSame(book, booksController.findOne(BOOK_ID)); + } + + @Test + public void whenFindOneNotFound_thenReturnsNull() { + Book book = new Book(BOOK_ID, BOOK_NAME); + when(booksRepository.findById(BOOK_ID)).thenReturn(book); + assertNull(booksController.findOne(OTHER_BOOK_ID)); + } + +} diff --git a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java new file mode 100644 index 0000000000..1edf9c7e89 --- /dev/null +++ b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.spring.redis.configuration.repository; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.spring.redis.configuration.entity.Book; + +@RunWith(SpringJUnit4ClassRunner.class) +public class BooksRepositoryUnitTest { + + @Spy + @InjectMocks + private BooksRepository booksRepository; + + @Mock + private RedisTemplate redisTemplate; + + @Mock + private ValueOperations valueOperations; + + private static final Long BOOK_ID = 1l; + private static final Long OTHER_BOOK_ID = 2l; + private static final String BOOK_NAME = "Ulysses"; + + @Test + public void whenSave_thenCorrect() { + Book book = new Book(BOOK_ID, BOOK_NAME); + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + booksRepository.save(book); + verify(redisTemplate, times(1)).opsForValue(); + verify(valueOperations, times(1)).set(BOOK_ID, book); + } + + @Test + public void whenFindByIdFound_thenReturnsBook() { + Book book = new Book(BOOK_ID, BOOK_NAME); + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + when(valueOperations.get(BOOK_ID)).thenReturn(book); + assertSame(book, booksRepository.findById(BOOK_ID)); + verify(redisTemplate, times(1)).opsForValue(); + verify(valueOperations, times(1)).get(BOOK_ID); + } + + @Test + public void whenFindByIdNotFound_thenReturnsNull() { + Book book = new Book(BOOK_ID, BOOK_NAME); + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + when(valueOperations.get(BOOK_ID)).thenReturn(book); + assertNull(booksRepository.findById(OTHER_BOOK_ID)); + verify(redisTemplate, times(1)).opsForValue(); + verify(valueOperations, times(1)).get(OTHER_BOOK_ID); + } + +}