java 8 DateTime

With Java < 8, you would need to write something like:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, cal.get(Calendar.HOUR) + 2);

vs. with Java 8:

LocalTime now = LocalTime.now();
LocalTime later = now.plus(2, HOURS);

The improvements are essentially on

  • readability:
    • Calendar.getInstance() is not very well named: it is hard to tell which instance you are getting without reading the Javadoc. LocalTime.now() is quite self-describing: you get a time and it is now.
    • To offset a date, you call an offsetting method (plus) whereas with the Calendar API, you have to manually change the fields of the object (in this example, the hour) which is error prone.
  • ease of use (see for example the table towards the bottom of this page for a comparison):
    • the Calendar API is complicated to use because it mixes concepts, such as a simple date (June 26th 2015) and an instant in time (June 26th 2015 at 10am UTC) - there isn't a class for the former concept
    • The new Time API has a clear separation between the various date/time concepts
  • safety:
    • The Calendar API is not safe: nothing prevents you from writing cal.set(123, 2) which would throw a not-so-helpful ArrayOutOfBoundsException. The new API uses enums which solves that problem.
    • The new API uses immutable objects, which makes it thread safe.

Overall, the new API is significantly inspired from jodatime which has been the preferred Java Date API for quite some time now. You can also read this detailed comparison of Java (<1.8) date vs. JodaTime (most of it should apply to the Java 8 Date API).

참고 : http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html

2015/10/28 10:05 2015/10/28 10:05
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

crontab 설정

필요할때마다 검색하기 구찮아서 정리해 둠

crontab [ -e | -l | -r | -v | File ]
-e : 수정 -l : 내용보기 -r : 삭제 -v : 작업상태보기

>crontab -e #주석 15 3 * * *      /home/koglo.com/public_html/system/autoftp.sh              >       /dev/null 2>&1
minute(분) hour(시) day_of_month(일) month(월) weekday(요일) command(명령)
minute(분) 0 - 59 hour(시) 0 - 23 day_of_month(일) 1 - 31 month(월) 1 - 12 weekday(요일) 일요일부터 금요일까지를 나타내는 0 - 6 command(명령) 쉘 명령

