12

I want to use RedisTemplate on spring boot. I can use StringRedeisTemplate successfully, but when i cant use RedisTemplate . here is the code.

@Service
public class MyService {

    @Autowired
    private RedisTemplate<String, Long> template;

    public void execute() {
        template.opsForValue().set("hoge", 1l);
    }
}

But, when start apps, get errors.

> Exception in thread "main"
> org.springframework.beans.factory.BeanCreationException: Error
> creating bean with name 'MyService': Injection of autowired
> dependencies failed; nested exception is
> org.springframework.beans.factory.BeanCreationException: Could not
> autowire field: private
> org.springframework.data.redis.core.RedisTemplate
> org.hoge.service.MyService.template; nested exception is
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
>   at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
>   at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)
>   at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
>   at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
>   at
> org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
>   at
> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
>   at
> org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
>   at
> org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
>   at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
>   at
> org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
>   at
> org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
>   at
> org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
>   at
> org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
>   at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
>   at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
>   at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
>   at
> jp.bizreach.davide.recommend.application.DavimendApplication.main(DavimendApplication.java:11)
>   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>   at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>   at java.lang.reflect.Method.invoke(Method.java:483)     at
> com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
> Caused by: org.springframework.beans.factory.BeanCreationException:
> Could not autowire field: private
> org.springframework.data.redis.core.RedisTemplate
> org.hoge.service.MyService.template; nested exception is
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
>   at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:558)
>   at
> org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
>   at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
>   ... 21 more Caused by:
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
>   at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
>   at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
>   at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
>   at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:530)
>   ... 23 more
Ken de Guzman
  • 2,790
  • 1
  • 19
  • 33
yo_nas
  • 125
  • 1
  • 1
  • 7

4 Answers4

13

The stacktrace suggest that you haven't defined the Bean which you will like to use for injecting in RedisTemplate.You can resolve it creating a configuration file, E.g.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class AppConfig {
 @Bean
 JedisConnectionFactory jedisConnectionFactory() {
  return new JedisConnectionFactory();
 }

 @Bean
 RedisTemplate< String, Long > redisTemplate() {
  final RedisTemplate< String, Long > template =  new RedisTemplate< String, Long >();
  template.setConnectionFactory( jedisConnectionFactory() );
  template.setKeySerializer( new StringRedisSerializer() );
  template.setHashValueSerializer( new GenericToStringSerializer< Long >( Long.class ) );
  template.setValueSerializer( new GenericToStringSerializer< Long >( Long.class ) );
  return template;
 }
}

Once you have the configuration file then you need to pass it to SpringApplication.run E.g.

Object[] sources = {AppConfig.class};
ApplicationContext ctx = SpringApplication.run(sources, args);
sol4me
  • 15,233
  • 5
  • 34
  • 34
  • Thank you very much for your reply. I created config file, then I can use RedisTemplate. – yo_nas Dec 18 '14 at 00:01
  • Thanks! but why have to add an independent jedisConnectionFactory bean, why not could just `template.setConnectionFactory( new JedisConnectionFactory() );` – zhuguowei Mar 12 '16 at 13:26
  • @zhuguowei If you ll not like to use/autowire ```JedisConnectionFactory``` in many places , then feel free to inline it – sol4me Apr 06 '16 at 11:10
  • @sol4me, could I configure bean in applicationContext.xml? I did that, but it did not work. Could you help to have a look at my issue which is configure in xml? The link is https://stackoverflow.com/questions/47449006/spring-boot-redistemplate-autoconfiguration-failed/47449147#47449147 – Jared Nov 23 '17 at 06:59
4

If you use Spring boot, add a dependency to spring-boot-starter-redis, which will bring in the redisTemplate bean. However, that bean is of type RedisTemplate<Object, Object>,

So create another bean for the operations that you need, as shown here enter link description here

nsdiv
  • 912
  • 12
  • 30
3

Give something different, as now is 2018(something changes a lot which blocks me for a long time)

  • First Dependency (Gradle)

    compile('org.springframework.boot:spring-boot-starter-data-redis')
    compile('org.springframework.boot:spring-boot-starter-data-redis-reactive')
    

Remember to use the latest version, you can use gradle-use-latest-versions-plugin to check whether the dependency is latest.

  1. RedisServer

    [Linux] 
    redis-server
    
    [spring.properties]
    spring.redis.host=localhost
    spring.redis.port=6379
    spring.cache.cache-names=orderIdPool,users
    spring.cache.redis.cache-null-values=true
    spring.cache.redis.time-to-live=600000ms
    
  2. Redis config

    @Configuration
    public class RedisConfig {
    
    /**
     * create a lettuceConnectionFactory for redisTemplate {@link 
     #redisUserTemplate()}
     * @return LettuceConnectionFactory, the old version use Jedis
    */
    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {
        return new LettuceConnectionFactory();
    }
    
    /**
     * Description: aiming to create a template for Long and user(To be a user cache)
     * @return redisTemplate<Long,User>
    */
    @Bean
    @Qualifier("redisUserTemplate")
    public RedisTemplate<Long, User> redisUserTemplate() {
        RedisTemplate<Long, User> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(new LettuceConnectionFactory());
        return redisTemplate;
    }
    
  3. use RedisTemplate

    private RedisTemplate redisTemplate
    //@Qualifier to choose the bean you actually want. 
    @Autowired
    public constructor(@Qualifier("xxxRedisTemplate")RedisTemplate redisTemplate){
      this.redisTemplate=redisTemplate;
    }
    
  4. use redisTemplate

    private HashOperations<Long, byte[], byte[]> hashOperations = redisUserTemplate.opsForHash();
    private HashMapper<Object, byte[], byte[]> hashMapper = new ObjectHashMapper();
    @Nullable
    public void saveObject(Long key, User user) {
       Map<byte[], byte[]> mappedHash = hashMapper.toHash(user);
       hashOperations.putAll(key, mappedHash);
    }
    public Object loadObject(Long key) {
       Map<byte[], byte[]> loadedHash = hashOperations.entries(key);
       return hashMapper.fromHash(loadedHash);
    }
    
  5. If you encounter the circular spring injection error, consider setter injection, @Lazy, @PostConstructor or implements ApplicationContextAware, InitalizingBean, for more information surf this link how to fix this

tyrantqiao
  • 319
  • 4
  • 7
1

You can do as sol4me said on the top, but you can handle this in a easy way:

1, auto wire RedisTemplate

@Autowired
private RedisTemplate redisTemplate;

2, set value like this:

redisTemplate.opsForValue().set("yourkey", 12434L);

3, get value like this:

(Long) redisTemplate.opsForValue().get("yourkey");

No need to create a bean like RedisTemplate< String, Long >, if you do this like that, you may create a lot of beans in your system. So just use the easy way.

Bruce
  • 1,718
  • 20
  • 15