티스토리 뷰

실무에서 elasticsearch 와 연동해야 할 일이 생겼다.

검색을 통해서 알아보니 Spring Data 프로젝트 하위에 Spring Data Elasticsearch 프로젝트가 존재했다.

https://github.com/spring-projects/spring-data-elasticsearch

그 외에 Elasticsearch와 연동 가능한 Java API가 있었지만 Spring Boot를 사용하고 있어 Spring Data를 선택하게 되었다.

선택 이유는 Spring Boot + Spring Data Elasticsearch 통합이 쉽기 때문이다.

      

일단 ElasticSearch와 연동하기 위해선 설치 작업이 선행되어야 한다.

개발 환경이 윈도우라서 난 윈도우 버전을 설치했다.

다른 환경이라고 해서 딱히 설치 과정이 복잡하지 않다. 그저 바이너리 다운로드 받고 압축을 푼 다음 실행만 하면 된다.

설치 방법 : http://lng1982.tistory.com/283


설치가 완료되고 Elasticsearch 서버가 구동되었다면 Spring Data Elasticsearch 셋팅을 해보자.


pom.xml 파일에 dependency 추가해 준다.

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
cs


모델을 생성하자.

indexName에 추가되어 있는 nklee는 RDB관점에서 봤을 때 데이터베이스와 유사하다.

type은 테이블과 유사하다.

1
2
3
4
5
6
7
8
9
10
11
12
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@lombok.ToString
@Document(indexName = "nklee", type = "phone")
public class Phone {
    @Id
    private int id;
    private String number;
    private String author;
}
cs


Repository를 생성하자.

이 구조 낯이 익다.

Spring Data JPA 도 이와같이 Repository 인터페이스를 상속하는데 Spring Data Elasticsearch 또한 유사하다.

아마도 Spring Data 프로젝트의 모든 서브 프로젝트들이 이와 같은 concept으로 되어 있지 않을까?

1
2
3
4
public interface PhoneRepository extends ElasticsearchCrudRepository<Phone, Integer> {
    Page<Phone> findByAuthor(String author, Pageable pageable);
    List<Phone> findByNumber(String number);
}
cs


Service를 생성하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Service
public class PhoneService {
 
    @Autowired
    private PhoneRepository phoneRepository;
 
    public Phone save(Phone phone) {
        return phoneRepository.save(phone);
    }
 
    public void delete(Phone phone) {
        phoneRepository.delete(phone);
    }
 
    public Phone findOne(Integer id) {
        return phoneRepository.findOne(id);
    }
 
    public Iterable<Phone> findAll() {
        return phoneRepository.findAll();
    }
 
    public Page<Phone> findByAuthor(String author, PageRequest pageRequest) {
        return phoneRepository.findByAuthor(author, pageRequest);
    }
 
    public List<Phone> findByNumber(String number) {
        return phoneRepository.findByNumber(number);
    }
}
cs


이제 Elasticsearch 서버와 연동하기 위한 ElasticsearchTemplate 설정을 해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Configuration
@EnableElasticsearchRepositories
class EsConfig {
 
    @Value("${elasticsearch.host}")
    private String EsHost;
 
    @Value("${elasticsearch.port}")
    private int EsPort;
 
    @Value("${elasticsearch.clustername}")
    private String EsClusterName;
 
    @Bean
    public Client client() throws Exception {
        Settings esSettings = Settings.settingsBuilder()
                .put("cluster.name", EsClusterName)
                .build();
        
        return TransportClient.builder()
                .settings(esSettings)
                .build()
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(EsHost), EsPort));
    }
 
    @Bean
    public ElasticsearchOperations elasticsearchTemplate() throws Exception {
        return new ElasticsearchTemplate(client());
    }
}
cs


application.properties

1
2
3
4
elasticsearch.clustername=my-application
elasticsearch.host=localhost
elasticsearch.port=9300
logging.config=classpath:logback-spring.xml
cs

나는 클러스터 이름을 my-application 이라고 했다.

Elasticsearch 서버의 config/elasticsearch.yml 파일에서 클러스터 이름을 지정할 수 있다.



이제 준비가 다 되었으니 테스트를 해보자.

Spring Data Elasticsearch를 사용하게 됨으로써 코드의 간결함을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void 데이터저장() {
    Phone phone = new Phone(1"010-1111-1111""nklee");
    Phone testPhone = phoneService.save(phone);
 
    assertNotNull(testPhone.getId());
    assertThat(testPhone.getNumber(), is(phone.getNumber()));
}
 
@Test
public void 조회() {
    Phone phone = new Phone(1"010-1111-1111""nklee");
    phoneService.save(phone);
 
    Phone testPhone = phoneService.findOne(1);
    assertNotNull(testPhone.getId());
    assertThat(testPhone.getNumber(), is(phone.getNumber()));
}
cs


전체 소스 코드는 Github에 올려놨다.

https://github.com/namkyu/test_spring_data


추가적으로 Spring Data Elasticsearch를 사용하기 위해서는 버전에 대해서 염두해야 한다.

Spring Data Elasticsearch 버전에 호환되는 Elasticsearch 서버가 존재한다는 의미이다.


내가 겪었던 문제에 대해서 적어본다.

Spring Data Elasticsearch를 이용해 Elasticsearch 서버와 연동을 하려고 하는데 아래와 같은 오류 메세지를 만났다.

1
org.elasticsearch.transport.ReceiveTimeoutTransportException: [][127.0.0.1:9200][cluster:monitor/nodes/liveness] request_id [0] timed out after [5001ms]
cs

확인해 보니 버전 오류로 발생되는 것이였다.

elasticsearch-5.5.2 버전을 구동하고 spring-data-elasticsearch 버전을 2.1.6.RELEASE 를 이용했기 때문이다.

