EzyRedis Introduction

1. Introduce EzyRedis

EzyRedis (Easy going to Redis Interaction) is a framework support to interact to Redis, It supports:
  1. Interacts to HMAP
  2. Pub/Sub message
  3. Serialize/Deserialize between byte array and POJO
  4. Annotation driven

2. Structure of EzyRedis

  1. Redis proxy: wraps redis client object like Jedis
  2. Map proxy: wraps hget, hset, hdel .. functions
  3. Atomic Long proxy: wraps hincrBy function
  4. Message Channel: wraps publish/subscribe functions

3. Install EzyRedis

1. To create EzyRedis we need add dependency
<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezydata-redis</artifactId>
    <version>1.2.5</version>
</dependency>
The latest version can be found in the Maven Central repository.
2. To use EzyRedis you need config to create repositories
You can use ezyfox-boot-autoconfigure by add to your pom.xml:
<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyfox-boot-autoconfigure</artifactId>
    <version>1.0.7</version>
</dependency>
Or because with some reason, you can not use ezyfox-boot-autoconfigure you can config like this:
import com.tvd12.ezydata.redis.EzyRedisClientPool;
import com.tvd12.ezydata.redis.EzyRedisProxy;
import com.tvd12.ezydata.redis.EzyRedisProxyFactory;
import com.tvd12.ezydata.redis.loader.EzyJedisClientPoolLoader;
import com.tvd12.ezyfox.bean.EzyBeanAutoConfig;
import com.tvd12.ezyfox.bean.EzySingletonFactory;
import com.tvd12.ezyfox.bean.EzySingletonFactoryAware;
import com.tvd12.ezyfox.bean.annotation.EzyConfigurationBefore;
import com.tvd12.ezyfox.util.EzyPropertiesAware;
import lombok.Setter;

import java.util.Properties;
import java.util.Set;

@Setter
@EzyConfigurationBefore
public class EzyRedisConfiguration implements
    EzyBeanConfig,
    EzyPropertiesAware,
    EzySingletonFactoryAware {

    private Properties properties;
    private EzySingletonFactory singletonFactory;

    @Override
    public void autoConfig() {
        singletonFactory.addSingleton("redisProxy", newRedisProxy());
    }

    private EzyRedisProxy newRedisProxy() {
        return EzyRedisProxyFactory.builder()
            .properties(properties)
            .scan("your packages to scan")
            .clientPool(newClientPool())
            .build()
            .newRedisProxy();
    }

    protected EzyRedisClientPool newClientPool() {
        return new EzyJedisClientPoolLoader()
            .properties(properties)
            .load();
    }
}
3. You can add to your configuration file like this:
# for application.yaml
redis:
  uri: redis://localhost:6379/
  map_naming:
    case: CAMEL
    ingored_suffix: Entity
# for application.properties
redis.uri=redis://localhost:6379/
redis.map_naming.case=CAMEL
redis.map_naming.ingored_suffix=Entity

4. Example

Let’s say we need create an http server application to manage a book store (Category, Author and Book), we need 6 apis
  • api/v1/author/add: Add an author
  • api/v1/category/add: Add a category
  • api/v1/book/add: Add a book
  • api/v1/books/{bookId}: Get a book by id
  • api/v1/books: Get a list of books
  • apiv1/books/expected-revenue:
4.1 Create data classes
To store Category, Author and Book to Redis, we need create 3 data classes
import com.tvd12.ezyfox.data.annotation.EzyCachedKey;
import com.tvd12.ezyfox.data.annotation.EzyCachedValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@EzyCachedValue
@NoArgsConstructor
@AllArgsConstructor
public class Category {
    @EzyCachedKey
    private Long id;
    private String name;
}

@Getter
@Setter
@EzyCachedValue
@AllArgsConstructor
@NoArgsConstructor
public class Author {
    @EzyCachedKey
    private long id;
    private String name;
}

@Getter
@Setter
@EzyCachedValue
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    @EzyCachedKey
    private Long id;
    private Long categoryId;
    private Long authorId;
    private String name;
    private BigDecimal price;
    private LocalDate releaseDate;
    private LocalDateTime releaseTime;
}
4.2 Use Atomic Long and Map to create an author
Let's say we need need create author with increment long Id, we can implement APIs for author like this:
import com.tvd12.ezydata.example.redis.entity.Author;
import com.tvd12.ezydata.example.redis.request.AddAuthorRequest;
import com.tvd12.ezydata.redis.EzyRedisAtomicLong;
import com.tvd12.ezydata.redis.EzyRedisProxy;
import com.tvd12.ezyhttp.server.core.annotation.Controller;
import com.tvd12.ezyhttp.server.core.annotation.DoPost;
import com.tvd12.ezyhttp.server.core.annotation.RequestBody;

import java.util.Map;

@Controller("/api/v1/author")
public class AuthorController {

    private final EzyRedisAtomicLong idGentor;
    private final Map<Long, Author> authorMap;

    public AuthorController(EzyRedisProxy redisProxy) {
        this.idGentor = redisProxy.getAtomicLong("author");
        this.authorMap = redisProxy.getMap("author");
    }

    @DoPost("/add")
    public Author addAuthor(@RequestBody AddAuthorRequest request) {
        Author author = new Author(
            idGentor.incrementAndGet(),
            request.getAuthorName()
        );
        authorMap.put(author.getId(), author);
        return author;
    }
}
You can see everything's simple, you just need redisProxy.getAtomicLong("author") to get an AtomicLong and redisProxy.getMap("author") to get a map. Further, you can put a java object to the map and EzyRedis will serialize it to byte array and put the byte array to Redis for you.
You you want to get an author by id, you just need use the get method with the author id:
Author author = authorMap.get(request.getAuthorId());
Full source code available on Github

5. Message channel usage

Let's say you want to publish/consume a message in a chat system like this: {"message": "message value"}. Now you will need a class like this:
import com.tvd12.ezyfox.message.annotation.EzyMessage;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@EzyMessage(channel = "ezydata_chat_message")
public class ChatMessage {
    private String message;
}
To subscribe the ezydata_chat_message you can do like this:
EzyRedisChannel<ChatMessage> subscribeChannel = redisProxy1.getChannel("ezydata_chat_message", ChatMessage.class)
subcribeChannel.addSubscriber(m -> System.out.println("received message: " + m));
To publish a message to the ezydata_chat_message channel, you can do like this:
EzyRedisChannel<ChatMessage> publishChannel = redisProxy2.getChannel("ezydata_chat_message", ChatMessage.class)
publishChannel.publish(new ChatMessage("Hello World"));

6. Conclusion

With EzyRedis you will work with Redis lot easier and more native. With query string, you will don't need care about bson, criteria and you will reduce a lot of your source code