Eclipse와 JDK9에서 @PostConstruct 어노테이션 오류

오랜만에 Eclipse를 띄어서 이전 프로젝트를 확인 하는데 @PostConstruct 어노테이션을 찾을 수 없다는 오류가 보였다.

따로 변경한 것은 JDK 버젼을 8에서 9로 업그레이드 한거 말곤 없었다.

검색을 해보니 해당 문제에 대한 해결책이 있었다.

eclipse.ini 파일에 –add-modules=java.se.ee 옵션을 추가 하면 된다.

-vmargs
--add-modules=java.se.ee
-Dosgi.requiredJavaVersion=1.8
-Xms256m
-Xmx1024m

JDK9이 아직 안정화가 안된건지, 여러 모듈에서 오류가 발생한다.

참고 자료


Posted by lahuman

데이터 베이스 테이블 복사 기능 만들기

DBeaver와 같은 DB TOOL을 사용하지 않고 다른 위치의 DB 간의 테이블 복제하는 프로그램이 필요하여 간단하게 만들었다.

프로그램은 아주 단순 한다. 원본 테이블의 Select Query와 타켓 테이블의 Insert Query를 기준으로 마이그레이션을 진행한다.

소스 보기

준비 사항

  • Gradle
  • JDK 1.8

사용법

lahuman.Migration 파일의 10번째 라인과 11번째 라인의 DB 접속 정보를 입력 한다.

//Line 10~11
Connection originalDB = DriverManager.getConnection("URL", "ID", "PW"); //원본 DBMS
Connection targetDB = DriverManager.getConnection("URL", "ID", "PW"); //복제예정 DBMS

lahuman.Migration 파일의 13번째 라인의 SQL을 작성한다. 이때 작성하는 SELECT SQL과 INSERT SQL의 Column 순서는 맞아야 한다.

//LINE 13
copyTableUsingSQL(originalDB, targetDB, "select A, B, C from T1", "insert into T2(A,B,C)values(?,?,?)");

단순하게 만들어서 그런지 쉽게 사용할 수 있다.



Posted by lahuman

예전에는 책을 구매 하기 전에 보통은 서점을 가서 책을 보고 구매를 진행 하였지만, 최근에는 도서관에 책을 희망 자료로 요청 하고 한달 정도 있다가 빌려서 본 후 구매를 진행한다. 한달에 총 25권까지 신청 할 수 있는데, 이를 하나하나 손으로 등록하기엔 너무 많은 시간과 노력이 필요하다. 이에 도서 목록을 가지고 자동으로 등록하는 프로그램을 만든다.

프로그램 설계

부천 시립 도서관에서 한달에 요청 할 수 있는 도서는 다음과 같다.

  • 상동, 심곡, 꿈빛, 책마루, 송내도서관 : 1인당 월 5권
  • 원미, 북부, 한울빛, 꿈여울도서관 : 1인당 월 20권

이에 도서 목록을 다음과 같이 TXT 파일로 작성하연 자동으로 등록 하도록 한다.

도서목록 파일 내용 샘플

도서관코드|도서명
AA|즐거운하루
AB|자동책등록프로그램

도서관 코드

도서관코드도서관명비고
AA상동월5권
AB원미월20권
AC삼곡월5권
AD북부월20권
AE꿈빛월5권
AF책마루월5권
AG한울빛월20권
AH꿈여울월20권
AI송내월5권
AK도당월20권

프로세스 순서도

프로세스 순서도

Notice

License

희망 도서 자동 등록 프로그램은 open source 프로그램으로 MIT 라이선스를 따릅니다.

This Request book apply is free and open source software, distributed under the MIT License. So feel free to use this program on your project without linking back to me or including a disclaimer.



Posted by lahuman

JAVA CODE STYLE GUIDE

코드 스타일 가이드가 있으면 결과적으로 코드의 질이 좋아진다.
(당장은 아니겠지만)

기본적으로 많은 곳에서 사용되는 자바 스타일 가이드는 SUN 의 스타일 가이드이다.

