LANGUAGE/!$%!% ERROR NOTE 2021. 4. 22. 18:52

Redis

  • ※ 환경
    • Spring Boot 1.5.4
    • Java 1.8
    • Lettuce 5.0.1

1. Error - 오류

Redis 맛 좀 보기 위해서

나의 Spring Boot 1.5.4 Project속 특정 하위 모듈에 io.lettuce:lettuce-core:5.0.1.RELEASE를 Dependencies로 추가해 봤다.

  • build.gradle

      dependencies {
          ...
          implementation 'io.lettuce:lettuce-core:5.0.1.RELEASE'
          ...
      }

음~ 모듈 테스트는 아주 잘되지만.. bootRun 해보았더니, 다음 Error가 발생하였다.

2021-04-10 17:37:39.857 DEBUG 9792 --- [           main] i.n.util.ResourceLeakDetectorFactory     : Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@1eb9ab8f
2021-04-10 17:37:39.863 DEBUG 9792 --- [           main] i.netty.util.internal.PlatformDependent  : org.jctools-core.MpscChunkedArrayQueue: available
2021-04-10 17:37:39.915  WARN 9792 --- [      Finalizer] i.l.c.resource.DefaultClientResources    : io.lettuce.core.resource.DefaultClientResources was not shut down properly, shutdown() was not called before it's garbage-collected. Call shutdown() or shutdown(long,long,TimeUnit) 
2021-04-10 17:37:39.962 ERROR 9792 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConfig': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: reactor/core/scheduler/Schedulers
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.springframework.boot.builder.SpringApplicationBuilder$run.call(Unknown Source) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-2.4.11.jar:2.4.11]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-2.4.11.jar:2.4.11]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-2.4.11.jar:2.4.11]
    at com.datastreams.mdosa.boot.Application.main(Application.groovy:53) [main/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_211]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_211]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_211]
    at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:64) [idea_rt.jar:na]
Caused by: java.lang.NoClassDefFoundError: reactor/core/scheduler/Schedulers
    at io.lettuce.core.resource.DefaultClientResources.<init>(DefaultClientResources.java:171) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at io.lettuce.core.resource.DefaultClientResources$Builder.build(DefaultClientResources.java:461) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at io.lettuce.core.resource.DefaultClientResources.create(DefaultClientResources.java:229) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at io.lettuce.core.AbstractRedisClient.<init>(AbstractRedisClient.java:96) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at io.lettuce.core.RedisClient.<init>(RedisClient.java:86) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at io.lettuce.core.RedisClient.create(RedisClient.java:135) ~[lettuce-core-5.0.1.RELEASE.jar:na]
    at com.datastreams.mdosa.redis.config.RedisCon.redisClient(RedisCon.java:19) ~[main/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_211]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_211]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_211]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    ... 26 common frames omitted
Caused by: java.lang.ClassNotFoundException: reactor.core.scheduler.Schedulers
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_211]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_211]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_211]
    ... 40 common frames omitted

2. Problem - 문제

SpringBoot는 Vesion 2 부터 Lettuce를 지원한다.

근본적으로 Lettuce 5.0.1 에서는 io.projectreactor:reactor-core:3.1.2.RELEASE를 의존하고 있는데

Spring Boot 1.4 또는 1.5에서 낮은 버전의 동일 의존성(io.projectreactor:reactor-core:2.0.8.RELEASE)을 가지고 있기 때문에

충돌이 일어나서 낮은 버전을 참조하고 있기 때문이다.

  • build.gradle

      dependencies {
          ...
          implementation 'io.lettuce:lettuce-core:5.0.1.RELEASE'
          ...
      }

3. Solved - 해결

[방법 가]. Spring Boot 2로 업그레이드

Spring Boot 2 부터 Lettuce를 지원한다 하니 해당 버전을 사용하는 것이 더 바람직 하겠다.

  • build.gradle

      dependencies {
          ...
          implementation "org.springframework.boot:spring-boot-starter-data-redis:${spring_boot_version}"
          ...
      }
    • 따로 Jedis와 다르게 Lettuce는 의존성 따로 명시 하지 않아도 된다고 하는데.. (나중에 해보고 다시 적겠다.)

[방법 나]. 강제 명시

당신의 Main 모듈에서 강제로 의존성을 걸어 주어야 한다.

  • build.gradle

      dependencies {
          ...
          implementation "io.projectreactor:reactor-core:3.1.2.RELEASE"
          ...
      }

4. Reference - 참조