반응형

Java NanoTime To Seconds


보통 특정 메서드를 실행하거나 로직을 수행할 때 시간이 얼마나 걸리는지 측정(성능측정)하기 위해서 nanotime을 자주사용한다.

long start = System.nanoTime();


하지만 나노타임(nanotime)은 우리가 보고 판단하기에는 너무 어렵다...초로 바꿔보자...


자바에서 nanotime을 second(초)로 변환하는 방법은 두 가지이다.


1. TimeUnit.SECONDS.convert(nanotime, TimeUnit.NANOSECONDS을 이용하는 방법


이 방법은 진짜 딱 초단위 까지만 나오게 된다. 11.035초의 시간이 걸렸더라도 딱 11초만 표기된다.


2.((double) nanotime) / 1000000000; 을 사용하는 방법


이 방법은 11.33599 형태로 double형 단위에 맞는 초단위로 표기된다.



반응형
반응형


웹 작업을 할 때 jsp내의 문구라던지 구조를 변경하고 확인해야하는데 실시간으로 반영이 안되면 무척이나 성가시지요...


빌드다시해줘야하고.....시간은 시간대로 잡아먹고...


SpringBoot를 쓰고 계신다면 application.properties에 다음과 같이 추가해 주세요.


server.jsp-servlet.init-parameters.development=true


추가 이후에는 어플리케이션 재시작 없이 바로 웹에 반영되는 것을 확인할수 있다.

반응형
반응형


다른 도메인 내부에 쿠키 생성하기 (이게 가능해???)


최근 쿠키매칭시스템 설계를 위해 광고 프로세스 전반에 대한 내용을 학습중 우리 도메인 쿠키 내부에 


다른 도메인 쿠키값들이 박혀있는 걸 발견하였다.


뭐야 이거 어떻게 박는거야? 크로스도메인 이슈 때문에 당연히 안될거라고 생각했었는데 심지어 여러 도메인들 쿠키값들이 박혀있었다....


위의 캡쳐화면을 보면 cloud.toast.com 페이지에 들어갔는데 toast.com쿠키 내부를 보면 .toast.com말고도 여러 도메인들의 


쿠키값들이 설정되어있는 것을 보았다.


어떻게 이게 가능하단 말인가????


근데 가능하다는거....실제로 구현을 해보고서도 좀 신기하긴했다...




방법은 다음과 같다. 


해당 페이지의 html에 다른 도메인을 호출하는 호출하는 태그를 심는다. 이 때 태그는 <img>, <a> 태그가 가능하다.


다음을 보자.


local.media.com(내가 호스트에 등록해 띄운 페이지) 도메인의 페이지 내부에는 다음과 같은 태그를 박았다.


이렇게 박았을 경우 페이지가 렌더링되는 시점에 해당 도메인의 서버에 요청이 가게 된다.


요청을 받은 해당 도메인의 서버에서 요청을 받아 내부에서 쿠키를 생성하면 다른 도메인 쿠키 내부에 본인들의 쿠키값을 설정할 수 있는 것이다.


local.toast.com:8082/dsp/request 컨트롤러에서 요청을 쿠키를 만들어주게 되면




내가 생성한 쿠키 값이 박히는걸 볼 수 있다.


만약 다른 도메인의 iframe을 박아 렌더링 하게 된다면 해당 도메인의 쿠키가 하나 더 생기게 된다.


iframe으로 local.doubleclick.com:8080/adx/request를 요청해보자


이번에는 local.media.com쿠키 내부에 값이 생성되는게 아니고 별도의 local.doubleclick.com쿠키가 생성된 것을 볼 수 있다.


물론 어떻게 쿠키를 심든간에 httpServletRequest로 request를 받아 cookie를 얻어오게되도 본인 


서브도메인에 일치하는 쿠키값만 받아올 수 있다!!!(당연당연)


반응형
반응형

스프링부트(Springboot) 사용시 java.lang.IllegalArgumentException: An invalid domain Error 해결하기


스프링에서 쿠키에 setDomain을 할 경우 현재 서버의 도메인 및 상위 도메인 외에 다른 도메인을 셋팅하게 되면 에러가 발생한다.


서버 도메인이 test.com인데 다음과 같이 쿠키에 setDomain을 하게되면


cookie.setDomain(".toast.com");


다음과 같은 에러가 발생한다.


java.lang.IllegalArgumentException: An invalid domain [.toast.com] was specified for this cookie

at org.apache.tomcat.util.http.Rfc6265CookieProcessor.validateDomain(Rfc6265CookieProcessor.java:183)

at org.apache.tomcat.util.http.Rfc6265CookieProcessor.generateHeader(Rfc6265CookieProcessor.java:125)

at org.apache.catalina.connector.Response.generateCookieString(Response.java:989)

at org.apache.catalina.connector.Response.addCookie(Response.java:937)

at org.apache.catalina.connector.ResponseFacade.addCookie(ResponseFacade.java:386)

at com.nhnent.demonaid.cms.CookieMatchingServiceController.getAdRequestFromMedia(CookieMatchingServiceController.java:80)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)