스타일 가이드에서 제시하는 코드 규칙의 중요성을 간략하게 정리하면 다음과 같다.
  • 소프트웨어를 개발하는 일련의 모든 과정에 들어가는 비용 중 80%가 유지보수에 사용된다.
  • 유지보수를 최초 소프트웨어를 개발한 사람이 담당하는 경우가 거의 없다.
  • 코드 규칙을 지키면 다른 개발자가 소스코드를 보았을 때 이른 시간에 이해할 수 있도록 도와준다.

만약 코드 스타일 가이드를 한 번도 읽어 보지 못했다면 SUN 의 스타일 가이드 를 읽어 보길 추천한다. 원본은 영어로 되어 있지만,한국어로 번역된 글도 많고 내용 대부분이 예제 코드로 이루어져 있으므로 문제없이 읽을 수 있을 것이다.

지금부터 소개할 것은 SUN 의 스타일 가이드가 아닌 GOOGLE의 스타일 가이드 이다.

Google java style guide 는 60% 정도는 SUN의 스타일 가이드와 같다.
몇 가지 다른 부분들은 tab 대신 space를 사용하는 것과 column limit 이 80 에서 100으로 더 크게 지정되었다는 부분과 최신 lambda 표기법 등이 있다.

선택의 이유는 SUN 의 스타일 가이드는 근래에 업데이트가 되지 않고 있지만, google의 스타일 가이드는 조금씩 업데이트가 되고 있다.

javaguide.html 파일의 마지막 변경 시점은 29일 전이다 - 2016.08.11 기준)

GOOGLE STYLE GUIDE

기본적으로 개발 도구를 ECLIPSE 을 사용하는 기준으로 기본 코드 컨벤션 설정은 SUN 사의 스타일로 처리 되어 있다.

우선 기본 CODE FORMAT를 Google 의 style로 변경해야 한다.
순서는 다음과 같다.

  1. 구글에서 제공하는 이클립스용 스타일 포맷 을 내려받는다.
  2. ECLIPSE를 실행하고 다음 메뉴로 이동한다.
    • Window > Preference > java > Code Style > Formatter
  3. Import를 선택하고 내려받은 XML 파일을 선택하고 Active Profile을 GoogleStyle로 설정 한다.
  4. Ctrl + Shift + F 를 이용해 소스 코드를 정렬한다.

참고 자료

Eclipse Checkstyle Plugin

코드를 작성하다 보면 스타일 가이드를 지키고 있는지 알 수 없다.
Checkstyle 이라는 프로그램을 이용하여, ant 또는 java 를 이용한 실행으로 잘못된 스타일 가이드를 확인할 수 있지만, 실시간이 아니므로 재작업에 어려움을 느낄 수 있다.

다행이 실시간으로 스타일 가이드를 확인할 수 있는 이클립스 플러그인이 있다.

설치는 다음과 같다.

  • Help > Eclipse Market place에서 CheckStyle로 검색을 하면 CheckStyle Plugin X.X.. 이라는 이름의 플러그인을 설치 하면 된다.
  • 설치가 완료되면 이클립스를 재기동한다.

설치가 끝나면 사용을 하기 위해 간단한 설정을 해야 한다

  1. Window > Preference > Checkstyle 에서 Google Check를 기본값으로 설정하고 저장한다.
  2. 사용할 프로젝트에서 마우스 오른쪽 키 > Properties 또는 Alt + Enter 를 이용해서 설정으로 이동한다.
  3. 왼쪽 트리 메뉴에서 Checkstyle를 선택하고 오른쪽의 Checkstyle active for this project의 체크박스를 체크 한다.
  4. OK 버튼을 누른다.

이후 화면에서 스타일을 지키지 않은 내용을 바로 확인할 수 있다.


MD FILE : 

코드스타일가이드.md



Posted by lahuman

Lambda Basic

function has 4 things

  1. name
  2. parameter list
  3. body
  4. return type
