Docker Kafka 설치

|

메시지큐 플랫폼중 Kafka를 Docker에 올려 사용하려고 가장 간단하고 쉬운 방법으로 할 수 있는 설치방법을 찾다가 정리합니다.
물론 Kafka 자체가 설치하고 실행하는게 간단하긴 하지만 개발하면서 Desktop을 어지르기 싫은 마음에 Docker에 올립니다.
정확한 설명은 wurstmeister/kafka-docker를 참고하세요 :)
위 이미지는 Docker kafka 이미지중 가장 많은 사람들이 쓰고 있습니다.

$ docker search kafka

NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
wurstmeister/kafkva               Multi-Broker Apache Kafka Image                 383                  [OK]
spotify/kafka                    A simple docker image with both Kafka and ...   217                  [OK]
ches/kafka                       Apache Kafka. Tagged versions. JMX. Cluste...   81                   [OK]
sheepkiller/kafka-manager        kafka-manager                                   73                   [OK]
confluent/kafka                                                                  26                   [OK]

기본 설치

1. docker, docker-compose

Windows나 Mac에서 Docker, Docker Toolbox를 설치했을 경우 기본적으로 docker-compose도 같이 설치 됩니다.
특정 버전에서는 docker-compose가 설치되어 있지 않을수 있으니 Install Docker Compose를 참고하세요.

$ docker --version          // docker version check
$ docker-compose --version  // docker-compose version check

2. git

git저장소에 쓰기 쉽게 만들어놓은 compose 설정파일을 다운로드 받기 위해 설치합니다. Git download

설정 다운로드

docker-compose 설정을 사용하기 위해 다음과 같이 Git Repository에서 clone해 옵니다.

$ git clone "https://github.com/wurstmeister/kafka-docker.git"

docker-compose.yml 수정

docker-compose를 실행하기 전에 설치할 HOST 주소를 바꿔주어야 하는데 설정은 아래와 같습니다.

// docker-compose.yml
KAFKA_ADVERTISED_HOST_NAME: [[HOST주소]]

windows / docker-toolbox를 사용할 경우 docker-machine을 사용하기 때문에 아래 명령어를 통해 machine의 IP를 적어주어야 합니다.

$ docker-machine ip [machine name]

mac의 경우 그냥 로컬IP를 적어주면 됩니다.

docker-compose 실행

아래 명령어를 통해 docker-compose를 실행합니다.

$ docker-compose up -d

위 명령어의 경우 kafka cluster를 구성하는 케이스로 단일 Broker를 사용할 경우에는 아래와 같이 사용 할 수 있습니다.
$ docker-compose -f docker-compose-single-broker.yml up -d

실행하면 자동으로 이미지를 다운받고 컨테이너를 만들어 kafka와 zookeeper를 실행해줍니다.

$ docker-compose up -d

.
.
.

Creating kafkadockergit_zookeeper_1 ... 
Creating kafkadockergit_kafka_1 ... 
Creating kafkadockergit_zookeeper_1
Creating kafkadockergit_zookeeper_1 ... done

$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                       PORTS                                                NAMES
380d9569c130        kafkadockergit_kafka      "start-kafka.sh"         3 minutes ago       Up 3 minutes                 0.0.0.0:32769->9092/tcp                              kafkadockergit_kafka_1
b573f7d7c39b        wurstmeister/zookeeper    "/bin/sh -c '/usr/..."   3 minutes ago       Up 3 minutes                 22/tcp, 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp   kafkadockergit_zookeeper_1

제가 테스트 했을 때는 위 docker-compose명령어로 올릴 경우 가끔 zookeeper나 kafka모듈이 하나 죽거나 잘못 뜰떄가 있었습니다.
원인은 알지 모르겠고 각 모듈을 재시작 할 경우 정상작동함을 확인했습니다. 원인 아시는분은 댓글 부탁드려요 :)

참고

