Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringBoot Redis remote host

I'm making an application that uses Spring Boot, MySQL and Redis on the Back End and Angular on the Front End. I want to deploy it to Heroku so I could use my front end with it but I just can't seem to configure the remote URL for Redis. I have the Redis To Go Add-on on Heroku for this with the remote URL ready. I just don't know how to configure the environment variables to access that instead of localhost and the default port 6379.

I added the following lines to my application.properties but it still did not work :

spring.redis.url= #URL
spring.redis.host= #HOSTNAME
spring.redis.password= #PASSWORD
spring.redis.port = #PORT

I keep getting the following error :

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis on localhost:6379; nested exception is com.lambdaworks.redis.RedisConnectionException: Unable to connect to localhost/127.0.0.1:6379

Is there any way I could configure this to access the remote url instead of localhost?

I'm using Lettuce and not Jedis and my HttpSessionConfig file is :

@EnableRedisHttpSession
public class HttpSessionConfig {

    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }

}
like image 513
Sarthak Sachdeva Avatar asked Aug 19 '18 06:08

Sarthak Sachdeva


3 Answers

I was having a similar issue, this is how I solved it:

If you define the bean this way:

@Bean
public LettuceConnectionFactory connectionFactory() {
    return new LettuceConnectionFactory();
}

You are not allowing Spring to take the Redis values from the application.properties.

To make it work, please do the following:

  1. Remove this bean definition:
@Bean
public LettuceConnectionFactory connectionFactory() {
    return new LettuceConnectionFactory();
}
  1. Define the RedisTemplate bean this way:
@Bean
public RedisTemplate<String, Object> deliveryRedisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    return template;
}
  1. Define the following values in application.properties:
spring.redis.database=<replace-me>
spring.redis.host=<replace-me>
spring.redis.port=<replace-me>
spring.redis.timeout=<replace-me>
like image 109
Julian Avatar answered Nov 06 '22 09:11

Julian


I was frustrated with the exact same issue you are facing and the spring boot documentation or examples do nothing to address what we are facing. The reason why your config entries are not being used is because you are creating a new instance of LettuceConnectionFactory with a parameter-less constructor. Digging into the source/byte code you can see that constructor is completely ignoring the spring.redis.host and spring.redis.port values and hardcoding them to localhost:6379.

What you should be doing is either:

  • Use the LettuceConnectionFactory(hostname, port) constructor.
  • Don't define the connection factory. Get rid of the entire @Bean entry for connectionFactory() and Spring will automatically wire everything up and use your config entries.

Also as a side note; to get this working with AWS Elasticache (locally via VPN) I had to add to that config class:

@Bean
public static ConfigureRedisAction configureRedisAction() {
    return ConfigureRedisAction.NO_OP;
}
like image 5
PeterO Avatar answered Nov 06 '22 07:11

PeterO


I found the Heroku documentation for connecting to their Redis add-on (https://devcenter.heroku.com/articles/heroku-redis#connecting-in-java) contains an example using Jedis and therefore needed a little adaption. The content of the REDIS_URL added by Heroku to the environment of your running app resembles

redis://h:credentials@host:port

I parsed this using RedisURI.create and then set the host, port and password parameters of RedisStandaloneConfiguration

val uri = RedisURI.create(configuration.redisUrl)
val config = RedisStandaloneConfiguration(uri.host, uri.port)
config.setPassword(uri.password)
return LettuceConnectionFactory(config)

The code above is Kotlin rather than Java but perhaps it will help? You can find the full code at https://github.com/DangerousDarlow/springboot-redis

like image 2
SuperMe Avatar answered Nov 06 '22 07:11

SuperMe