.

.

.



[ 원인 ] 


tomcat8 버전 이상에서는 Cookie Header를 파싱하는 기본 CookieProcessor가 RFC6265를 기반으로 하고 다음과 같은 속성을 같는다.

5.2.3.  The Domain Attribute

   If the attribute-name case-insensitively matches the string "Domain",
   the user agent MUST process the cookie-av as follows.

   If the attribute-value is empty, the behavior is undefined.  However,
   the user agent SHOULD ignore the cookie-av entirely.

   If the first character of the attribute-value string is %x2E ("."):

      Let cookie-domain be the attribute-value without the leading %x2E
      (".") character.

   Otherwise:

      Let cookie-domain be the entire attribute-value.

   Convert the cookie-domain to lower case.

   Append an attribute to the cookie-attribute-list with an attribute-
   name of Domain and an attribute-value of cookie-domain.


Domain값 맨 앞자리에 "."을 붙일 경우 "."을 제거하고 파싱하게 된다.


[ 해결 ]

SpringBoot를 사용하고 있는 경우(Embedded Tomcat) 다음과 같은 설정을 해주면 된다. 스프링부트 자바 config클래스에 넣어주면 된다.




[ reference ]

https://jistol.github.io/java/2017/08/30/tomcat8-invalid-domain/

http://hyunc87.tistory.com/34

반응형
반응형


스프링프로젝트에서 디버깅 모드를 실행하려고 했는데 다음과 같은 에러가 발생했다.


ERROR: transport error 202: gethostbyname: unknown host

ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)

JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debugInit.c:750]



일단 이런문제가 발생한다면 host파일을 체크해보도록 하자.



host파일에 로컬호스트가 주석처리되어 있다면 다음과 같은 문제가 발생할 수 있다.


확인해본 결과 역시나 '127.0.0.1 localhost' 에 주석처리가 되어있었다.


주석을 풀고 다시 실행시키면 정상작동한다!


반응형
반응형


작업 중 java.sql.SQLException: Before start of result set 오류가 발생하였다.



뭔가 하고 보니 소스코드에서 mysql에 질의를 던져 데이터를 가져와서 ResultSet에 담는데 ResultSet에서 데이터를 읽을 경우 cursor의 points를 첫 번째 로우에 맞추어주어야 한다.


즉, 결과값을 읽기전에 next() 메서드를 호출 후 사용 하여야 한다. 


[ 오류가 발생했던 소스코드 ] 




[ 문제 해결 소스코드 ] 



보다시피 result.next() 전에 result.getString()으로 값을 불러오려고 했을 때 문제가 발생했다.

result.next() while문 안으로 넣어서 해결~!

반응형
반응형

 

 안녕하세요. 오늘은 간단하게 자바 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파일 내에 한글명의 파일이 있을 경우에도 정확히 처리하는 것을 확인 할 수 있었다.



반응형
반응형

최근 자바 어플리케이션에서 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

반응형

+ Recent posts