I am facing a problem with connecting to two different Redis databases in the scope of the same instance. My Redis configuration class looks like this:
package com.application.apigateway.intrastructure.cache;
import java.time.Duration;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {
private static final String REDIS_PROPERTIES = "redis.properties";
private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.timeout}")
private String timeout;
@Bean(name = "redisUserConnectionFactory")
public JedisConnectionFactory redisUserConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String userDb = getProperty(redisProperties, "redis.user.cache.database");
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(Integer.parseInt(userDb));
redisConfiguration.setPassword(RedisPassword.of(password));
JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofMillis(Long.parseLong(timeout)));
log.info(
"Connected to Redis host: {}, port: {}, database: {}",
redisConfiguration.getHostName(),
redisConfiguration.getPort(),
redisConfiguration.getDatabase());
return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration.build());
}
@Bean(name = "userRedisTemplate")
public RedisTemplate<String, Object> userRedisTemplate(
@Qualifier(value = "redisUserConnectionFactory")
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean(name = "redisRegistrationTokenConnectionFactory")
public JedisConnectionFactory redisRegistrationTokenConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String registrationTokenDb =
getProperty(redisProperties, "redis.registration.token.cache.database");
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(Integer.parseInt(registrationTokenDb));
redisConfiguration.setPassword(RedisPassword.of(password));
JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofMillis(Long.parseLong(timeout)));
log.info(
"Connected to Redis host: {}, port: {}, database: {}",
redisConfiguration.getHostName(),
redisConfiguration.getPort(),
redisConfiguration.getDatabase());
return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration.build());
}
@Bean(name = "registrationTokenRedisTemplate")
public RedisTemplate<String, Object> registrationTokenRedisTemplate(
@Qualifier(value = "redisRegistrationTokenConnectionFactory")
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
and
pom.xml
looks like:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/>
</parent>
<groupId>com.Application</groupId>
<artifactId>ApiGateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ApiGateway</name>
<description>Application - ApiGateway</description>
<properties>
<java.version>15</java.version>
<apache.common.math.version>3.6.1</apache.common.math.version>
<guava.version>28.1-jre</guava.version>
<h2.version>1.4.200</h2.version>
<hamcrest.version>2.1</hamcrest.version>
<http.client.version>4.5.9</http.client.version>
<junit.jupiter.version>5.3.2</junit.jupiter.version>
<junit.surefire.version>1.1.0</junit.surefire.version>
<lombok.version>1.18.20</lombok.version>
<mapstruct.version>1.3.0.Final</mapstruct.version>
<maven.compiler.version>3.8.0</maven.compiler.version>
<mockito.junit.jupiter.version>2.23.0</mockito.junit.jupiter.version>
<mysql.driver.version>8.0.18</mysql.driver.version>
<pdf.box.version>2.0.16</pdf.box.version>
<postgres.driver.version>42.2.8</postgres.driver.version>
<spring.security.version>5.2.0.RELEASE</spring.security.version>
<aws.sdk.version>1.11.870</aws.sdk.version>
<commons.lang.version>2.6</commons.lang.version>
<spring.boot.configuration.processor.version>2.2.6.RELEASE
</spring.boot.configuration.processor.version>
<json-smart.version>2.3</json-smart.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-boot-starter-redis.version>2.5.0</spring-boot-starter-redis.version>
<redis.version>3.7.0</redis.version>
<spring-cloud-starter-netflix-zuul.version>2.2.9.RELEASE</spring-cloud-starter-netflix-zuul.version>
<spring-cloud-starter-eureka-client.version>3.0.3</spring-cloud-starter-eureka-client.version>
<nimbus-jose-jwt>9.11.1</nimbus-jose-jwt>
<maven-plugin-version>2.5.5</maven-plugin-version>
</properties>
<dependencies>
<!-- SPRING STARTERS -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>${spring-cloud-starter-eureka-client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>${spring-cloud-starter-netflix-zuul.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot-starter-redis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring.boot.configuration.processor.version}</version>
</dependency>
<!-- SPRING -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- OTHERS -->
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbus-jose-jwt}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>${apache.common.math.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${http.client.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${pdf.box.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>${json-smart.version}</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${redis.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-cognitoidp</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<!-- DB -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.driver.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.driver.version}</version>
<scope>runtime</scope>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring.security.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${maven-plugin-version}</version>
</plugin>
</plugins>
</build>
</project>
While the application starts I am receiving:
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'redisTemplate' that could not be found.
Action:
Consider defining a bean named 'redisTemplate' in your configuration.
I am a little bit confused because I created two separated RestTemplate
beans and it still doesn't bring a desirable effect. I will be grateful for suggestions on how to fix this problem.
I have found a solution, namely:
spring-boot-starter-data-redis
to version 2.5.4RedisTemplate
and JedisConnectionFactory
beansMy RedisConfiguration
class looks like below:
@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {
private static final String REDIS_PROPERTIES = "redis.properties";
private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.timeout}")
private String timeout;
@Bean(name = "jedisConnectionFactory")
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(
@Qualifier(value = "jedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringRedisSerializer());
template.setValueSerializer(stringRedisSerializer());
return template;
}
@Bean(name = "redisUserConnectionFactory")
public JedisConnectionFactory redisUserConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String userDb = getProperty(redisProperties, RedisDb.USER_DB);
setRedisProperties(redisConfiguration, userDb);
JedisClientConfiguration jedisClientConfiguration =
JedisClientConfiguration.builder()
.connectTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration);
return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration);
}
@Bean(name = "userRedisTemplate")
public RedisTemplate<String, Object> userRedisTemplate(
@Qualifier(value = "redisUserConnectionFactory")
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringRedisSerializer());
template.setValueSerializer(stringRedisSerializer());
return template;
}
@Bean(name = "redisRegistrationTokenConnectionFactory")
public JedisConnectionFactory redisRegistrationTokenConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String registrationTokenDb = getProperty(redisProperties, RedisDb.REGISTRATION_TOKEN_DB);
setRedisProperties(redisConfiguration, registrationTokenDb);
JedisClientConfiguration jedisClientConfiguration =
JedisClientConfiguration.builder()
.connectTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration);
return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration);
}
@Bean(name = "registrationTokenRedisTemplate")
public RedisTemplate<String, Object> registrationTokenRedisTemplate(
@Qualifier(value = "redisRegistrationTokenConnectionFactory")
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringRedisSerializer());
template.setValueSerializer(stringRedisSerializer());
return template;
}
@Bean(name = "stringRedisSerializer")
public StringRedisSerializer stringRedisSerializer() {
return new StringRedisSerializer();
}
private void setRedisProperties(RedisStandaloneConfiguration redisConfiguration, String redisDb) {
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(Integer.parseInt(redisDb));
redisConfiguration.setPassword(RedisPassword.of(password));
}
private void logRedisConnectionDetails(RedisStandaloneConfiguration redisConfiguration) {
log.info(
"Connected to Redis host: {}, port: {}, database: {}",
redisConfiguration.getHostName(),
redisConfiguration.getPort(),
redisConfiguration.getDatabase());
}
}
This approach resolved a problem.