wurstmeister/kafka-docker

(Lombok) @Slf4j 사용하기

|

클래스를 생성할 때마다 항상 로그를 남기기 위해 Logger 변수를 선언해야 했는데 Lombok의 @Slf4j 어노테이션을 사용하면 편하게 사용할 수 있습니다.
(lombok은 쓰면 쓸 수록 편해서 헤어나올수가 없는거 같습니다.)

@Slf4j어노테이션 사용시 변환되는 코드는 아래와 같습니다.

// source
@Slf4j
public class LogExample {
}
// generate
public class LogExample {
     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
}

참고

Annotation Type Slf4j

org.springframework.data.mapping.PropertyReferenceException: No property undefined found for type

|

원인

SpringBoot + JPA 환경에서 작업을 하다가 아래와 같은 에러를 만났습니다.

org.springframework.data.mapping.PropertyReferenceException: No property undefined found for type PartnerPaymentRefundInfo!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243)
at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:542)

JPA 작업을 하기 전까지는 오류가 안나길래 JPA설정 문제인가 하고 헤매다보니 원인은 다른곳에 있었습니다.

결론

Controller에서 인자값으로 Pageable 정보를 받아와 JPA Repository에 넘겨 조회를 하는데 아래와 같이 넘기는 값중에 undefined가 있었습니다.

http://localhost/api?page=0&size=15&sort=undefined%2Casc

Controller에서 다른 작업실행시에는 별 탈이 없다가 JPA Repository에서 쿼리시 Pageable의 sort변수에 undefined를 파싱하지 못해 오류가 발생한 케이스입니다.

List 생성방식과 주의점

|

일반적으로 List를 생성시 아래와 같이 합니다.

방법 1

List list = new ArrayList();
list.add(1);
list.add(2);

방법 2

List객체를 만드는 또 다른 방법은 아래와 같이 생성시 enclosing scope에서 초기화를 같이 해주는 방법입니다.

List list = new ArrayList(){
  {
      add(1); 
      add(2);
      add(3);
  }
};

방법 3

위 1,2번 방법으로 생성할 경우 코드 라인수가 길어지기 때문에 Arrays.asList(T... a)를 이용하는 경우가 있습니다.

List list = Arrays.asList(1,2,3,4);

코드라인은 확실히 짧아지지만 위 코드는 조심히 사용해야합니다.
Arrays.asList는 배열을 wrapping하여 Collection처럼 사용할 수 있게 해주지만 리스트 길이를 고정 시켜버리기 때문에 단순 조회가 아닌 객체 데이터를 변경시키는 작업(remove, add, set … )을 시도시 아래와 같은 오류를 만날수도 있습니다.

java.lang.UnsupportedOperationException: null

위와 같은 방식으로 List객체를 자유롭게 쓰려면 아래와 같이 ArrayList객체를 생성하고 인자로 넣어 사용해야합니다.

List list = new ArrayList(Arrays.asList(1,2,3,4));

참고

remove() on List created by Arrays.asList() throws UnsupportedOperationException

(Thymeleaf)placeholder 줄바꿈 방법

|

placeholder 에서 줄바꿈 방법

placeholder 속성에 &#13;&#10;을 추가해주면 됩니다.

<textarea style="height:50px;" placeholder="안녕하세요. 방갑습니다."></textarea><br/>
<textarea style="height:50px;"  placeholder="안녕하세요.&#13;&#10;방갑습니다."></textarea>

thymeleaf 사용시 placeholder에서 줄바꿈 방법

thymeleaf의 th:placeholder를 사용할 경우 &#13;&#10;와 같은 특수문자가 그대로 노출됩니다. 이 때는 유니코드를 통 &#13;&#10;대신 \u000D\u000A를 사용하여 줄바꿈을 할 수 있습니다.

<textarea style="height:50px;"  th:placeholder="안녕하세요.\u000D\u000A방갑습니다."></textarea>