반응형

 

 안녕하세요. 오늘은 간단하게 자바 EXCEPTION처리시  EXCEPTION이 처리되는 우선순위에 대한 궁금증이 생겨 확인한 내용 간단히 공유해봅니다. 포스팅을 너무 장황하게 하려하니 글쓰는 수도 줄어들고 해서 앞으로는 간단히라도 자주 기록을 남기는 습관을 들이려합니다:)


상 황 ]

 2개의 exceptionHandler 클래스가 있고 범위는 다음과 같다.  

 

1번 - @ControllerAdvice("com.nhnent.webcc")       (프로젝트 전체 패키지)          

  -   (2번이 1번에 완전 귀속)   - 

2번 - @ControllerAdvice("com.nhnent.webcc.controller.api")  (API 관련 패키지) 


 

[ 궁금증 ]

2번 패키지 범위의 클래스에서 1번 범위의 메서드 실행하다가 에러가 발생할 경우 1번 handler에서 처리가 될지 2번 handler에서 처리가 될지?


예측이 되시나요? ㅎㅎ

 

동작확인  ]

실제로 1번 범위의 클래스에서 exception이 발생했을지라도 ExceptionHandlerExceptionResolver에 의해 메서드를 호출한 상위

클래스를 찾아가게 되고 그 클래스내에서 exception이 발생하게 된다. 따라서 2번 handler에 의해서 exception이 처리되게 된다.

 

궁금하시거나 잘못된 부분이 있다면 코멘트 부탁드립니다.




오늘도 좋은하루보내세요:)

 



반응형
반응형


 안녕하세요. 오늘은 ZIP파일 안의 파일 중 한글명으로 된 파일이 있을 경우 해당 파일에 접근하지 못하는 문제를 COMMONS COMPRESS라이브러리를 통해 해결한 방법을 공유하도록 하겠습니다. 최근 작업 중에 고객들이 넣는 문의들 중 파일 첨부된 ZIP 파일의 경우 해당 ZIP파일 내에 .exe파일이 있는지 확인해 인입이 안되도록 처리해야 하는 작업이 있었습니다. 처음엔 COMMONS COMPRESS를 사용하지 않고 ZIP파일내의 파일들의 확장자를 확인하는 방법으로 작업하였습니다. 작업 후 테스트 결과 ZIP 파일 내에 한글명으로 된 파일이 있을 경우 제대로 파일내의 ZIPENTRY에 접근을 하지 못하는 문제점을 발견할 수 있었습니다. COMMONS COMPRESS 라이브러리를 통해 해결하였고 그 방법에 대해 포스팅하도록 하겠습니다.


[ 코 드 ]  

 


코드에서 보면 알겠지만 ZIP파일을 굳이 따로 디렉토리를 만들어 압축을 푼 후 체크하지 않고 ZipEntry를 통해 ZIP파일의 파일들에 접근하는 것을 볼 수 있다. 이렇게 JDK에서 지원하는 java.util.zip을 사용했을 경우 위에서 언급했던 대로 ZIP파일 내에 한글 파일 처리를 할 수 없는 문제가 발생합니다. 이를 해결하기 위한 방법으로는 jazzlib 및 commons-compress를 사용하는 방법이 있는데 jazzlib 같은 경우 라이브러리 자체도 상당히 오래 되었고 라이센스 문제가 발생할 수 있어 commons-compress를 사용하게 되었다. 



[ Commons Compress 적용 ]

먼저 메이븐 프로젝트이기 때문에 dependency를 추가해주었다. 

 


라이브러리를 추가 하고 다음과 같이 변경하였다.

 

다른 점은 ZipArchiveInputStream을 사용하여 인코딩 방식을 EUC-KR로 지정해 주었다. 수정 후 테스트를 해본 결과 ZIP파일 내에 한글명의 파일이 있을 경우에도 정확히 처리하는 것을 확인 할 수 있었다.



반응형
반응형

동시성 코드와 블로킹(blocking)콜 그리고 아카(akka)

