https://docs.gradle.org/5.0/release-notes.html

Gradle 5.0 이 나왔습니다.

Java 11 및 운영가능한 수준으로 Kotlin DSL 1.0 를 지원합니다.


터치패드 없이 리얼포스 키보드는 모니터(Dell U2718Q)에 연결하고 터치패드는 별도로 구매하지 않고 왼손으로 터치패드를 사용했다.
맥북이 절전모드였다거나 모니터가 꺼져있는 상태에서는 키보드 인식이 제대로 되지 않았고, 마우스 커서를 움직이기 위해 왼손을 뻗어 터치패드를 조작해야했고(키보드에서 손을 떼야 했...) 드래그를 위해서는 종종 왼손으로 시프트키를 누르고 오른손을 교차해서 뻗어야 했다.

그런 불편함을 6개월 정도 감내하다가 '에잇 못참겠다!' 하고 짜증을 부리면서 해결책을 모색했다. 회사에서 지급한 맥북용 어댑터는 USB 포트가 하나였고, 키보드와 마우스를 동시에 연결할 수 없었고, USB 허브를 이용해봤는데 이 경우에도 맥북에서 제대로 인식하지 못해서 번번히 어댑터를 뺐다가 다시 꼽아야 했다.

문득 싱크패드 울트라나브 키보드가 떠올랐다.
개인적으로, 맥북보다는 싱크패드 노트북을 선호한다. 윈도우즈 시스템보다는 파티션을 나눠서 리눅스(주로 우분투)를 설치하고 그 안에서 개발하는 것을 선호하는데 입사하면서 싱크패드를 요청했다가 거절당하고 겨우겨우 맥북을 쓰고 있지만, 터치바 맥북은 정말 못쓰겠다. ㅡ_-);;

내 돈주고 맥북을 사는 일은 없을 것이다.

국내 쇼핑몰에서 구매가능한 모델은 유선USB케이블 방식이었다. 인터넷을 뒤적거리다가 중국내수용 멀티페어링을 지원하는 울트라나브를 구매가능하다는 것을 확인하고 구매대행을 통해 구매했다. 가격은 저렴하게 구매했다는 사람들보다는 2~3만원 비싸긴 하지만 2주 안에 받을 수 있었고, 크게 신경쓰지 않아서 만족하고 있다(98,500)에 구매.

기존에 사용하던 싱크패드S440 키보드와 크게 차이는 없다(개인적으로 저가형 싱크패드에 들어간 클릭패드는 싫어한다).

동봉되어 있는 USB케이블 때문에 당연히 유선연결이 되는 줄 알았는데, 그건 내 착각이었다.순전히 충전을 위한 케이블이었다.

기기와 연결은 블루투스 연결만 가능하며, 총 3개 기기를 상단에 있는 버튼을 통해 변경가능하다.

Fn키 잠금은 지원하지 않는듯 하고, 최근 나온 싱크패드나 맥북 모두 Fn키가 왼쪽 하단에 위치하고 있고 기능키를 누르기 위해서 반드시 눌러야 하니 크게 고민되지는 않았다.

어제 받은 싱크패드 울트라나브를 연결하고서는 노트북이 절전모드에서 돌아와도 키보드 인식이 되고, 커서를 움직이기 위해서 굳이 터치패드로 손을 뻗을 필요도 없었다. 키보드는 윈도우즈 타입으로 설정하니 대부분의 키 설정이 맞고 키배치만 조금 수정해서 기능키를 맥북키보드와 일치시켰다.

스크롤은 가운데버튼 누르고 빨콩을 움직이는 것으로 커버가 되었다.

맥북과 호환성 잘되고, 내가 가지고 있는 안드로이드폰과도 잘 연결된다.

키감은 당연히 리얼포스보다는 약하지만, 지금사용하고 있는 맥북보다는 훨씬 낫다고 생각한다. 약간 쫀득함이 부족한 것 같은 느낌이 있기는 하지만 뭐...