> /dev/null 표준출력내용을 null로보낸다
명령 지정 cron 데몬은 선택된 날짜와 시간의 여섯 번째 필드에 지정된 명령을 수행합니다. 
여섯 번째 필드에 %(퍼센트 기호)를 포함하면, cron 데몬은 그 앞에 오는 모든 것을 명령 호출로서 취급하고, 퍼센트 기호(\%)를 탈출하지 않는 한 그 뒤에 오는 모든 것을 표준 입력에 사용 가능하게 만듭니다. 공백 행과 첫번째 비공백 문자가 번호 기호(#)인 행을 무시됩니다.

예제 
mycronjobs이라는 파일을 /var/admn/cron/crontabs 디렉토리에 복사하려면, 다음과 같이 입력하십시오. 
crontab mycronjobs 

매 시간마다 콘솔에 시간을 기록하려면, 다음과 같이 입력하십시오. 
0 * * * * echo The hour is `date` . >/dev/console 

모든 월요일, 수요일 및 금요일 오전 6시 30분에 calendar 명령을 수행하려면, 다음과 같이 입력하십시오. 
30 6 * * 1,3,5 /usr/bin/calendar 

일년 내내 매일 6시 30분에 calendar 명령을 수행하려면, 다음과 같이 입력하십시오. 
30 6 * * * /usr/bin/calendar 

8월 동안 매일 자정에 maintenance라는 스크립트를 수행하려면, 다음과 같이 입력하십시오. 
0 0 * 8 * /u/harry/bin/maintenance 

명령에 대한 표준 입력에 대해 텍스트를 정의하려면, 다음과 같이 입력하십시오. 
0 16 * 12 5 /usr/sbin/wall%HAPPY HOLIDAY!%Remember to turn in your time card. 

%(퍼센트 기호) 뒤에 오는 텍스트가 다음과 같이 wall 명령에 대한 표준 입력을 정의합니다. 
HAPPY HOLIDAY! Remember to turn in your time card. 
파일 
/var/adm/cron/FIFO crontab 또는 at 명령으로 새 작업이 제출될 때 cron 디먼으로 메세지를 전송하는 명명된 파이프. 
/var/spool/cron/crontabs crontab 스풀 영역을 지정합니다. 
/var/adm/cron/cron.allow  crontab 명령에 대한 액세스가 허용되는 사용자 리스트를 지정합니다. 
/var/adm/cron/cron.deny crontab 명령에 대한 액세스가 거부되는 사용자 리스트를 지정합니다

0,30 * 1,15 * 1-5 fsck -y 
상기의 예에서 보면 매달 1일과 15일날 30분마다 요일에 관계없이 fsck -y명령을 실행하도록 되어 있다.
(위의 예는 있을 수 없는 상황이겠지만 예로 들어본다.) 이러한 방식으로 명령어필드에 여러가지의 내용을 넣을 수 있다.

20 1 * * * root find /tmp -atime +3 -exec rm -f () ';' 
매일 새벽 1시 20분에 3일간 접근하지 않은 /tmp내의 파일을 삭제하는 내용 

0 4 * * * root find / -xdev -name core +7 -exec rm -f {}';' 
매일 새벽 4시 정각에 지난 일주일간 접근하지 않은 core파일들을 삭제한다. -xdev옵션은 독립형시스템이면 사용하지 않아도 된다.

수정하는 방법은 리눅스의 경우에는 crontab -e명령으로 에디팅을 할 수 있다. 
수정하기 전에 지금 등록된 crontab을 보고자 하면 -l옵션을 사용하고 등록된 내용을 삭제하려면 -d옵션을 사용하면 된다.(-r옵션을 사용하는 유닉스도 있다.) 
실행결과는 메일로 알려주게 되므로 자신의 메일을 읽어보면 된다.
CRON 메일 전송 차단을 원하면
MAILTO=""

crontab을 직접 고칠 수 없는 상황이면 crontab을 -l옵션을 사용하여 새로운 화일명으로 리다이렉션 받아서 편집한 뒤에 crontab filename의 형태로 등록하면 된다. 
리눅스의 경우에는 /var/spool/cron/crontabs/에 자신의 계정을 화일명으로 crontab이 존재하고 있다.
2015/10/23 09:37 2015/10/23 09:37
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

메이븐 레파지토리에 없는 jar 추가하고 manifest 에 기술하기

IBM DB2를 가지고 개발할 일이 생겼다.
늘 하던대로 executeable-jar 형식으로 빌딩을 수행하는 메이븐 프로젝트를 구성하는데.. 으잉? DB2의 jdbc 드라이버 db2jcc4.jar가 메이븐센트럴에 등록되어있지 않는것이다. 뭐지.. 이건?
회사 넥서스에 등록하고 땡겨쓰면 되긴 하지만 넥서스같은 로컬 메이븐 레파지토리가 없는 환경에서 이런경우는 어떻게 해야하는지 궁금했다.
귀찮겠지만 빌드하고 라이브러리 폴더에 jar를 복사해도 되긴하지만 문제는 POM파일에 기술되지 않으면 dependancy 관리가 안된다는것. 곧 IDE에서 클래스를 참조할 수 없다는 치명적인 문제가 발생한다.

이럴때를 대비해 메이븐은 dependencies.dependency.scope 속성 값으로 system을 제공하고 있고 <scope>system</scope> 를 사용한 경우 추가로 systemPath 속성을 정의할 수 있다.

이렇게 말이지..
[code xml]     <dependencies>
        <dependency>
            <groupId>ibm.db2</groupId>
            <artifactId>db2jcc4</artifactId>
            <version>10.5</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/db2jcc4.jar</systemPath>
        </dependency>
    </dependencies>
[/code]
이제, 코드를 짤 수 있고 라이브러리 참조도 된다. 그런데.. 문제가 하나 있는데 <scope>system</scope> 속성은 메이븐 빌드 시 <scope>provided</scope> 와 마찬가지로 라이브러리를 빌드 결과물에 포함시키기 않는다.
이 현상은 maven-dependency-plugin의 configuration 조정을 통해 우회할 수 있다.
plugins.plugin.executions.execution.configuration.includeScope 속성을 추가하고 그 값으로 system 을 설정한다.
[code xml]             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.10</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                            <includeScope>system</includeScope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>[/code]
이제 빌드를 수행하면 system 스코프로 설정된 db2jcc4.jar 가 /lib/db2jcc4-10.5.jar 란 이름으로 이쁘게 들어와 있는걸 확인할 수 있다.

나는 이 프로그램을 executeable-jar 로 뽑을거라서 maven-jar-plugin 을 사용한다. 그런데 빌드 후 jar 내부의 MENIFEST 파일을 까 보니 Class-Path 정의에 db2jcc4-10.5.jar 가 기술되어 있지 않다... maven-dependency-plugin을 통해 복사까진 어떻게 처리했는데 메니페스트를 만드는건 maven-jar-plugin 역할이니 당연한건지도 모르겠다.
이제 마지막으로 /lib/db2jcc4-10.5.jar 에 들어온 jar를 메니페스트의 class path에 꾸겨넣어보자.
 plugin.configuration.archive.manifestEntries.Class-Path 속성을 사용했다.

[code xml]    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <addExtensions>true</addExtensions> 
                    <mainClass>com.usbcopy.repository.DBProcess</mainClass>
                    <classpathPrefix>lib/</classpathPrefix>                            
                </manifest>
                <!--MANIFEST  with systemPath-->
                <manifestEntries>
                    <Class-Path>lib/db2jcc4-10.5.jar</Class-Path>
                </manifestEntries>
            </archive>
        </configuration>
    </plugin>[/code]
이제 빌드하고 java -jar app.jar 로 실행도 잘 된다.
2015/10/22 19:19 2015/10/22 19:19
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

java json 라이브러리 별 parser 속도 비교.

우선, 테스트 진행한 json 라이브러리 후보군은
  • JSON.simple ( Yidong Fang )
  • GSON ( Google )
  • Jackson ( FasterXML )
  • JSONP  ( Oracle )
과 같음. 상기 라이브러리를 이용한 비교적 큰 사이즈의 json 문서 파싱 속도 벤치마킹 결과를 java 어플리케이션 성능평가/모니터링 도구를 개발하는 Takipi에서 공개.

벤치마크는 190MB 짜리( https://github.com/zeMirco/sf-city-lots-json )와 1KB 짜리( http://www.json-generator.com/ ) JSON 파일을 파싱하는 속도를 측정. AWS c3.large 인스턴스에서 큰 파일은 라이브러리당 10회 씩, 작은 파일은 10,000회 씩 수행한 결과를 정리했다고 함.

큰 파일 파싱
대용량 파일 처리 결과

이미지 출처 http://blog.takipi.com

큰 파일 파싱에는 Jackson과 Json.simple 이 빠르고 Jsonp와 gson이 상대적으로 느린걸로...

가장 빠른 Jakson 성능을 기준으로 나타낸 상대 수치.
Jackson 기준 상대 속도

이미지 출처 http://blog.takipi.com


작은 파일 파싱
작은 파일 파싱

이미지 출처 http://blog.takipi.com

큰 파일 때와는 다른 양상을 보임. 작은 파일일때는 정도의 차이는 있지만 모든 라이브러리들이 측정 때마다 들쑥날쑥한 결과를 보임.  GSON 이 1순위를 가장많이 나타내고 있고 Json.simple 은 1순위가 한번도 없음.

가장 빠른 GSON 성능을 기준으로 나타낸 상대 수치.
Gson 기준 상대 비교

이미지 출처 http://blog.takipi.com


결론.
  • 당신의 개발 환경이 빅데이터처리와 같이 주로 큰사이즈의 JSON을 처리해야한다면 Jackson 을 써라. 대용량 환경에서 GSON은 좋지않은 선택임.
  • 마이크로 서비스와 분산아키텍처 설정등과 같이 작은 용량의 많은 json 파일을 처리하는 환경이라면 GSON을 써라.
  • 대용량과 소용량 모두를 다양하게 처리하는 환경이라면 양쪽에서 2순위 정도를 기록한 JSON.simple 이 좋을수도 있겠다.
2015/10/20 10:19 2015/10/20 10:19
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다