1. 개요

Apache Camel 은 알려진 여러  엔터프라이즈 통합 패턴 을 구현하는 강력한 오픈 소스 통합 프레임워크 입니다.

일반적으로 Camel을 사용하여 메시지 라우팅 작업을 할 때 콘텐츠에 따라 메시지를 다르게 처리하는 방법이 필요합니다. 이를 위해 Camel은 EIP 패턴 모음에서 Content Based Router 라는 강력한 기능을 제공합니다 .

이 사용방법(예제)에서는 일부 조건에 따라 메시지를 라우팅할 수 있는 몇 가지 방법을 살펴보겠습니다.

2. 의존성

시작하는 데 필요한 것은 pom.xml 에 추가된 camel-spring-boot-starter 뿐입니다 .

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
     <artifactId>camel-spring-boot-starter</artifactId>
     <version>3.18.1</version>
</dependency>

그런 다음  pom.xml 에 camel-test-spring-junit5  의존성을  추가해야 합니다 .

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-test-spring-junit5</artifactId>
    <version>3.18.1</version>
</dependency>

이름에서 알 수 있듯이 이 의존성은 특히 단위 테스트를 위한 것입니다.

3. 간단한 Camel Spring Boot 애플리케이션 정의

이 사용방법(예제) 전체에서 예제의 초점은 간단한 Apache Camel Spring Boot 애플리케이션입니다.

이제 애플리케이션 진입점을 정의하여 시작하겠습니다.

@SpringBootApplication
public class ConditionalRoutingSpringApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConditionalRoutingSpringApplication.class, args);
    }
}

보시다시피 이것은 표준 Spring Boot 애플리케이션입니다.

4. 조건부 라우팅

빠르게 요약하면 Apache Camel의 경로 는 일반적으로 메시지를 소비하고 처리하는 Camel이 순서대로 실행하는 일련의 단계로 구성된 기본 빌딩 블록입니다.

예를 들어 경로는 일반적으로 디스크의 파일이나 메시지 Queue에서 소비자를 사용하여 메시지를 수신합니다. 그런 다음 Camel은 메시지를 처리하거나 다른 Endpoints으로 보내는 경로의 나머지 단계를 실행합니다.

의심할 여지 없이 우리는 어떤 사실을 기반으로 메시지를 조건부로 라우팅하는 방법을 원할 것입니다. 이를 위해 Camel은 선택구성 제공합니다 . 우리는 이것을 Java 의 if-else 문과 동일하다고 생각할 수 있습니다.

이를 염두에 두고 몇 가지 조건부 논리를 사용하여 첫 번째 경로를 만들어 보겠습니다.

5. 루트 만들기

이 예에서는 수신된 메시지 본문의 내용을 기반으로 일부 조건부 논리를 사용하여 기본 경로를 정의합니다.

@Component
public class ConditionalBodyRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        
        from("direct:start-conditional")
          .routeId("conditional-body-route")
          .choice()
            .when(body().contains("Baeldung"))
              .setBody(simple("Goodbye, Baeldung!"))
              .to("mock:result-body")
            .otherwise()
              .to("mock:result-body")
          .end();
    }
}

간단한 예에서 볼 수 있듯이 start-conditional 이라는 직접 Endpoints 에서 메시지를 사용하도록 경로를 구성합니다 .

이제 경로의 주요 부분을 살펴보겠습니다.

  • 먼저 choice() 메서드 를 사용하여 경로를 시작합니다. 이것은 Camel에게 다음 줄에 평가할 몇 가지 조건이 포함될 것임을 알려줍니다.
  • 다음으로 when() 메서드는 평가할 새 조건을 나타냅니다. 이 예제에서는 메시지 본문에 Baeldung 문자열이 포함되어 있는지 확인하기만 하면 됩니다. when 조건은 필요한 만큼 추가할 수 있습니다.
  • 우리의 경로를 마무리하기 위해, else() 메서드를 사용하여 이전 조건이 충족되지 않을 때 수행할 작업을 정의합니다.
  • 마지막으로 경로 는 선택 블록을 닫는 end() 메서드를 사용하여 종료됩니다.

요약하자면, 경로를 실행할 때 메시지 본문에 Baeldung 문자열이 포함되어 있으면 메시지 본문을 Goodbye, Baeldung! 결과를 result-body 라는 모의 Endpoints 으로 보냅니다 .