#월급쟁이개발자 일은 못하면서 조금이라도 덜 움직이는 걸 찾는다.

반나절 정도 사용해보니 빨콩사용도 익숙해지있다.

Fn키 고정이 안되는 건 아쉽지만, 맥북쓰면서 익숙해져서 그렇게 불편함은 없다.


'Tools' 카테고리의 다른 글

ZSH - The Z Shell  (0) 2016.05.14
[atom] asciidoc-preview 한글처리  (0) 2015.10.29

그레이들 래퍼를 이용하면 프로젝트 구성원들이 일일이 그레이들을 설치는 번거로움을 피할 수 있다(한명만 고생하면 된다). 다음과 같이 실행하면 로컬에 설치되어 있는 그레이들 버전을 기준으로 그레이들 래퍼가 설치된다.

$ gradle wrapper
$ cat gradle/wrapper/gradle-wrapper.properties
#Fri Mar 24 21:30:00 KST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

하지만 그레이들 래퍼의 버전은 간단한 인자변경을 통해 손쉽게 할 수가 있다. 다음 명령어를 이용한다.

$ gradle wrapper --gradle-version={version}

3.4.1 버전을 설정한다고 치면!

$ gradle wrapper --gradle-version=3.4.1
:wrapper

BUILD SUCCESSFUL

Total time: 0.724 secs
$ cat gradle/wrapper/gradle-wrapper.properties
#Fri Mar 24 21:28:35 KST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip

다음과 같은 형태로 설치되고, 이후에 그레이들 빌드를 진행하면 자연스럽게 래퍼를 변경한다.


내겐 인텔리제이 개발환경은 너무너무 낯설다. ㅡ0-)

이클립스에서 스프링부트 기반으로 개발하던 환경을 벗어나니 너무너무 낯설기만 하다.

지금 진행하고 있는 프로젝트를 war 로 배포하려고 하면서 전과는 다른 개발방식 때문에 이런저런 새로운 상황들이 벌어져서 나를 당황하도록 만든다.

Table of Contents

1. 문제발생

@Entity 선언한 엔티티 객체를 생성한 후 테스트를 위해 실행하려는 순간 다음과 같은 문제가 발생한다.

2016-05-22 21:02:21.993  INFO 11450 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@b62fe6d: startup date [Sun May 22 21:02:21 KST 2016]; root of context hierarchy
2016-05-22 21:02:23.603  INFO 11450 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2016-05-22 21:02:23.620  INFO 11450 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2016-05-22 21:02:23.687  INFO 11450 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.1.0.Final}
2016-05-22 21:02:23.688  INFO 11450 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2016-05-22 21:02:23.690  INFO 11450 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
2016-05-22 21:02:23.722  INFO 11450 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2016-05-22 21:02:23.860  INFO 11450 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2016-05-22 21:02:24.165  WARN 11450 --- [           main] o.h.c.beanvalidation.TypeSafeActivator   : HHH000274: Unable to apply constraints on DDL for io.honeymon.springboot.proto.entity.Article
 
javax.validation.ValidationException: HV000183: Unable to load 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.createValidator(ValidatorFactoryImpl.java:339) ~[hibernate-validator-5.2.4.Final.jar:5.2.4.Final]
at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.getValidator(ValidatorFactoryImpl.java:256) ~[hibernate-validator-5.2.4.Final.jar:5.2.4.Final]
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.applyDDL(TypeSafeActivator.java:207) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.applyRelationalConstraints(TypeSafeActivator.java:191) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.applyRelationalConstraints(TypeSafeActivator.java:150) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.activate(TypeSafeActivator.java:98) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
at org.hibernate.cfg.beanvalidation.BeanValidationIntegrator.integrate(BeanValidationIntegrator.java:132) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:276) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465) [hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881) [hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) [spring-orm-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338) [spring-orm-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) [spring-orm-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) [spring-orm-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076) [spring-context-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851) [spring-context-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) [spring-context-4.3.0.RC2.jar:4.3.0.RC2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:765) [spring-boot-1.4.0.M3.jar:1.4.0.M3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.4.0.M3.jar:1.4.0.M3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.4.0.M3.jar:1.4.0.M3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1182) [spring-boot-1.4.0.M3.jar:1.4.0.M3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1171) [spring-boot-1.4.0.M3.jar:1.4.0.M3]
at io.honeymon.springboot.proto.PrototypeBootApplication.main(PrototypeBootApplication.java:10) [main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]

