2017-10-02
2017-09-21
mybatis 유감
mybatis 쓰느니 그냥 SQL 날코딩해서 JDBC로 다이렉트 호출 할래...
스프링이라면 JDBCTemplate이라는 거도 있고
쿼리문 날코딩이 귀찮으면 querydsl로 메타데이터 뽑아서 쿼리를 코드로 짜도 되고...
스프링이라면 JDBCTemplate이라는 거도 있고
쿼리문 날코딩이 귀찮으면 querydsl로 메타데이터 뽑아서 쿼리를 코드로 짜도 되고...
2017-02-28
Hudson/Jenkins proxy with Nginx
허드슨이나 젠킨스를 맨날 단독으로 띄워서 쓰다가
Let’s Encrypt를 적용하면서 앞에다가 nginx를 두고 프록시로 요청을 받게 설정했다.
그런데 자꾸 다음 메세지가 나면서 로그인할 때나 일부 링크가 엉뚱한 곳으로 간다.
구글신의 신탁을 받아 이곳 저곳을 돌아봤는데 다 소용이 없었다.
그래서 그냥 소스를 까볼까? 해서 봤더니…
소스 링크
그래서 nginx 설정에서 프록시 헤더를
역시 답 없을 때는 소스를 직접 들여다 보는게 답이네.
Let’s Encrypt를 적용하면서 앞에다가 nginx를 두고 프록시로 요청을 받게 설정했다.
그런데 자꾸 다음 메세지가 나면서 로그인할 때나 일부 링크가 엉뚱한 곳으로 간다.
It appears that your reverse proxy set up is broken
구글신의 신탁을 받아 이곳 저곳을 돌아봤는데 다 소용이 없었다.
그래서 그냥 소스를 까볼까? 해서 봤더니…
소스 링크
X-Forwarded-Host
를 받고 계셨어요?그래서 nginx 설정에서 프록시 헤더를
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
이렇게 설정해주니까 잘 된다.역시 답 없을 때는 소스를 직접 들여다 보는게 답이네.
2017-02-24
enum 네 이놈! - 제네릭과 람다와 enum과 헬게이트
조금 전에
원래대로라면
그래서 다 때려박으면서 예제삼아 코드값 <-> 텍스트 상호전환 코드까지 같이 만들었는데…
누가 (울 회사 직원이라고 말 안할거임) 그걸 그대로 복붙해서
해서 코드값 <-> 텍스트 상호전환 하는 부분을 별도의 유틸리티 클래스로 분리했다.
문제는 여기서 발생하는데…
먼저
그리고 맨 처음 유틸리티 클래스를 람다식을 활용하여 만들었다.
그리고 테스트를 돌렸을 때, 처음 보는 당황스러운 에러가…
…모라고요?
곰곰히 머리를 싸매고 생각하다가 분석을 해보니
그래서 람다 말고 메소드 직접 호출로 변경.
이러니까 잘 된다.
이게
enum
들에 널려있는 중복 코드들을 제거하는 와중에 일어난 이야기.원래대로라면
enum
에는 코드값만 넣고 텍스트는 따로 properties
에 빼놓는데, 이번 고객은 아아주 특이하게도 그렇게 하면 유지보수하기 귀찮다고 소스에 다 때려박아달랜다.그래서 다 때려박으면서 예제삼아 코드값 <-> 텍스트 상호전환 코드까지 같이 만들었는데…
누가 (울 회사 직원이라고 말 안할거임) 그걸 그대로 복붙해서
enum
수십 개를 만들었고, CPD는 복붙 고마해라 라고 지랄대고…해서 코드값 <-> 텍스트 상호전환 하는 부분을 별도의 유틸리티 클래스로 분리했다.
문제는 여기서 발생하는데…
먼저
WithCodeLabel
이라는 인터페이스를 만들고 메소드를 정의한 다음, 해당 enum
들에 implements
를 걸었다.그리고 맨 처음 유틸리티 클래스를 람다식을 활용하여 만들었다.
public class EnumCodeLabelCache<E extends Enum<E> & WithCodeLabel> {
private final Map<String, E> codeToLabelMap;
private final Map<String, E> labelToCodeMap;
private EnumCodeLabelCache(Class<E> cls) {
final EnumSet<E> set = EnumSet.allOf(cls);
codeToLabelMap = set.stream().collect(Collectors.toMap(WithCodeLabel::getCode, Function.identity());
labelToCodeMap = set.stream().collect(Collectors.toMap(WithCodeLabel::getLabel, Function.identity());
}
...
}
그리고 테스트를 돌렸을 때, 처음 보는 당황스러운 에러가…
java.lang.BootstrapMethodError: call site initialization exception
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
…모라고요?
곰곰히 머리를 싸매고 생각하다가 분석을 해보니
enum
의 각 값의 RTTI에 WithCodeLabel
인터페이스에 대한 정보가 누락되어 있다는 결과밖에 나오지를 않는다.그래서 람다 말고 메소드 직접 호출로 변경.
public class EnumCodeLabelCache<E extends Enum<E> & WithCodeLabel> {
private final Map<String, E> codeToLabelMap = new HashMap<>();
private final Map<String, E> labelToCodeMap = new HashMap<>();
private EnumCodeLabelCache(Class<E> cls) {
final EnumSet<E> set = EnumSet.allOf(cls);
set.forEach(e -> {
codeToLabelMap.putIfAbsent(e.getCode(), e);
labelToCodeMap.putIfAbsent(e.getLabel(), e);
});
}
...
}
이러니까 잘 된다.
이게
enum
만 특히 이런건지, 제네릭 특징인지는 더 살펴봐야 알겠지만, 내가 알 게 뭐야.