Thread th = new Thread(new Runnable(){
    public void run(){
        Sysout.out.println("In side Thread");
    }
});
th.start();

lambda expression

1. name

  1. parameter list
  2. body

4. return type

Thread th = new Thread(() ->Sysout.out.println("In side Thread"));
th.start();

iterators

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//external iterators
for(int i = 0; i < numbers.size(); i++){
    System.out.println(numbers.get(i));
}

//external iterators also
for( int e : numbers){
    System.out.println(e);
}

//interal iterators
numbers.forEach(new Consumer<Integer(){
    public void accept(Integer value){
        System.out.println(value);
    }
});

numbers.forEach((Integer value) ->System.out.println(value));

numbers.forEach((value) ->System.out.println(value));

//only for on parameter lambdas
numbers.forEach(value ->System.out.println(value));

numbers.forEach(System.out::println);

//ANTI PATTERN :: DO NOT USE LIKE THIS!
number.forEach(e -> {
...;
...;
...;
return ... need return...;
});

Parameter

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
numbers.stream()
    //.map(e -> String.valueOf(e))
    .map(String::valueOf)
    .forEach(System.out::println);

numbers.stream()
    .map(e -> String.valueOf(e))
    //.map(e -> e.toString())
    .map(String::toString)
    .forEach(System.out::println);

Two parameter

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(
    numbers.stream()
        //.reduce(0, (total, e) -> Integer.sum(total, e)));
        .reduce(0, Integer::sum));
);
System.out.println(
    numbers.stream()
        .map(String::valueOf)
        //.reduce("", (carry, str) -> carry.concat(str)));
        .reduce("", String::concat));
);

Stream

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//given thevalues, double the even numbers and total.
int result = 0;
for(int e : numbers){
    if(e % 2 == 0){
        result += e*2;
    }
}
System.out.println(result);

System.out.println(
    numbers.stream()
        .filter(e -> e % 2 == 0)
        .mapToInt(e ->e * 2)
        //.reduce(0, Integer::sum));
        .sum();
);

출처


Get a Test of Lambda.md



Posted by lahuman

** 2016-07-08 추가 내용 **

SSL 관련 JAVA 설정이 필요 할때 참조 : https://www.facebook.com/lahuman/posts/1175481055835258



** 기존 내용 **


Jsch 라이브러리를 이용해서 ssh 접속을 문제 없이 하던 중, 갑자기 다음과 같은 오류 메시지를 만나게 될 경우 해결 방법 입니다.


com.jcraft.jsch.JSchException: Session.connect: java.security.NoSuchAlgorithmException: Algorithm DH not available

at com.jcraft.jsch.Session.connect(Session.java:558)



내용인 즉, DH 알고리즘이 없다는 내용이라 해당 알고리즘을 추가를 해야 합니다.



추가를 위해서는 bouncycastle 라이브러리가 필요 합니다.


라이브러리를 추가 하셨다면 jsch 호출 하기전에 Security 에서 제공자를 추가 합니다.


소스 코드는 다음과 같습니다.

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
java.security.KeyPairGenerator.getInstance("DH");
javax.crypto.KeyAgreement.getInstance("DH");


"Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());" 가 없을 경우, 에러가 발생하지만 제공자를 추가 하면 java.security.NoSuchAlgorithmException: Algorithm DH not available 와 같은 오류가 발생하지 않고 연결에도 문제가 없습니다.




Posted by lahuman

[TIP.1]Mybatis XML 에서 JAVA static method 호출 하기

다음과 같은 class가 있을 경우

package kr.pe.lahuman;
public class CallOfMybatis{
    public static final String callStaticMethod(Parameter param ){
        //처리
        reutrn "처리 결과";
    }
}

mybatis XML 에서는 다음과 같이 호출 할 수 있다.

${@kr.pe.lahuman.CallOfMybatis@callStaticMethod(param)}

[TIP.2]Mybatis configuration 에서 TypeAliase 설정하여 여러 VO를 alias 사용하기

특정 패키지를 다음과 같이 설정 하면