현재 spring-data-elasticsearch 최신 2.1.6.RELEASE 버전은 Elasticsearch 5.x 버전을 지원하고 있지 않다. (2017-08-31)


[추가]

5.x 지원 가능한 spring-data-elasticsearch RC 버전이 최근에서야 추가된 것을 확인했다.



참고


지원 버전

https://github.com/spring-projects/spring-data-elasticsearch/wiki/Spring-Data-Elasticsearch---Spring-Boot---version-matrix


버전 관련 질문

https://stackoverflow.com/questions/42001828/does-spring-data-support-elasticsearch-5-x


Spring Data Elasticsearch 프로젝트

https://github.com/wonwoo/spring-boot-elasticsearch


Elasticsearch 기본 설명

http://d2.naver.com/helloworld/273788

https://iju707.gitbooks.io/elasticsearch/content/_introducing_the_query_language.html

https://github.com/spring-projects/spring-data-elasticsearch


예제 코드

https://examples.javacodegeeks.com/enterprise-java/spring/spring-data-elasticsearch-example/

https://www.mkyong.com/spring-boot/spring-boot-spring-data-elasticsearch-example/

http://www.mkyong.com/elasticsearch/elasticsearch-hello-world-example/

'[DEV] 프로그래밍' 카테고리의 다른 글

14. [JPA] Lock - 잠금  (0) 2017.09.20
13. [JPA] 트랜잭션 격리 수준 (Transaction Isolation Level)  (0) 2017.09.12
12. [JPA] 복합키  (0) 2017.09.08
11. [JPA] Querydsl  (0) 2017.09.01
spring data elasticsearch 사용해 보기  (6) 2017.08.31
10. [JPA] JPQL  (0) 2017.08.28
9. [JPA] @Enumerated  (0) 2017.08.23
8. [JPA] Attribute Converter  (0) 2017.08.23
7. [JPA] fetch type - 로딩 기법  (0) 2017.08.21
TAG
댓글
  • 프로필사진 방문자 좋은 글은 추천과 함께 하트와 도움될밀한거 클릭이죠. 해보진 않았지만, 집에가서 한번 시도 해보겠습니다. ^^ 2018.08.22 17:02
  • 프로필사진 규우82 감사합니다. ^^ 2018.12.13 10:37 신고
  • 프로필사진 와오 정리 쩐다 2018.12.12 16:06
  • 프로필사진 규우82 감사합니다. ^^ 2018.12.13 10:37 신고
  • 프로필사진 왕초보 =========================
    AUTO-CONFIGURATION REPORT
    =========================


    Positive matches:
    -----------------

    DispatcherServletAutoConfiguration matched:
    - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

    DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
    - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)

    DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched:
    - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    - DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition)

    DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration matched:
    - @ConditionalOnBean (names: dispatcherServlet; types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found beans 'dispatcherServlet', 'dispatcherServlet' (OnBeanCondition)

    ElasticsearchAutoConfiguration matched:
    - @ConditionalOnClass found required classes 'org.elasticsearch.client.Client', 'org.springframework.data.elasticsearch.client.TransportClientFactoryBean', 'org.springframework.data.elasticsearch.client.NodeClientFactoryBean'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

    ElasticsearchDataAutoConfiguration matched:
    - @ConditionalOnClass found required classes 'org.elasticsearch.client.Client', 'org.springframework.data.elasticsearch.core.ElasticsearchTemplate'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

    ElasticsearchDataAutoConfiguration#elasticsearchConverter matched:
    - @ConditionalOnMissingBean (types: org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; SearchStrategy: all) did not find any beans (OnBeanCondition)

    ElasticsearchDataAutoConfiguration#elasticsearchTemplate matched:
    - @ConditionalOnMissingBean (types: org.springframework.data.elasticsearch.core.ElasticsearchTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)

    ElasticsearchDataAutoConfiguration#mappingContext matched:
    - @ConditionalOnMissingBean (types: org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; SearchStrategy: all) did not find any beans (OnBeanCondition)

    EmbeddedServletContainerAutoConfiguration matched:
    - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

    EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat matched:
    - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.apache.catalina.startup.Tomcat'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    - @ConditionalOnMissingBean (types: org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; SearchStrategy: current) did not find any beans (OnBeanCondition)

    ErrorMvcAutoConfiguration matched:
    - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

    ErrorMvcAutoConfiguration#basicErrorController matched:
    - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)

    ErrorMvcAutoConfiguration#errorAttributes matched:
    - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorAttributes; SearchStrategy: current) did not find any beans (OnBeanCondition)

    등등

    Negative matches:
    -----------------

    ActiveMQAutoConfiguration:
    Did not match:
    - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

    AopAutoConfiguration:
    Did not match:
    - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

    ArtemisAutoConfiguration:
    Did not match:
    - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)

    BatchAutoConfiguration:
    Did not match:
    - @ConditionalOnClass did not find required classes 'org.springframework.batch.core.launch.JobLauncher', 'org.springframework.jdbc.core.JdbcOperations' (OnClassCondition)

    비슷하게 쭉 찍히는데 이유를 모르겠씁니다. ㅜㅜ
    2019.04.29 22:03
  • 프로필사진 규우82 Spring Boot Starter 디펜던시 등록 시 다른 것들이 포함되어 있지 않아서 발생되는 것 같은데요. 로그상에 오류가 대부분 class 파일을 찾지 못해서 발생하는 것들입니다.

    제가 아래 링크 드린 프로젝트를 참고하셔서 프로젝트 구성을 해보시겠어요.

    https://github.com/namkyu/test_spring_data/blob/master/pom.xml
    2019.04.30 11:50 신고
댓글쓰기 폼
공지사항
Total
2,688,635
Today
0
Yesterday
184
링크
«   2019/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
글 보관함