이 에러를 뱉으며 애플리케이션이 실행되지 않는다. 이와 관련된 문제를 인터넷을 통해 찾아본 결과, 이 문제의 답은 역시나 스택오버플로우에서 찾았다.

이와 관련해서 스프링부트 프로젝트에서도 이슈로 등록되어 논의가 있었지만…​

인텔리제이의 버그로 정리가 된 듯 싶다. @_@)>

2. 원인

스프링부트를 https://start.spring.io 를 통해서 프로젝트를 생성하면 프로젝트에서 기본내장컨테이너가providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')로 선언이 된다. providedCompile  compile, runtime 에서는 동일한 스코프로 적용이 되지만 war 로 빌드될 때는 제외된다.

providedXXX는 이행성 설정이다. 어떤 라이브러리가 provided로 설정되면 그것이 의존하는 다른 라이브러리도 자동으로 provided가 된다. 강제로 compile 로 지정해도 상관없다.

— http://kwonnam.pe.kr/wiki/gradle/webGradle Web(War) Plugin - 손권남님

providedCompile 로 정의가 된 spring-boot-starter-tomcat 의존성과 관련된 부분들이 war 에서 제외되는 상황이 생긴다.

<dependencies>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-el</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-logging-juli</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-websocket</artifactId>
    </dependency>
</dependencies>

위의 내용은 org.springframework.boot : spring-boot-starter-tomcat : 1.3.5.RELEASE 에서 확인가능하다.

providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')으로 인해서 tomcat-embed-el 도 제외가 되어 el 처리를 위한 구현체가 없어서 하이버네이트 validator 에서 예외를 뱉는 것이다. ㅡ_-)

== 해결방법

compile("javax.el:javax.el-api:2.2.5")

을 추가하면 정상적으로 실행이 된다…​. 뭘까? ㅡ_-)?

혹은

providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')

를 제거하면 된다. javax.el-api 혹은 org.apache.tomcat.embed:tomcat-embed-el 를 추가하는 것으러 처리가 될 것이다.

흠냐릿!!


아무런 생각없이 인텔리제이에서 자바프로젝트를 생성해서 자바8 코딩을 연습해보려고 하는데 거북스럽게 뜨는 빨간줄들!!

거기에 “lambda expressions not supported at this language level” 메시지가 뜬다.

'Project Structure' 창을 열어 'Project language level' 을 8에 맞춰도 위의 빨간줄과 팝업이 사라지질 않는다.

그러다가 '설마?' 하는 마음에 'build.gradle' 을 열어보니 아래 항목이 똬악!

sourceCompatibility 는 자바소스를 컴파일링하는데 사용할 자바버전을 지정하는 항목인데 인텔리제이에서 생성하는 템플릿의 버전이 1.5로 되어 있는 것을 발견하지 못하고 프로젝트 설정부분에서만 깨작거리고 있었는데...!!

`build.gradle`  에서 `sourceCompatibility` 를 제외하니 빨간줄과 팝업이 사라졌다. 흠냐.

문제가 생기면 그 발생한 부분에 너무 함몰되어 전체적으로 살펴보려는 것을 나중에 하는 이상한 습관이 들어버린 듯 하다. ㅡ_-);;

반성하자.

+ Recent posts