<typeAliases>
  <package name="kr.pe.lahuman.vo"/>
</typeAliases>

다음과 같이 XML에서 사용할 수 있다. 주의 할 점은 alias 명은 모두 소문자로 작성 해야 한다.

<select id="getHaveANiceDay" parameterType="sohappyvo" resultType="resultvo" >
select happy, day
from good_day
</select>

MD 파일 : 

Mybatis-TIP.md



Posted by lahuman

JMH

JAVA와 JVM이 대상인 언어로 작성된 나노/마이크로/밀리/매크로 벤치 마크 분석 구축, 실행을 위한 자바 라이브러리입니다.

기본고려사항

JMH 벤치 마크를 실행하기 위한 권장 방법은 어플리케이션에서 jar 파일의 기본 의존성을 설정하는 메이븐 사용입니다.
이 방법은 벤츠마크가 정확하게 초기화 되고 믿을 수 있는 결과를 받을 수 있도게 접근하도록 한다.
이것은 이미 존재 하는 프로젝트나, IDE 에서 조차 벤치마크가 가능하다, 설치는 더 복잡 하고 신뢰할 수 없는 결과를 준다.
모든 경우에, JMH는 키를 이용해서 annotation이나 bytecode-processors(바이트코드 프로세서) 합성 벤치마크 코드를 생성 한다.
기본 동작은 메이븐 원형을 사용하여 이것을 활성화 합니다.
우리는 새로운 사용자가 설정을 올바른 환경에서 사용하도록 강하게 추천합니다.

MD FILE : 

JMH.md



Posted by lahuman

원문 : Why 1000 == 1000 Returns False, but 100 == 100 Returns True in Java?

이것은 아마도 많이 이야기 되는 흥미로운 내용일 것입니다.
다음의 코드를 실행하면

Integer a=1000, b=1000;
System.out.println(a == b); //1
Integer c=100, d=100;
System.out.println(c == d); //2

다음의 결과를 확인할 수 있습니다.

false
true

이해를 위한 기본: 두 개의 참조 값이 같은 객체를 가리키는 경우, 그것이 == 로 같은 것으로 알고 있습니다. 만약 두 개의 객체가 가르치는 참조가 다를 경우, 같은 내용을 가지고 있어도 == 로 같지 않다는 결과를 받습니다.

그래서 마지막 결괏값 역시 false 여야 합니다.

이 흥미로운 것은 사실이다. 만약 당신이 Integer.java 클래스를 본다면 IntegerCache.java 내부 private 클래스를 확인할 수 있을 것이며, 이 클래스에서 -128부터 127까지의 값을 캐시에 저장한다.

그래서 다음과 같이 우리가 뭔가를 선언 할 때 작은 숫자 값은 캐시에 저장된다.

Integer c = 100;

다음 실행하면 내부에서 어떤 일이 일어나는가?

Integer i = Integer.valueOf(100);

valueOf() 메소드를 확인하면

public static Integer valueOf(int i){
    if(i >=-128 && i <= 127){
        return IntegerCache.cache[i+(128)];
    }
    return new Integer(i);
}

만약 값이 범위가 -128에서 127이라면 캐시에 저장된 객체가 전달 될 것이다.
그래서

System.out.println(c == d);

에 결과로 우리는 true를 확인하였다.

당신은 “왜 캐시가 필수일까?” 라는 의문을 가질 것이다.
아마도, 논리적인 근거는 작은 값의 숫자 범위 값은 큰 숫자 하나 보다 더 많이 사용된다. 그래서 같은 객체를 이용하여 메모리 사용량을 줄이는 것이다.

그러나 reflections API를 이용하여 이 기능을 악용할 수 있습니다.

다음 코드를 실행하면, 재미있는 결과를 확인할 수 있습니다.

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
  Class cache = Integer.class.getDeclaredClasses()[0]; //1
  Field myCache = cache.getDeclaredField("cache"); //2
  myCache.setAccessible(true);//3
  Integer[] newCache = (Integer[]) myCache.get(cache); //4
  newCache[132] = newCache[133]; //5
  int a = 2;
  int b = a + a;
  System.out.printf("%d + %d = %d", a, a, b); //
}