또는 원본 메시지를 모의 엔드포인트로 라우팅합니다.

6. 경로 테스트

마지막 섹션을 염두에 두고 경로가 어떻게 작동하는지 알아보기 위해 단위 테스트를 작성해 보겠습니다.

@SpringBootTest
@CamelSpringBootTest
class ConditionalBodyRouterUnitTest {

    @Autowired
    private ProducerTemplate template;

    @EndpointInject("mock:result-body")
    private MockEndpoint mock;

    @Test
    void whenSendBodyWithBaeldung_thenGoodbyeMessageReceivedSuccessfully() throws InterruptedException {
        mock.expectedBodiesReceived("Goodbye, Baeldung!");

        template.sendBody("direct:start-conditional", "Hello Baeldung Readers!");

        mock.assertIsSatisfied();
    }
}

보시다시피 테스트는 세 가지 간단한 단계로 구성됩니다.

  • 먼저 모의 엔드포인트가 주어진 메시지 본문을 수신할 것이라는 기대치를 설정해 보겠습니다.
  • 그런 다음 템플릿을 사용하여 direct:start-conditional 엔드포인트 에 메시지를 보냅니다  . 메시지 본문에 Baeldung 문자열이 포함되어 있는지 확인합니다.
  • 테스트를 마무리  하기 위해 assertIsSatisfied 메서드를 사용하여   모의 엔드포인트에 대한 초기 기대치가 충족되었는지 확인합니다.

이 테스트는 조건부 라우팅이 올바르게 작동하는지 확인합니다. 엄청난!

Camel 경로에 대한 신뢰할 수 있고 자체 포함된 단위 테스트 를 작성하는 방법에 대해 자세히 알아보려면 이전 사용방법(예제)를 참조하십시오 .

7. 다른 조건부 술어 만들기

지금까지 when 술어 를 작성하는 방법에 대한 한 가지 옵션 인 교환의 메시지 본문을 조사했습니다. 그러나 우리가 사용할 수 있는 몇 가지 다른 옵션이 있습니다.

예를 들어 주어진 메시지 헤더의 값을 검사하여 조건을 제어할 수도 있습니다.

@Component
public class ConditionalHeaderRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        
        from("direct:start-conditional-header")
            .routeId("conditional-header-route")
            .choice()
              .when(header("fruit").isEqualTo("Apple"))
                .setHeader("favourite", simple("Apples"))
                .to("mock:result")
              .otherwise()
                .setHeader("favourite", header("fruit"))
                .to("mock:result")
            .end();
    }
}

이번에 는 fruit라는 헤더의 값을 보기 위해 when 메서드를 수정했습니다. 우리의 when 조건에서 Camel이 제공 하는 간단한 언어 를 사용하는 것도 완벽하게 가능합니다 .

8. 자바빈으로 작업하기 

또한 술어에서 Java 메소드 호출의 결과를 사용하려는 경우 Camel Bean 언어 를 사용할 수도 있습니다.

먼저 부울을 반환하는 메서드를 포함하는 Java bean을 생성해야 합니다.

public class FruitBean {

    public static boolean isApple(Exchange exchange) {
        return "Apple".equals(exchange.getIn().getHeader("fruit"));
    }
}

여기에서 선택적으로 Exchange 를 인수로 추가하여 Camel이 Exchange 를 메서드에 자동으로 전달합니다.

그런 다음 when 블록 에서 FruitBean 을 사용할 수 있습니다.

@Component
public class ConditionalBeanRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        
        from("direct:start-conditional-bean")
            .routeId("conditional-bean-route")
            .choice()
              .when(method(FruitBean.class, "isApple"))
                .setHeader("favourite", simple("Apples"))
                .to("mock:result")
              .otherwise()
                .setHeader("favourite", header("fruit"))
                 .to("mock:result")
              .endChoice()
            .end();
    }
}

9. 결론

이 기사에서 우리는 경로의 특정 조건에 따라 메시지를 라우팅하는 방법을 배웠습니다. 먼저 메시지 본문을 검사하는 하나의 경로가 있는 간단한 Camel 애플리케이션을 만들었습니다.

그런 다음 메시지 헤더와 Java Bean을 사용하여 경로에 술어를 구축하는 몇 가지 다른 기술에 대해 배웠습니다.

언제나처럼 기사의 전체 소스 코드는  GitHub에서 확인할 수 있습니다 .

Generic footer banner