Over a million developers have joined DZone.

Spring Data & Redis

· Java Zone

Navigate the Maze of the End-User Experience and pick up this APM Essential guide, brought to you in partnership with CA Technologies

This article will cover the following topics:


  1. How to install Redis on a *nix machine.
  2. How to write a simple app using Spring-Data and Redis.

Before moving forward let's understand what Redis is.

Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.

In this article I'm not going to talk how fast is redis and how it works. But believe me it's a very fast key-value store.

Now let's install redis on *nix machine

wget http://redis.googlecode.com/files/redis-2.4.8.tar.gz
tar xzf redis-2.4.8.tar.gz
cd redis-2.4.8
make

src/redis-server

That's all! Your redis is ready to use.

Now let's create a simple maven application to work with redis.

 Currently Spring Redis has support for Jedis and JRedis (Jedis and JRedis are Redis bindings for Java).

 In this article we are going to use Jedis. Here are the Maven dependencies:

<!-- Redis Java Binding-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.0.0</version>
</dependency>

<!-- Spring Data Redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
     <version>1.0.0.RELEASE</version>
</dependency>

You can find the full application on GitHub here: spring-data-redis example

Now let's define and configure our beans:

<!-- redis conection factory -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true" p:host-name="${app.config.redis.host}" p:port="${app.config.redis.port}" p:password="${app.config.redis.password}"/>

<!-- redis template -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="connectionFactory"/>

<!-- redis string template -->
<bean id="redisStringTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
p:connection-factory-ref="connectionFactory"/>

<!-- redis map binding -->
<bean id="userRedisMap" class="org.springframework.data.redis.support.collections.DefaultRedisMap">
    <constructor-arg ref="redisTemplate"/>
    <constructor-arg value="USER"/>
</bean>

RedisTemplate provides high level abstraction for redis operations. If your application stores and retrieves strings, then you may use StringRedisTemplate.

Let's create a simple domain object.

public interface Cachable extends Serializable {

    public String getKey();

    public String getObjectKey();
}

public class User implements Cachable {

    private static final long serialVersionUID = -7898194272883238670L;

    public static final String OBJECT_KEY = "USER";

    public User() {
    }

    public User(String id) {
    }

    public User(String id, String name) {
       this.id = id;
       this.name = name;
    }

    private String id;

    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + "]";
    }

    @Override
    public String getKey() {
        return getId();
    }

    @Override
    public String getObjectKey() {
        return OBJECT_KEY;
    }
}

Now let's create Service layer classes.

public interface Service<V extends Cachable> {

    public void put(V obj);

    public V get(V key);

    public void delete(V key);
}

@Service("userService")
public class UserService implements co.sdr.service.Service<User> {

    @Autowired
    RedisTemplate<String, Cachable> redisTemplate;

    @Override
    public void put(User user) {
        redisTemplate.opsForHash().put(user.getObjectKey(), user.getKey(), user);
    }

    @Override
    public void delete(User key) {
        redisTemplate.opsForHash().delete(key.getObjectKey(), key.getKey());
    }

    @Override
    public User get(User key) {
        return (User) redisTemplate.opsForHash().get(key.getObjectKey(), key.getKey());
    }
}

So domain and service classes are ready. Now let's use them.

Here is the simple Main class which uses the above-mentioned classes.

public class Main
{
    public static void main( String[] args )
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("springapp.xml");
    
        @SuppressWarnings("unchecked")
        Service<User> userService = (Service<User>)context.getBean("userService");
        
        User user1 = new User("user1ID", "User 1");
        User user2 = new User("user2ID", "User 2");
        
        System.out.println("==== getting objects from redis ====");
        System.out.println("User is not in redis yet: " + userService.get(user1));
        System.out.println("User is not in redis yet: " + userService.get(user2));
        
        System.out.println("==== putting objects into redis ====");
        userService.put(user1);
        userService.put(user2);
        
        System.out.println("==== getting objects from redis ====");
        System.out.println("User should be in redis yet: " + userService.get(user1));
        System.out.println("User should be in redis yet: " + userService.get(user2));
        
        System.out.println("==== deleting objects from redis ====");
        userService.delete(user1);
        userService.delete(user2);
        
        System.out.println("==== getting objects from redis ====");
        System.out.println("User is not in redis yet: " + userService.get(user1));
        System.out.println("User is not in redis yet: " + userService.get(user2));

    }
}

Wasn't it simple? Spring makes everything much more easy to use.

And this isn't the end. spring-data-redis's org.springframework.data.redis.support package provides List, Set, Map implemetations.

Let's try to use a map:

@Service("userMapService")
public class UserMapService implements co.sdr.service.Service<User> {

    @Autowired
    Map<String, Cachable> userRedisMap;

    @Override
    public void put(User user) {
        userRedisMap.put(user.getKey(), user);
    }

   @Override
   public void delete(User key) {
       userRedisMap.remove(key.getKey());
   }

    @Override
    public User get(User key) {
        return (User) userRedisMap.get(key.getKey());
    }
}

This may help you with unit testing, and you may change the datastore without the changing service layer.

You may also use RedisCacheManager as a backing implementation for spring cache abstraction.

Find the full version of this application on GitHub here:  spring-data-redis example

Thrive in the application economy with an APM model that is strategic. Be E.P.I.C. with CA APM.  Brought to you in partnership with CA Technologies.

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}