여러 개의 스레드가 동시에 작업을 수행하더라도 synchronized 블록이나 데이터베이스, 네트워크 API 호출 등을 만날 다른 스레드와 나란히 줄을 서서 순차적으로 작업을 수행해야 하는 경우도 있다. 암달의 법칙은 프로그램이 있는 속도의 상한이 이런 순차적 코드가 사용하는 시간에 의해서 제한된다고 말한다. 이러한 순차적 코드의 다른 이름은 블로킹(blocking)콜이다. 조금 과장해서 말하자면 자바 개발자가 스레드를 이용해서 만들어내는 '동시성' 코드는 일종의 신기루다. 사실은 코드 곳곳에 존재하는 블로킹 , 순차적 코드 때문에 전체적인 프로그램의 처리율은 이미 상한이 정해져 있지만 여러개의 스레드가 '동시에' 동작한다는 사실로부터 위안을 받을 뿐이다.


아카(akka) 스칼라(scala)언어로 작성되었지만 아래로 내려가면 자바의 동시성 패키지를 사용하기 때문에 아카를 사용하는 것은 궁극적으로 자바의 Thread Task 사용하는 것과 마찬가지다. 하지만 아카를 사용하면 프로그램 곳곳에 존재하는 순차적 부분, 블로킹 콜을 전부 없애거나 최소한으로 만드는 것이 가능해진다. 아카(akka) 이용해서 프로그램을 설계하는 것은 블로킹 호출이 일어나는 지점을 논블로킹 호출로 전환하는 작업을 수행하는 것을 의미한다.



반응형
반응형

최근 자바 어플리케이션에서 hdfs파일을 local파일로 쓰는 외부 명령을 실행시켜야 하는 작업이 있었다.


Runtime 객체를 생성하고 exec 메소드를 이용하여 외부 명령을 실행시키는 프로세스를 생성하였다.


코드를 보면 알겠지만 command 명령에 파이프라인(|)이 사용되었다.


Runtime runtime = Runtime.getRuntime();

Process process = null;


String command = "hadoop fs -text /log/dmp_log/2017/09/19/dmp_log.*.1505786400000.gz | head -100"


process = runtime.exec(command);


이렇게 해서 동작을 시키니 100라인만 읽어와야하는데 해당 hdfs파일의 모든 로그를 읽어왔었다...


한참을 헤매다가 파이프라인(|)이 안먹는다는 생각이 들었고 찾아보니 문제가 있었다.


파이프라인(|)을 사용하는 것은 shell 실행 후 또 다른 프로세스로 실행하기 때문에 정상적으로 작동을 안한 것이다.


다음과 같이 해결을 하면 된다.


String commandHdfs = "hadoop fs -text /log/dmp_log/" + date + "/dmp_log.*." + unixTime + "000.gz | head -150";


String[] command = {

      "/bin/sh",

      "-c",

     commandHdfs

};


[ stack overflow 참고 ]

https://stackoverflow.com/questions/5928225/how-to-make-pipes-work-with-runtime-exec


간단히 요약하자면, 자바 어플레케이션에서 exec로 실행하는 system command는 실제로 unix, linux의 shell을 불러와 명령을 실행시키는게 아니라고하네요.


그렇기 때문에 쉘의 기능(shell feature)인 pipeline (파이프라인)을 사용하기 위해서는 명시적으로 shell(/bin/sh)을 불러주고 


해당 쉘 안에서 command를 실행시켜야 한다고 합니다.


더 정확한 원인을 알고 싶다면 참고부탁드려요

https://alvinalexander.com/java/java-exec-system-command-pipeline-pipe

반응형
반응형

쉘 스크립트를 사용하다보면 스크립트 중간에 그 다음 로직으로 넘어가기전 특정 시간동안 멈추고 싶을 경우가 있다.


그럴 경우 다음과 같이 원하는 시간만큼 간편히 sleep 시킬 수 있다.


[ shell script 간편 sleep 포맷 ]

