Checkstyle 실행 시 다음과 같은 에러에 직면할 수 있다.


'+' should be on a new line. (172:21)


다음과 같은 설정 때문인데


        <module name="OperatorWrap">

            <property name="option" value="NL"/>

            <property name="tokens"

                      value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>

        </module>


인텔리제이 (IntelliJ)를 사용한다면,


toString() 생성 시 '+'가 라인의 끝에 위치하기 때문에


다음과 같이 설정하는 수밖에 없다.


        <module name="OperatorWrap">

            <property name="option" value="EOL"/>

            <property name="tokens"

                      value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>

        </module>


인텔리제이에서 toString() 생성 규칙을 변경할 수 있으면 될텐데 찾지 못했다.


References:

http://checkstyle.sourceforge.net/config_whitespace.html

http://checkstyle.sourceforge.net/property_types.html#wrapOp

Posted by izeye

댓글을 달아 주세요

Checkstyle 실행 시 다음과 같은 에러에 직면할 수 있다.


Abbreviation in name must contain no more than '1' capital letters. (12:0)


다음과 같이 allowedAbbreviations에 예외를 추가함으로써 해결할 수 있다.


        <module name="AbbreviationAsWordInName">

            <property name="ignoreFinal" value="false"/>

            <property name="allowedAbbreviationLength" value="1"/>

            <property name="allowedAbbreviations" value="IO"/>

        </module>


References:

http://checkstyle.sourceforge.net/config_naming.html

http://checkstyle.sourceforge.net/apidocs/com/puppycrawl/tools/checkstyle/checks/naming/AbbreviationAsWordInNameCheck.html

Posted by izeye

댓글을 달아 주세요

Checkstyle 실행 시 다음과 같은 에러에 직면할 수 있다.


Wrong lexicographical order for 'org.hamcrest.core.IsNot.not' import. (6:0)


import 문을 알파벳 (Alphabet) 순으로 정렬한다.


참고로 소문자가 대문자보다 앞으로 정렬해야만 한다.


Reference:

http://checkstyle.sourceforge.net/config_imports.html

Posted by izeye

댓글을 달아 주세요

Checkstyle 실행 시 다음과 같은 에러에 직면할 수 있다.


Import statement is in the wrong order. Should be in the 'STATIC' group. (5:0)


다음과 같은 설정 때문이다.


        <module name="CustomImportOrder">

            ...

            <property name="customImportOrderRules"

                      value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>

        </module>


import static 구문을 상단에 위치시키면 된다.


Reference:

http://checkstyle.sourceforge.net/config_imports.html

Posted by izeye

댓글을 달아 주세요

Checkstyle 실행 시 다음과 같은 에러에 직면할 수 있다.


Line contains a tab character. (14:1)


다음은 파일 내 탭 (Tab) 문자를 허용하지 않는 옵션이다.


    <module name="FileTabCharacter">

        <property name="eachLine" value="true"/>

    </module>


이를 제거한다.


Reference:

http://checkstyle.sf.net/config_whitespace.html

Posted by izeye

댓글을 달아 주세요

톰캣에 오래 걸리는 요청 발생 시 쓰레드가 필요 이상으로 증가한다.


오래 걸리는 요청이 한 쓰레드를 점유하고 있으면 20개 이상 증가시키고,


다른 오래 걸리는 요청이 다른 한 쓰레드를 점유하고 있으면 또 20개 이상 증가시키고,


그런 식으로 동작하다가 갑자기 폭주해서 최대 개수에 도달한다.


-----


다시 확인하니 톰캣 문제가 아니라


오래 걸리는 요청이 부하가 커서 다른 톰캣 쓰레드들에도 영향을 줬기 때문이었다.


그로 인해 순간적으로 다른 톰캣 쓰레드들이 동시에 Running인 상태가 되어


톰캣 입장에서는 쓰레드를 증가시키는 것이 당연한 상황이었다.


References:

http://tomcat.apache.org/tomcat-7.0-doc/config/executor.html

http://stackoverflow.com/questions/26378981/when-does-tomcat-increase-the-number-of-threads

Posted by izeye

댓글을 달아 주세요

아파치를 톰캣의 Reverse Proxy 설정 시 X-Forwarded-For 헤더가 나타나지 않아 삽질했다 ㅠㅠ


다음과 같이 하면,


    @RequestMapping("/headers")

    public void headers(HttpServletRequest request) {

        for (String headerName : Collections.list(request.getHeaderNames())) {

            log.debug("{}: {}", headerName, request.getHeader(headerName));

        }

    }


x-forwarded-host 헤더와 x-forwarded-server 헤더는 있지만, x-forwarded-for 헤더는 없었다.


