Spring Redis Cache Service on Heroku


1. Setup Heroku RedisConnectionFactory Configuration
2. Setup RedisTemplate Configuration
3. Setup Redis Service
4. Setup Redis Controller

1. Setup Heroku RedisConnectionFactory Configuration

package com.example.redis;

import java.net.URI;
import java.net.URISyntaxException;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

import redis.clients.jedis.Protocol;

@Configuration
@Profile("default")
public class LocalRedisConfiguration {
	
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
    	
		try {
			URI redisUri = new URI(System.getenv("REDISCLOUD_URL"));
			JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
			redisConnectionFactory.setHostName(redisUri.getHost());
			redisConnectionFactory.setPort(redisUri.getPort());
			redisConnectionFactory.setTimeout(Protocol.DEFAULT_TIMEOUT);
			redisConnectionFactory.setPassword(redisUri.getUserInfo().split(":",2)[1]);
			
        return redisConnectionFactory;
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
    }
}

2. Setup RedisTemplate Configuration

package com.example.redis;

import javax.inject.Inject;

import org.springframework.context.annotation.*;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@Import({LocalRedisConfiguration.class})
public class RedisConfiguration {
	
	@Inject private RedisConnectionFactory redisConnectionFactory;
	
    @Bean
    public Topic topic() {
        return new ChannelTopic("pubsub:customer");
    }

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(Topic topic, RedisConnectionFactory redisConnectionFactory, TaskExecutor taskExecutor) {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setTaskExecutor(taskExecutor);
        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
        redisMessageListenerContainer.addMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message, byte[] pattern) {
                System.out.println("Received notification " + new String(message.getBody()) + ".");
                System.out.println(new String(pattern));
            }
        }, topic);
        return redisMessageListenerContainer;
    }

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setQueueCapacity(1);
        taskExecutor.setCorePoolSize(10);
        return taskExecutor;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() throws Exception {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}

3. Setup Redis Service

package com.example.redis;

import com.example.service.CustomerService;
import com.example.model.Customer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.*;

@Service
public class RedisCustomerService implements CustomerService {

	@Autowired
	private RedisTemplate<String, Object> redisTemplate; 

    private String uniqueIdKey = "customerId";
 
    private BigInteger uniqueId() {
        long uniqueId = this.redisTemplate.opsForValue().increment(uniqueIdKey, 1);
        return BigInteger.valueOf(uniqueId);
    }
   
    private String lastNameKey(BigInteger id) {
        return "customer:ln:" + id;
    }

    private String firstNameKey(BigInteger id) {
        return "customer:fn:" + id;
    }

    public Collection<Customer> loadAllCustomers() {
        String keyPattern = "customer:fn:*";
        Set<String> keys = redisTemplate.keys(keyPattern);
        Set<Customer> customerSet = new HashSet<Customer>();
        for (String firstNameKey : keys) {
            long id = Long.parseLong(firstNameKey.split(":")[2]);
            customerSet.add(this.getCustomerById(BigInteger.valueOf(id)));
        }
        return customerSet;
    }

	@Override
	public Customer updateCustomer(BigInteger id, String fn, String ln) {
		 this.redisTemplate.opsForValue().set(lastNameKey(id), ln);
	     this.redisTemplate.opsForValue().set(firstNameKey(id), fn);
	     return getCustomerById(id);
	}

	@Override
	public List<Customer> updateCustomers(List<Customer> customersToUpdate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Customer getCustomerById(BigInteger id) {
		String ln = (String) this.redisTemplate.opsForValue().get(lastNameKey(id));
	    String fn = (String) this.redisTemplate.opsForValue().get(firstNameKey(id));
	    return new Customer(id, fn, ln);
	}

	@Override
	public Collection<Customer> getAllCustomers() {
		 String keyPattern = "customer:fn:*";
	        Set<String> keys = redisTemplate.keys(keyPattern);
	        Set<Customer> customerSet = new HashSet<Customer>();
	        for (String firstNameKey : keys) {
	            long id = Long.parseLong(firstNameKey.split(":")[2]);
	            customerSet.add(this.getCustomerById(BigInteger.valueOf(id)));
	        }
	      return customerSet;
	}

	@Override
	public void deleteCustomer(BigInteger id) {
		redisTemplate.opsForValue().getOperations().delete(String.valueOf(id));
	}
	

	@Override
	public int getTotalRecords() {
		return redisTemplate.keys("customer:fn:*").size();
	}

	 private void setCustomerValues(BigInteger lid, String fn, String ln) {
	        this.redisTemplate.opsForValue().set(lastNameKey(lid), ln);
	        this.redisTemplate.opsForValue().set(firstNameKey(lid), fn);
	 }
	
	@Override
	public Customer createCustomer(String fn, String ln) {
		BigInteger lid = uniqueId();
        setCustomerValues(lid, fn, ln);
        return getCustomerById(lid);
	}
}

4. Setup Redis Controller

package com.example.controller;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Map;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.example.redis.RedisCustomerService;

@Controller
@RequestMapping("/redis")
public class RedisController {

	@Autowired
	RedisCustomerService redisCustomerService;
	
	@RequestMapping("")
	public String redisView(Map<String, Object> map){
		map.put("redisCustomerList", redisCustomerService.getAllCustomers());
		return "redis";
	}
	
	@RequestMapping(value="/insert")
	public String insertCustomersView(){
		return "insertredis";
	}
	
	@RequestMapping(value="/insert", method=RequestMethod.POST)
	public String insertCustomers(Map<String, Object> map, @RequestParam("firstName") String firstName, @RequestParam("lastName") String lastName) {
		redisCustomerService.createCustomer(firstName, lastName);
		return "redis";
	}
	
	@RequestMapping(value="/delete/{id}", method=RequestMethod.POST)
	public String deleteCustomer(@PathVariable("id") String id, Map<String, Object> map){
		redisCustomerService.deleteCustomer(new BigInteger(id));
		map.put("redisCustomerList", redisCustomerService.getAllCustomers());
		return "redis";
	}
	
	@RequestMapping(value="/update/{id}", method=RequestMethod.GET)
	public String updateCustomerView(@PathVariable("id") String id, Map<String, Object> map){
		map.put("redisupdate", Arrays.asList(redisCustomerService.getCustomerById(new BigInteger(id))));
		return "updateredis";
	}
	
	@RequestMapping(value="/update/{id}", method=RequestMethod.POST)
	public String updateCustomer(@PathVariable("id") String id, Map<String, Object> map, @RequestParam("firstName") String firstName, @RequestParam("lastName") String lastName){
		redisCustomerService.updateCustomer(new BigInteger(id), firstName, lastName);
		map.put("redisCustomerList", redisCustomerService.getAllCustomers());
		return "redis";
	}
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: