Monthly Archives: July 2018

Kotlin DSL – BeanDefinitionDSL.kt

코틀린 DSL Bean 선언.

이거 공부 좀 하면 커스텀 빈도 만들 수 있지 않나

샘플코드
https://github.com/sdeleuze/spring-kotlin-functional
가이드 페이지
https://spring.io/blog/2017/08/01/spring-framework-5-kotlin-apis-the-functional-way

한글 번역이나 어설프게 소스코드 붙여놓고 설명하면 더 헷갈릴 것 같다.

이해할 것도 없고 간단하니 그냥 소스 리포지터리 보는게 더 쉬움.

Kotlin에서 slf4j 로거 선언

https://www.reddit.com/r/Kotlin/comments/8gbiul/slf4j_loggers_in_3_ways/
자바에서 lombok을 쓰면서 고민도 하지 않았던 부분인데… 여기서는 왠지 신경쓰이는 부분.


class SimpleClass {
private val log = LoggerFactory.getLogger(SimpleClass::class.java)
}

이렇게 해야되는데.. 이렇게 매번쓰기 귀찮으니

CoreUtil.kotlin

inline fun logger(): Logger {
return LoggerFactory.getLogger(T::class.java)
}
inline fun logger2(): Logger {
return LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())
}

이걸 선언 해 두고 가져다 쓴다.
오브젝트에 선언하면 스태틱처럼 선언도 가능하지만 클래스 밖에 선언해두면 전역전역펑션으로 선언된다
인라인이 아니었다면… 클래스를 파라미터로 전달했겠지만 이렇게 해서 좀 더 간단해진다.

refied는 여기 참고.
https://medium.com/@joongwon/kotlin-kotlin-%ED%82%A4%EC%9B%8C%EB%93%9C-%EB%B0%8F-%EC%97%B0%EC%82%B0%EC%9E%90-%ED%95%B4%EB%B6%80-part-3-59ff3ed736be

logger2는 댓글에 써 있는 방법.. 좀 더 간단해 보이는데 검증은 필요.

h2. 처리방법 1

companion object 길어서 좀 꼴뵈기 싫다

class MemberService {
companion object {
private val log = logger()
}
}

h2. 처리방법 2

위에다 선언… intellij에서 클래스 표시가 꺼진다. 왠지 기분나쁨

private val log = logger()
class MemberService {
}

h3. 처리방법 3

인터페이스, 앱스트랙트 사용

선언이 좀 성가셔 보이는데 코드가 제일 깔끔해보인다.

매번 호출하는건 아니겠지?


interface Logger {
fun logger() = LoggerFactory.getLogger(this.javaClass)
}

class SimpleClass {
companion object : Logger
fun testfun(){
logger().info("aaa")
}
}


abstract class Logger {
val logger: Logger = LoggerFactory.getLogger(this.javaClass)
}

class SimpleClass {
companion object : Logger()
fun testfun(){
logger.info("aaa")
}
}

Error: Spring Session 실행시 TaskScheduler를 찾는 에러

Error :
2018-07-25 11:05:19.871 DEBUG 3353 --- [ restartedMain] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.session.RedisSessionConfiguration$SpringBootRedisHttpSessionConfiguration'
2018-07-25 11:05:19.876 DEBUG 3353 --- [ restartedMain] s.a.ScheduledAnnotationBeanPostProcessor : Could not find default TaskScheduler bean

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.scheduling.TaskScheduler' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:992) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:293) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:234) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:211) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:102) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:888) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at kr.scripton.elemhant.app.StartApplicationKt.main(StartApplication.kt:11) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.0.1.RELEASE.jar:2.0.1.RELEASE]

2018-07-25 11:05:19.877 DEBUG 3353 --- [ restartedMain] s.a.ScheduledAnnotationBeanPostProcessor : Could not find default ScheduledExecutorService bean

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.concurrent.ScheduledExecutorService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:992) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:293) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:255) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:211) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:102) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:888) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at kr.scripton.elemhant.app.StartApplicationKt.main(StartApplication.kt:11) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.0.1.RELEASE.jar:2.0.1.RELEASE]

2018-07-25 11:05:19.877 INFO 3353 --- [ restartedMain] s.a.ScheduledAnnotationBeanPostProcessor : No TaskScheduler/ScheduledExecutorService bean found for scheduled processing

추가 해 준다.

@Bean
fun taskScheduler(): TaskScheduler {
return ConcurrentTaskScheduler() //single threaded by default
}

아래 커넥션 연결해제부분

2018-07-25 11:50:00.000 DEBUG 8136 --- [pool-3-thread-1] o.s.d.redis.core.RedisConnectionUtils : Opening RedisConnection
2018-07-25 11:50:00.010 DEBUG 8136 --- [pool-3-thread-1] o.s.d.redis.core.RedisConnectionUtils : Closing Redis Connection
2018-07-25 11:50:00.011 DEBUG 8136 --- [pool-3-thread-1] o.s.d.redis.core.RedisConnectionUtils : Opening RedisConnection
2018-07-25 11:50:00.012 DEBUG 8136 --- [pool-3-thread-1] o.s.d.redis.core.RedisConnectionUtils : Closing Redis Connection

Error: kotlin 뭔지 모를 reflection 오류

문제

SpringBoot + Kotlin을 실행시킬 때 다음과 같은 오류 발생

환경

해결

jackson_fastxml_version =2.9.6
jackson.version =2.9.6

spring boot에서 jackson이 2.8.x대르 가져오고 있었다. 변경.

아래 의존성이 제대로 설정되지 않은 경우 비슷한 오류 발생가능.
compile “org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version”
compile “org.jetbrains.kotlin:kotlin-reflect:$kotlin_version”

자바는 1시간이상 삽질했는데 제자리라면 의존성 오류.