아파치에서 x-forwarded-for를 제공하는 것이 mod_proxy_http 모듈 (Module)이니


configure 시 --enable-proxy=shared뿐만 아니라


--enable-proxy-http=shared도 해야하나 해서 했으나 소용없었다.


x-forwarded-host 헤더와 x-forwarded-server 헤더가 이미 제공되고 있었으니


이미 활성화됐던 상태였다.


아파치 설정 문제로 국한시켜 삽질하니 답이 보이질 않았다.


혹시나 해서 다음과 같이 tcpdump로 출력해보니 X-Forwarded-For 헤더가 전달되고 있었다.


sudo /usr/sbin/tcpdump -vvX -i lo "dst port 8080"


결국 톰캣이 먹고 있었던 것이었다.


혹시나 해서 HttpServletRequest 객체의 getRemoteAddr() 메소드를 호출하니


X-Forwarded-For 헤더에 포함된 클라이언트 (Client) IP 주소 (Address)를 반환했다.


이것이 톰캣의 기본 동작인지


스프링 부트 (Spring Boot)의 임베디드 (Embedded) 톰캣의 설정인지는 확인해보지는 않았다.


아마도 스프링 부트?


-----


스프링 부트의 기본 설정인데 1.1.7부터 제거되어 유지하려면,


application.properties에 다음과 같이 명시적으로 설정해줘야만 한다.


server.tomcat.remote_ip_header=x-forwarded-for

server.tomcat.protocol_header=x-forwarded-protocol


References:

http://stackoverflow.com/questions/5610822/convert-enumeration-to-a-set-list

http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

http://httpd.apache.org/docs/2.2/programs/configure.html

http://stackoverflow.com/questions/3130911/tcpdump-localhost-to-localhost

http://www.rackspace.com/knowledge_center/article/capturing-packets-with-tcpdump

http://expert-mode.blogspot.kr/2011/09/tcpdump-how-to-capture-full-packet.html

https://github.com/spring-projects/spring-boot/issues/1631

Posted by izeye

댓글을 달아 주세요

자바 (Java) 8에서 다음과 같이 사용하면,


        Instant instant = new Date().toInstant();

        System.out.println(instant);


        String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(instant);

        System.out.println(formatted);


다음과 같은 예외 (Exception)에 직면한다.


java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year


Instant 객체에는 Year 정보가 없기 때문이다.


Year 정보를 포함하는 LocalDateTime 객체를 다음과 같이 생성하려고 하면,


        Instant instant = new Date().toInstant();

        System.out.println(instant);


        LocalDateTime localDateTime = LocalDateTime.from(instant);

        String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(localDateTime);

        System.out.println(formatted);


다음과 같은 예외에 직면한다.


java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2014-09-02T10:05:09.766Z of type java.time.Instant


시간 대 (Time Zone) 정보가 없기 때문이다.


다음과 같이 사용하면 된다.


        Instant instant = new Date().toInstant();

        System.out.println(instant);


        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

        String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(localDateTime);

        System.out.println(formatted);


        formatted = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        System.out.println(formatted);


References:

http://docs.oracle.com/javase/tutorial/datetime/iso/instant.html

http://stackoverflow.com/questions/25561377/format-localdatetime-with-timezone-in-java8

Posted by izeye

댓글을 달아 주세요

JSON을 객체 (Object)로 변환하려고 할 때 다음과 같은 예외에 직면할 수 있다.


Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class ...]: can not instantiate from JSON object (need to add/enable type information?)

 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c4f21; line: 1, column: 2]


디폴트 생성자 (Default Constructor)가 있는지 확인한다.

Posted by izeye

댓글을 달아 주세요

RabbitMQ 사용 시 다음과 같은 예외에 직면할 수 있다.


Caused by: java.net.SocketException: Connection reset


/var/log/rabbitmq/rabbit\@xxx.log 파일의 내용을 보면,


다음과 같이 접속은 된 것으로 보인다.


accepting AMQP connection <0.295.0> (1.2.3.4:1234 -> 2.3.4.5:2345)


사용자 (User)를 추가 (Add)하고,


권한 (Permission)을 설정하지 않은 경우에 발생할 수 있다.


다음과 같이 권한 목록을 확인한다.


$ /usr/lib/rabbitmq/bin/rabbitmqctl list_permissions

Listing permissions in vhost "/" ...

guest   .*      .*      .*

...done.

$


다음과 같이 권한을 추가한다.


/usr/lib/rabbitmq/bin/rabbitmqctl set_permissions izeye ".*" ".*" ".*"


Reference:

http://www.rabbitmq.com/man/rabbitmqctl.1.man.html

Posted by izeye

댓글을 달아 주세요