결괏값

2 + 2 = 5



추가 내용 :

warpper class(Integer, Double, Long 등)의 인스턴스의 경우 값에 대한 비교는 equals() 메소드를 이용해야 합니다.


MARK DOWN FILE :

1000_100_Integer.md




Posted by lahuman

Lombok 이란?

간단하게 BEAN(POJO) 를 도와주는 라이브러리 입니다. 

annotation을 이용하여 getter, setter 등을 생성한다거나, toSring 객체를 지원 한는 등의 기능을 제공 합니다.



사용법은 IDE를 사용할 경우와 javac 를 이용한 compile을 할 경우로 나누어 집니다.


저는 Intellij 기준으로 설명을 하겠습니다.


Intellij 에서 사용하기 위해서는 Lombok plugin을 설치 해야 합니다.

설치 방법은, 다음과 같습니다.


  • Using IDE built-in plugin system on Windows:
    • File > Settings > Plugins > Browse repositories... > Search for "lombok" > Install Plugin
  • Using IDE built-in plugin system on MacOs:
    • Preferences > Settings > Plugins > Browse repositories... > Search for "lombok" > Install Plugin
  • Manually:
    • Download the latest release and install it manually using Preferences > Plugins > Install plugin from disk...

원본 : https://github.com/mplushnikov/lombok-intellij-plugin


설치 이후에는 IDE를 재기동 해야 합니다.


이후 Lombok 을 사용하기 위한 compiler 설정을 변경 합니다.


  • install plugin
  • change compiler setting:
    • ... > Compiler > Java Compiler > Use Compiler: Eclipse
    • ... > Compiler > Annotation Processors > Enable annotation processing: checked (default configuration)
    • ... > Compiler > Additional build process VM options: -javaagent:lombok.jar

원본 : https://github.com/mplushnikov/lombok-intellij-plugin


이 설정을 하지 않을 경우 간혈적으로 오류가 발생하거나, 기동시 getter setter method를 찾을 수 없다고 표출 될 수 있습니다.


마지막으로 Lombok 에서 제공하는 기능에 대한 정리 입니다.


val : final 키워드 대신 사용하는 변수 선언 class

@NonNull : 해당 값이 Null 일경우 NullPointerException을 발생한다.

@Cleanup : 자동 리소스 관리 : close() 메소드를 귀찮음 없게 안전하게 호출

@Getter / @Setter : getter, setter를 생성하지 않도록 지원

@ToString : 모든 필드를 출력하는 toString() 메소드 생성

@EqualsAndHashCode : hascode 와 equals 메소드를 생성

@NoArgsConstructor, @RequriedArgsConstructor and @AllArgsConstructor : 인자 없는 생성자 생성, 필수 인자만 있는 생성자 생성, 모든 인자를 가진 생성자 생성

@Data : 다음을 처리 합니다 - @ToString, @EqualsAndHashCode, @Getter(모든 필드), @Setter(모든 필드-final로 성언되지 않은), @RequiredArgsConstructor!

@Value : 불변 클래스를 쉽게 생성

@Builder : Builder API 처럼 사용 할수 있도록 지원

@SneakyThrows : Exception 발생시 체크된 Throable로 감싸서 전달

@Synchronized : 메소드에서 동기화 Lock을 설정

@Getter(lazy=true) : 동기화를 이용하여 최초 1회만 getter가 호출

@Log : 종류별 로그를 사용할 수 있도록 한다. (@Log, @Slf4j, @CommonLog 등)

Configuration system : lombok을 사용하기 위해서 최초 설정

Experimental features : 준비중인 추가 기능



Lomobk library download LINK

Lombok site : https://projectlombok.org/features/index.html

Lombok tutorial : http://jnb.ociweb.com/jnb/jnbJan2010.html


Posted by lahuman