sleep .5 # Waits 0.5 second.

sleep 5  # Waits 5 seconds.

sleep 5s # Waits 5 seconds.

sleep 5m # Waits 5 minutes.

sleep 5h # Waits 5 hours.

sleep 5d # Waits 5 days.


반응형
반응형

특정 포트의 프로세스를 죽이고 싶을 때 사용


특정 포트를 사용하는 프로세스를 찾고 싶을 때

lsof (list open file)을 나타내며, 

시스템에서 열린 파일 목록을 알려주고 사용하는 프로세스, 디바이스 정보, 파일의 종류등 상세한 정보를 출력해준다.

lsof -n -i4TCP:8080(원하는 port)


lsof 명령이 안먹힌다면 netstat

netstat -anp | grep LISTEN | grep :포트번호

> tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2542/java


뒤에 2542가 프로세스ID이다.



[ lsof 실행결과 ]

COMMAND  PID   USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME

java    6079 irteam   70r  IPv6 197862007      0t0  TCP 172.20.0.5:webcache->10.161.240.88:35522 (ESTABLISHED)


PID를 찾아서


kill -9 PID(6079)


생각보다 서버운영시 필요할때가 많기 때문에 되도록이면 외우도록 하자~!

반응형
반응형

스프링부트(springboot)로 카산드라 데이터 모니터링 하는 프로젝트 작업 중  java.lang.NoClassDefFoundError:org/springframework/data/cassandra/mapping/UserTypeResolver 과 같은 에러가 발생해 한참을 해맸다.



Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/data/cassandra/mapping/UserTypeResolver

at java.lang.Class.getDeclaredMethods0(Native Method)

at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)

.

.

생략

Caused by: java.lang.ClassNotFoundException: org.springframework.data.cassandra.mapping.UserTypeResolver

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)


일단 해결은 pom.xml 의 <parent>부분의 버전을 수정하여 해결하였다.

<parent>

         <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.6.RELEASE</version>

        <!-- <version>1.2.3.RELEASE</version> -->

              <relativePath/> <!-- lookup parent from repository -->

</parent>


버전의 1.5.6버전을 하위 dependency에서 사용하는 스프링부트 버전과 맞춰주니 해결되었다. (1.5.6-> 1.2.3)


<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

<spring-boot.version>1.2.3.RELEASE</spring-boot.version>

<spring-data-cassandra.version>1.2.0.RELEASE</spring-data-cassandra.version>

<spring-cql.version>1.2.0.RELEASE</spring-cql.version>

<datastax.cassandra.version>2.1.7</datastax.cassandra.version>

</properties>


버전이 맞지않으면 예상치 못한 예외가 발생한다. 디텍팅하기도 너무 힘들뿐도로 원인파악이 너무 힘들기 때문에 메이븐 설정을 다른 프로젝트 등에서 가져다 


사용 할때는 버전을 꼭 참고하여 사용하도록 하자. 무작정 사용하는 ctrl+c, ctrl+v는 재앙을 가져올지니...

반응형
반응형

리눅스(Linux) 페이지 캐시


리눅스는 파일 I/O의 성능 향상을 위해 페이지 캐시라는 메모리 영역을 만들어서 사용한다.


한 번 읽은 파일의 내용을 페이지 캐시라는 영역에 저장 시켜 놨다가 다시 한 번 동일한 파일 접근이 일어나면 디스크에서 


읽지 않고 페이지 캐시에서 읽어서 제공해 주는 방식.


free -k 명령으로 파일을 읽기전 cached 영역과 cat으로 파일을 읽은 후 free -k 명령으로 확인해 볼 수 있다.



반응형
반응형

vi 로 파일을 열었을 때 파일의 마지막 줄이 개행문자로 끝나지 않았을  경우 콘솔 하단에 파일이름 옆 [noeol]이라고 적혀있는 것을 볼 수 있다.


해당 문제를 해결하기 위해서 다음 명령어를 실행해준다.


echo "" >> fileName




반응형

+ Recent posts